Merge with default

This commit is contained in:
Henrik Andersson
2011-06-01 14:59:09 +02:00
31 changed files with 1581 additions and 1187 deletions
+5 -5
View File
@@ -426,9 +426,9 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
{
vector<TimeSignatureSegment>::const_iterator next = iter;
next++;
int iSegmentEndRow = (next == timing.m_vTimeSignatureSegments.end()) ? iEndRow : next->m_iStartRow;
int iSegmentEndRow = (next == timing.m_vTimeSignatureSegments.end()) ? iEndRow : next->GetRow();
for( int i=max(iter->m_iStartRow,iStartRow); i<min(iEndRow,iSegmentEndRow); i+=4*iter->GetNoteRowsPerMeasure() )
for( int i=max(iter->GetRow(),iStartRow); i<min(iEndRow,iSegmentEndRow); i+=4*iter->GetNoteRowsPerMeasure() )
{
// Don't fade. It causes frame rate dip, especially on slower machines.
BackgroundDef bd = m_Layer[0].CreateRandomBGA( m_pSong, change.m_def.m_sEffect, m_RandomBGAnimations, this );
@@ -450,7 +450,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
bool bAtBeginningOfMeasure = false;
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
{
if( (bpmseg.m_iStartRow - iter->m_iStartRow) % iter->GetNoteRowsPerMeasure() == 0 )
if( (bpmseg.GetRow() - iter->GetRow()) % iter->GetNoteRowsPerMeasure() == 0 )
{
bAtBeginningOfMeasure = true;
break;
@@ -461,7 +461,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
continue; // skip
// start so that we don't create a BGChange right on top of fEndBeat
bool bInRange = bpmseg.m_iStartRow >= iStartRow && bpmseg.m_iStartRow < iEndRow;
bool bInRange = bpmseg.GetRow() >= iStartRow && bpmseg.GetRow() < iEndRow;
if( !bInRange )
continue; // skip
@@ -471,7 +471,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
BackgroundChange c = change;
c.m_def.m_sFile1 = bd.m_sFile1;
c.m_def.m_sFile2 = bd.m_sFile2;
c.m_fStartBeat = NoteRowToBeat(bpmseg.m_iStartRow);
c.m_fStartBeat = bpmseg.GetBeat();
m_Layer[0].m_aBGChanges.push_back( c );
}
}
+1 -1
View File
@@ -182,7 +182,7 @@ SongOptions.cpp SongOptions.h SongUtil.cpp SongUtil.h StageStats.cpp StageStats.
SoundEffectControl.cpp SoundEffectControl.h \
StepsUtil.cpp StepsUtil.h Style.cpp Style.h StyleUtil.cpp StyleUtil.h \
SubscriptionManager.h \
TimingData.cpp TimingData.h \
TimingData.cpp TimingData.h TimingSegments.cpp TimingSegments.h \
ThemeMetric.h \
Trail.cpp Trail.h TrailUtil.cpp TrailUtil.h TitleSubstitution.cpp TitleSubstitution.h \
Tween.cpp Tween.h
+104 -13
View File
@@ -778,27 +778,118 @@ void NoteDataUtil::LoadTransformedLightsFromTwo( const NoteData &marquee, const
NoteDataUtil::RemoveMines( out );
}
struct RadarStats {
int taps;
int jumps;
int hands;
int quads;
};
RadarStats CalculateRadarStatsFast( const NoteData &in, RadarStats &out )
{
out.taps = 0;
out.jumps = 0;
out.hands = 0;
out.quads = 0;
map<int, int> simultaneousMap;
map<int, int> simultaneousMapNoHold;
map<int, int> simultaneousMapTapHoldHead;
map<int, int>::iterator itr;
for( int t=0; t<in.GetNumTracks(); t++ )
{
FOREACH_NONEMPTY_ROW_IN_TRACK_RANGE( in, t, r, 0, MAX_NOTE_ROW )
{
const TapNote &tn = in.GetTapNote(t, r);
switch( tn.type )
{
case TapNote::mine:
case TapNote::empty:
case TapNote::fake:
continue; // skip these types - they don't count
}
if( (itr = simultaneousMap.find(r)) == simultaneousMap.end() )
simultaneousMap[r] = 1;
else
itr->second++;
if( (itr = simultaneousMapNoHold.find(r)) == simultaneousMapNoHold.end() )
simultaneousMapNoHold[r] = 1;
else
itr->second++;
if( tn.type == TapNote::tap || tn.type == TapNote::lift || tn.type == TapNote::hold_head )
{
simultaneousMapTapHoldHead[r] = 1;
}
if( tn.type == TapNote::hold_head )
{
int searchStartRow = r + 1;
int searchEndRow = r + tn.iDuration;
FOREACH_NONEMPTY_ROW_ALL_TRACKS_RANGE( in, rr, searchStartRow, searchEndRow )
{
switch( in.GetTapNote(t, rr).type )
{
case TapNote::mine:
case TapNote::empty:
case TapNote::fake:
continue; // skip these types - they don't count
}
if( (itr = simultaneousMap.find(rr)) == simultaneousMap.end() )
simultaneousMap[rr] = 1;
else
itr->second++;
}
}
}
}
for( itr = simultaneousMap.begin(); itr != simultaneousMap.end(); itr ++ )
{
if( itr->second >= 3 )
{
out.hands ++;
if( itr->second >= 4 )
{
out.quads ++;
}
}
}
for( itr = simultaneousMapNoHold.begin(); itr != simultaneousMapNoHold.end(); itr ++ )
{
if( itr->second >= 2 )
{
out.jumps ++;
}
}
out.taps = simultaneousMapTapHoldHead.size();
return out;
}
void NoteDataUtil::CalculateRadarValues( const NoteData &in, float fSongSeconds, RadarValues& out )
{
RadarStats stats;
CalculateRadarStatsFast( in, stats );
// The for loop and the assert are used to ensure that all fields of
// RadarValue get set in here.
FOREACH_ENUM( RadarCategory, rc )
{
switch( rc )
{
case RadarCategory_Stream: out[rc] = GetStreamRadarValue( in, fSongSeconds ); break;
case RadarCategory_Voltage: out[rc] = GetVoltageRadarValue( in, fSongSeconds ); break;
case RadarCategory_Air: out[rc] = GetAirRadarValue( in, fSongSeconds ); break;
case RadarCategory_Freeze: out[rc] = GetFreezeRadarValue( in, fSongSeconds ); break;
case RadarCategory_Chaos: out[rc] = GetChaosRadarValue( in, fSongSeconds ); break;
case RadarCategory_TapsAndHolds: out[rc] = (float) in.GetNumRowsWithTapOrHoldHead(); break;
case RadarCategory_Jumps: out[rc] = (float) in.GetNumJumps(); break;
case RadarCategory_Holds: out[rc] = (float) in.GetNumHoldNotes(); break;
case RadarCategory_Mines: out[rc] = (float) in.GetNumMines(); break;
case RadarCategory_Hands: out[rc] = (float) in.GetNumHands(); break;
case RadarCategory_Rolls: out[rc] = (float) in.GetNumRolls(); break;
case RadarCategory_Lifts: out[rc] = (float) in.GetNumLifts(); break;
case RadarCategory_Fakes: out[rc] = (float) in.GetNumFakes(); break;
case RadarCategory_Stream: out[rc] = GetStreamRadarValue( in, fSongSeconds ); break;
case RadarCategory_Voltage: out[rc] = GetVoltageRadarValue( in, fSongSeconds ); break;
case RadarCategory_Air: out[rc] = GetAirRadarValue( in, fSongSeconds ); break;
case RadarCategory_Freeze: out[rc] = GetFreezeRadarValue( in, fSongSeconds ); break;
case RadarCategory_Chaos: out[rc] = GetChaosRadarValue( in, fSongSeconds ); break;
case RadarCategory_TapsAndHolds: out[rc] = (float) stats.taps; break;
case RadarCategory_Jumps: out[rc] = (float) stats.jumps; break;
case RadarCategory_Holds: out[rc] = (float) in.GetNumHoldNotes(); break;
case RadarCategory_Mines: out[rc] = (float) in.GetNumMines(); break;
case RadarCategory_Hands: out[rc] = (float) stats.hands; break;
case RadarCategory_Rolls: out[rc] = (float) in.GetNumRolls(); break;
case RadarCategory_Lifts: out[rc] = (float) in.GetNumLifts(); break;
case RadarCategory_Fakes: out[rc] = (float) in.GetNumFakes(); break;
default: ASSERT(0);
}
}
+31 -30
View File
@@ -857,16 +857,16 @@ void NoteField::DrawPrimitives()
{
vector<TimeSignatureSegment>::const_iterator next = iter;
next++;
int iSegmentEndRow = (next == vTimeSignatureSegments.end()) ? iLastRowToDraw : next->m_iStartRow;
int iSegmentEndRow = (next == vTimeSignatureSegments.end()) ? iLastRowToDraw : next->GetRow();
// beat bars every 16th note
int iDrawBeatBarsEveryRows = BeatToNoteRow( ((float)iter->m_iDenominator) / 4 ) / 4;
int iDrawBeatBarsEveryRows = BeatToNoteRow( ((float)iter->GetDen()) / 4 ) / 4;
// In 4/4, every 16th beat bar is a measure
int iMeasureBarFrequency = iter->m_iNumerator * 4;
int iMeasureBarFrequency = iter->GetNum() * 4;
int iBeatBarsDrawn = 0;
for( int i=iter->m_iStartRow; i < iSegmentEndRow; i += iDrawBeatBarsEveryRows )
for( int i=iter->GetRow(); i < iSegmentEndRow; i += iDrawBeatBarsEveryRows )
{
bool bMeasureBar = iBeatBarsDrawn % iMeasureBarFrequency == 0;
BeatBarType type = quarter_beat;
@@ -899,9 +899,9 @@ void NoteField::DrawPrimitives()
// BPM text
FOREACH_CONST( BPMSegment, timing.m_BPMSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawBPMText( fBeat, seg->GetBPM() );
}
@@ -921,11 +921,11 @@ void NoteField::DrawPrimitives()
// Warp text
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawWarpText( fBeat, seg->m_fLengthBeats );
DrawWarpText( fBeat, seg->GetLength() );
}
}
@@ -933,11 +933,11 @@ void NoteField::DrawPrimitives()
// Time Signature text
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawTimeSignatureText( fBeat, seg->m_iNumerator, seg->m_iDenominator );
DrawTimeSignatureText( fBeat, seg->GetNum(), seg->GetDen() );
}
}
@@ -946,11 +946,11 @@ void NoteField::DrawPrimitives()
// Tickcount text
FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawTickcountText( fBeat, seg->m_iTicks );
DrawTickcountText( fBeat, seg->GetTicks() );
}
}
}
@@ -960,11 +960,11 @@ void NoteField::DrawPrimitives()
// Combo text
FOREACH_CONST( ComboSegment, timing.m_ComboSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawComboText( fBeat, seg->m_iCombo );
DrawComboText( fBeat, seg->GetCombo() );
}
}
}
@@ -972,11 +972,11 @@ void NoteField::DrawPrimitives()
// Label text
FOREACH_CONST( LabelSegment, timing.m_LabelSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawLabelText( fBeat, seg->m_sLabel );
DrawLabelText( fBeat, seg->GetLabel() );
}
}
@@ -984,11 +984,12 @@ void NoteField::DrawPrimitives()
{
FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawSpeedText( fBeat, seg->m_fPercent, seg->m_fWait, seg->m_usMode );
DrawSpeedText(fBeat, seg->GetRatio(),
seg->GetLength(), seg->GetUnit() );
}
}
}
@@ -998,11 +999,11 @@ void NoteField::DrawPrimitives()
{
FOREACH_CONST( ScrollSegment, timing.m_ScrollSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawScrollText( fBeat, seg->m_fPercent );
DrawScrollText( fBeat, seg->GetRatio() );
}
}
}
@@ -1012,11 +1013,11 @@ void NoteField::DrawPrimitives()
{
FOREACH_CONST( FakeSegment, timing.m_FakeSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
float fBeat = seg->GetBeat();
if( IS_ON_SCREEN(fBeat) )
DrawFakeText( fBeat, seg->m_fLengthBeats );
DrawFakeText( fBeat, seg->GetLength() );
}
}
}
+29
View File
@@ -307,6 +307,35 @@ inline int BeatToNoteRowNotRounded( float fBeatNum ) { return (int)( fBeatNum
* @return the beat. */
inline float NoteRowToBeat( int iRow ) { return iRow / (float)ROWS_PER_BEAT; }
// These functions can be useful for function templates,
// where both rows and beats can be specified.
/**
* @brief Convert the note row to note row (returns itself).
* @param row the row to convert.
*/
static inline int ToNoteRow(int row) { return row; }
/**
* @brief Convert the beat to note row.
* @param beat the beat to convert.
*/
static inline int ToNoteRow(float beat) { return BeatToNoteRow(beat); }
/**
* @brief Convert the note row to beat.
* @param row the row to convert.
*/
static inline float ToBeat(int row) { return NoteRowToBeat(row); }
/**
* @brief Convert the beat row to beat (return itself).
* @param beat the beat to convert.
*/
static inline float ToBeat(float beat) { return beat; }
#endif
/**
+2 -2
View File
@@ -17,8 +17,8 @@ void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector<RString>
void Deserialize(BPMSegment &seg, const Json::Value &root)
{
seg.m_iStartRow = BeatToNoteRow((float)root["Beat"].asDouble());
seg.m_fBPS = (float)(root["BPM"].asDouble() / 60);
seg.SetBeat((float)(root["Beat"].asDouble()));
seg.SetBPM((float)(root["BPM"].asDouble()));
}
static void Deserialize(StopSegment &seg, const Json::Value &root)
+3 -4
View File
@@ -541,13 +541,12 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
* and stops. It will be called again in LoadFromKSFFile for the
* actual steps. */
iTickCount = StringToInt( sParams[1] );
iTickCount = iTickCount > 0 ? iTickCount : 2; // again, Direct Move uses 4 as a default.
iTickCount = iTickCount > 0 ? iTickCount : 4;
// add a tickcount for those using the [Player]
// CheckpointsUseTimeSignatures metric. -aj
// It's not with timesigs now -DaisuMaster
TickcountSegment tcs;
tcs.m_iStartRow = BeatToNoteRow(0.0f);
tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount;
TickcountSegment tcs(0);
tcs.SetTicks(iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount);
out.m_SongTiming.AddTickcountSegment( tcs );
}
else if ( sValueName=="STEP" )
+5 -6
View File
@@ -678,19 +678,18 @@ static bool LoadFromMidi( const RString &sPath, Song &songOut )
FOREACH_CONST( MidiFileIn::TempoChange, midi.tempoEvents_, iter )
{
BPMSegment bpmSeg;
bpmSeg.m_iStartRow = MidiCountToNoteRow( iter->count );
bpmSeg.SetRow( MidiCountToNoteRow( iter->count ) );
double fSecondsPerBeat = (iter->tickSeconds * GUITAR_MIDI_COUNTS_PER_BEAT);
bpmSeg.m_fBPS = float( 1. / fSecondsPerBeat );
bpmSeg.SetBPS( float( 1. / fSecondsPerBeat ) );
songOut.m_SongTiming.AddBPMSegment( bpmSeg );
}
FOREACH_CONST( MidiFileIn::TimeSignatureChange, midi.timeSignatureEvents_, iter )
{
TimeSignatureSegment seg;
seg.m_iStartRow = MidiCountToNoteRow( iter->count );
seg.m_iNumerator = iter->numerator;
seg.m_iDenominator = iter->denominator;
TimeSignatureSegment seg(MidiCountToNoteRow( iter->count ),
iter->numerator,
iter->denominator);
songOut.m_SongTiming.AddTimeSignatureSegment( seg );
}
+1 -1
View File
@@ -751,7 +751,7 @@ static void ReadGlobalTags( const NameToData_t &mapNameToData, Song &out, Measur
{
BPMSegment newSeg( iStepIndex, fBPM );
out.m_SongTiming.AddBPMSegment( newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartRow), newSeg.GetBPM() );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", newSeg.GetBeat(), newSeg.GetBPM() );
}
else
+4 -4
View File
@@ -382,15 +382,15 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString sParam )
continue;
}
if( seg.m_iNumerator < 1 )
if( seg.GetNum() < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.GetNum() );
continue;
}
if( seg.m_iDenominator < 1 )
if( seg.GetDen() < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.GetDen() );
continue;
}
+6 -5
View File
@@ -296,9 +296,9 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
continue;
}
if( seg.m_iNumerator < 1 )
if( seg.GetNum() < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.GetNum() );
continue;
}
@@ -340,7 +340,8 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS
unsigned short tmp = ( (vs2[2].find("s") || vs2[2].find("S") )
? 1 : 0);
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ), tmp);
SpeedSegment seg(fBeat, StringToFloat( vs2[1] ), StringToFloat(vs2[2]));
seg.SetUnit(tmp);
if( fBeat < 0 )
{
@@ -348,9 +349,9 @@ void SMALoader::ProcessSpeeds( TimingData &out, const int iRowsPerBeat, const RS
continue;
}
if( seg.m_fWait < 0 )
if( seg.GetLength() < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, fWait %f.", fBeat, seg.m_fWait );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, length %f.", fBeat, seg.GetLength() );
continue;
}
+4 -3
View File
@@ -158,7 +158,8 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam )
const float fBeat = StringToFloat( vs2[0] );
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ), static_cast<unsigned short>(StringToInt(vs2[3])));
SpeedSegment seg( fBeat, StringToFloat( vs2[1] ), StringToFloat( vs2[2] ));
seg.SetUnit(StringToInt(vs2[3]));
if( fBeat < 0 )
{
@@ -166,9 +167,9 @@ void SSCLoader::ProcessSpeeds( TimingData &out, const RString sParam )
continue;
}
if( seg.m_fWait < 0 )
if( seg.GetLength() < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, fWait %f.", fBeat, seg.m_fWait );
LOG->UserLog( "Song file", "(UNKNOWN)", "has an speed change with beat %f, length %f.", fBeat, seg.GetLength() );
continue;
}
+2 -2
View File
@@ -350,7 +350,7 @@ 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()) );
ASSERT( out.m_SongTiming.m_BPMSegments[0].m_iStartRow == 0 );
ASSERT( out.m_SongTiming.m_BPMSegments[0].GetRow() == 0 );
f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) );
f.PutLine( ssprintf("#BPM:%.3f;", out.m_SongTiming.m_BPMSegments[0].GetBPM()) );
f.PutLine( ssprintf("#GAP:%ld;", -lrintf( out.m_SongTiming.m_fBeat0OffsetInSeconds*1000 )) );
@@ -395,7 +395,7 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
for( unsigned i=1; i<out.m_SongTiming.m_BPMSegments.size(); i++ )
{
const BPMSegment &bs = out.m_SongTiming.m_BPMSegments[i];
f.Write( ssprintf("%.3f=%.3f", bs.m_iStartRow * 4.0f / ROWS_PER_BEAT, bs.GetBPM() ) );
f.Write( ssprintf("%.3f=%.3f", bs.GetRow() * 4.0f / ROWS_PER_BEAT, bs.GetBPM() ) );
if( i != out.m_SongTiming.m_BPMSegments.size()-1 )
f.Write( "," );
}
+2 -2
View File
@@ -11,8 +11,8 @@
void Serialize(const BPMSegment &seg, Json::Value &root)
{
root["Beat"] = NoteRowToBeat(seg.m_iStartRow);
root["BPM"] = seg.m_fBPS * 60;
root["Beat"] = seg.GetBeat();
root["BPM"] = seg.GetBPM();
}
static void Serialize(const StopSegment &seg, Json::Value &root)
+3 -3
View File
@@ -102,7 +102,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
{
const BPMSegment &bs = out.m_SongTiming.m_BPMSegments[i];
f.PutLine( ssprintf( "%.3f=%.3f", NoteRowToBeat(bs.m_iStartRow), bs.GetBPM() ) );
f.PutLine( ssprintf( "%.3f=%.3f", bs.GetBeat(), bs.GetBPM() ) );
if( i != out.m_SongTiming.m_BPMSegments.size()-1 )
f.Write( "," );
}
@@ -113,9 +113,9 @@ static void WriteGlobalTags( RageFile &f, Song &out )
{
for( unsigned i=0; i < wSize; i++ )
{
int iRow = out.m_SongTiming.m_WarpSegments[i].m_iStartRow;
int iRow = out.m_SongTiming.m_WarpSegments[i].GetRow();
float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow);
float fSkip = fBPS * out.m_SongTiming.m_WarpSegments[i].m_fLengthBeats;
float fSkip = fBPS * out.m_SongTiming.m_WarpSegments[i].GetLength();
StopSegment ss;
ss.m_iStartRow = iRow;
ss.m_fStopSeconds = -fSkip;
+9 -9
View File
@@ -93,7 +93,7 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
w.Init( "BPMS" );
FOREACH_CONST( BPMSegment, timing.m_BPMSegments, bs )
w.Write( bs->m_iStartRow, bs->GetBPM() );
w.Write( bs->GetRow(), bs->GetBPM() );
w.Finish();
w.Init( "STOPS" );
@@ -110,49 +110,49 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
w.Init( "WARPS" );
FOREACH_CONST( WarpSegment, timing.m_WarpSegments, ws )
w.Write( ws->m_iStartRow, ws->m_fLengthBeats );
w.Write( ws->GetRow(), ws->GetLength() );
w.Finish();
ASSERT( !timing.m_vTimeSignatureSegments.empty() );
w.Init( "TIMESIGNATURES" );
FOREACH_CONST( TimeSignatureSegment, timing.m_vTimeSignatureSegments, iter )
w.Write( iter->m_iStartRow, iter->m_iNumerator, iter->m_iDenominator );
w.Write( iter->GetRow(), iter->GetNum(), iter->GetDen() );
w.Finish();
ASSERT( !timing.m_TickcountSegments.empty() );
w.Init( "TICKCOUNTS" );
FOREACH_CONST( TickcountSegment, timing.m_TickcountSegments, ts )
w.Write( ts->m_iStartRow, ts->m_iTicks );
w.Write( ts->GetRow(), ts->GetTicks() );
w.Finish();
ASSERT( !timing.m_ComboSegments.empty() );
w.Init( "COMBOS" );
FOREACH_CONST( ComboSegment, timing.m_ComboSegments, cs )
w.Write( cs->m_iStartRow, cs->m_iCombo );
w.Write( cs->GetRow(), cs->GetCombo() );
w.Finish();
// Song Timing should only have the initial value.
w.Init( "SPEEDS" );
FOREACH_CONST( SpeedSegment, timing.m_SpeedSegments, ss )
w.Write( ss->m_iStartRow, ss->m_fPercent, ss->m_fWait, ss->m_usMode );
w.Write( ss->GetRow(), ss->GetRatio(), ss->GetLength(), ss->GetUnit() );
w.Finish();
w.Init( "SCROLLS" );
FOREACH_CONST( ScrollSegment, timing.m_ScrollSegments, ss )
w.Write( ss->m_iStartRow, ss->m_fPercent );
w.Write( ss->GetRow(), ss->GetRatio() );
w.Finish();
if( !bIsSong )
{
w.Init( "FAKES" );
FOREACH_CONST( FakeSegment, timing.m_FakeSegments, fs )
w.Write( fs->m_iStartRow, fs->m_fLengthBeats );
w.Write( fs->GetRow(), fs->GetLength() );
w.Finish();
}
w.Init( "LABELS" );
FOREACH_CONST( LabelSegment, timing.m_LabelSegments, ls )
w.Write( ls->m_iStartRow, ls->m_sLabel.c_str() );
w.Write( ls->GetRow(), ls->GetLabel().c_str() );
w.Finish();
}
+22 -16
View File
@@ -198,6 +198,9 @@ ThemeMetric<int> COMBO_STOPPED_AT ( "Player", "ComboStoppedAt" );
ThemeMetric<float> ATTACK_RUN_TIME_RANDOM ( "Player", "AttackRunTimeRandom" );
ThemeMetric<float> ATTACK_RUN_TIME_MINE ( "Player", "AttackRunTimeMine" );
/** @brief Will battle modes have their steps mirrored or kept the same? */
ThemeMetric<bool> BATTLE_RAVE_MIRROR ( "Player", "BattleRaveMirror" );
float Player::GetWindowSeconds( TimingWindow tw )
{
float fSecs = m_fTimingWindowSeconds[tw];
@@ -558,23 +561,26 @@ void Player::Load()
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
NoteDataUtil::TransformNoteData( m_NoteData, m_pPlayerState->m_PlayerOptions.GetStage(), st );
// shuffle either p1 or p2
static int count = 0;
switch( count )
if (BATTLE_RAVE_MIRROR)
{
case 0:
case 3:
NoteDataUtil::Turn( m_NoteData, st, NoteDataUtil::left);
break;
case 1:
case 2:
NoteDataUtil::Turn( m_NoteData, st, NoteDataUtil::right);
break;
default:
ASSERT(0);
// shuffle either p1 or p2
static int count = 0;
switch( count )
{
case 0:
case 3:
NoteDataUtil::Turn( m_NoteData, st, NoteDataUtil::left);
break;
case 1:
case 2:
NoteDataUtil::Turn( m_NoteData, st, NoteDataUtil::right);
break;
default:
ASSERT(0);
}
count++;
count %= 4;
}
count++;
count %= 4;
}
break;
}
@@ -2875,7 +2881,7 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
TimeSignatureSegment tSignature = m_Timing->GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iLastRowCrossed ) );
// Most songs are in 4/4 time. The frequency for checking tick counts should reflect that.
iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.m_iDenominator / (tSignature.m_iNumerator * 4);
iCheckpointFrequencyRows = ROWS_PER_BEAT * tSignature.GetDen() / (tSignature.GetNum() * 4);
}
if( iCheckpointFrequencyRows > 0 )
+2 -2
View File
@@ -445,7 +445,7 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH
if( iNumBreakCombo == 0 )
{
TimingData td = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing;
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo );
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).GetCombo() );
m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier;
}
else
@@ -465,7 +465,7 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn
{
m_pPlayerStageStats->m_iCurMissCombo = 0;
TimingData td = GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]->m_Timing;
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo );
int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).GetCombo() );
m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier;
}
else if ( tns < m_MinScoreToMaintainCombo )
+16 -9
View File
@@ -1307,7 +1307,9 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
m_iShiftAnchor = -1;
return;
}
int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iNumerator;
TimingData &sTiming = GAMESTATE->m_pCurSong->m_SongTiming;
float playerBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat;
int beatsPerMeasure = sTiming.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum();
switch( EditB )
{
@@ -3222,7 +3224,7 @@ void ScreenEdit::DisplayTimingMenu()
{
float fBeat = GetBeat();
TimingData &pTime = GetAppropriateTiming();
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).m_iStartRow == BeatToNoteRow( fBeat );
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).GetBeat() == fBeat;
g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) );
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) );
@@ -3967,13 +3969,16 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
);
break;
case time_signature:
{
TimeSignatureSegment &ts = GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() );
ScreenTextEntry::TextEntry(
SM_BackFromTimeSignatureChange,
ENTER_TIME_SIGNATURE_VALUE,
ssprintf( "%d/%d", GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iNumerator, GetAppropriateTiming().GetTimeSignatureSegmentAtBeat( GetBeat() ).m_iDenominator ),
ssprintf( "%d/%d", ts.GetNum(), ts.GetDen() ),
8
);
break;
}
case tickcount:
ScreenTextEntry::TextEntry(
SM_BackFromTickcountChange,
@@ -4010,7 +4015,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromSpeedPercentChange,
ENTER_SPEED_PERCENT_VALUE,
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).m_fPercent ),
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetRatio() ),
10
);
break;
@@ -4018,7 +4023,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromScrollChange,
ENTER_SCROLL_VALUE,
ssprintf( "%.5f", GetAppropriateTiming().GetScrollSegmentAtBeat( GetBeat() ).m_fPercent ),
ssprintf( "%.5f", GetAppropriateTiming().GetScrollSegmentAtBeat( GetBeat() ).GetRatio() ),
10
);
break;
@@ -4026,7 +4031,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
ScreenTextEntry::TextEntry(
SM_BackFromSpeedWaitChange,
ENTER_SPEED_WAIT_VALUE,
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).m_fWait ),
ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetLength() ),
10
);
break;
@@ -4258,8 +4263,8 @@ void ScreenEdit::CheckNumberOfNotesAndUndo()
if( EDIT_MODE.GetValue() != EditMode_Home )
return;
TimeSignatureSegment curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat );
int rowsPerMeasure = curTime.m_iDenominator * curTime.m_iNumerator;
TimeSignatureSegment &curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat );
int rowsPerMeasure = curTime.GetDen() * curTime.GetNum();
for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure )
{
@@ -4310,7 +4315,9 @@ float ScreenEdit::GetMaximumBeatForNewNote() const
/* Round up to the next measure end. Some songs end on weird beats
* mid-measure, and it's odd to have movement capped to these weird
* beats. */
int beatsPerMeasure = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ).m_iNumerator;
TimingData &songTiming = GAMESTATE->m_pCurSong->m_SongTiming;
float playerBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat;
int beatsPerMeasure = songTiming.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum();
fEndBeat += beatsPerMeasure;
fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure );
+1 -1
View File
@@ -222,7 +222,7 @@ bool ScreenSyncOverlay::OverlayInput( const InputEventPlus &input )
if( GAMESTATE->m_pCurSong != NULL )
{
BPMSegment& seg = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMSegmentAtBeat( GAMESTATE->m_Position.m_fSongBeat );
seg.m_fBPS += fDelta;
seg.SetBPS( seg.GetBPS() + fDelta );
}
}
break;
+2
View File
@@ -1524,6 +1524,8 @@
RelativePath="TimingData.h"
>
</File>
<File RelativePath="TimingSegments.cpp"></File>
<File RelativePath="TimingSegments.h"></File>
<File
RelativePath="TitleSubstitution.cpp"
>
+3 -1
View File
@@ -502,6 +502,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClCompile Include="Style.cpp" />
<ClCompile Include="StyleUtil.cpp" />
<ClCompile Include="TimingData.cpp" />
<ClCompile Include="TimingSegments.cpp" />
<ClCompile Include="TitleSubstitution.cpp" />
<ClCompile Include="Trail.cpp" />
<ClCompile Include="TrailUtil.cpp" />
@@ -1822,6 +1823,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<ClInclude Include="SubscriptionManager.h" />
<ClInclude Include="ThemeMetric.h" />
<ClInclude Include="TimingData.h" />
<ClInclude Include="TimingSegments.h" />
<ClInclude Include="TitleSubstitution.h" />
<ClInclude Include="Trail.h" />
<ClInclude Include="TrailUtil.h" />
@@ -2393,4 +2395,4 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)</Command>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+7 -1
View File
@@ -507,6 +507,9 @@
<ClCompile Include="TimingData.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
<ClCompile Include="TimingSegments.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
<ClCompile Include="TitleSubstitution.cpp">
<Filter>Data Structures</Filter>
</ClCompile>
@@ -2027,6 +2030,9 @@
<ClInclude Include="TimingData.h">
<Filter>Data Structures</Filter>
</ClInclude>
<ClInclude Include="TimingSegments.h">
<Filter>Data Structures</Filter>
</ClInclude>
<ClInclude Include="TitleSubstitution.h">
<Filter>Data Structures</Filter>
</ClInclude>
@@ -3148,4 +3154,4 @@
<Filter>BaseClasses</Filter>
</CustomBuildStep>
</ItemGroup>
</Project>
</Project>
+235 -217
View File
File diff suppressed because it is too large Load Diff
+2 -844
View File
@@ -2,98 +2,15 @@
#define TIMING_DATA_H
#include "NoteTypes.h"
#include "TimingSegments.h"
#include "PrefsManager.h"
struct lua_State;
/** @brief Compare a TimingData segment's properties with one another. */
#define COMPARE(x) if(x!=other.x) return false;
/**
* @brief Identifies when a song changes its BPM.
*/
struct BPMSegment
{
/**
* @brief Creates a simple BPM Segment with default values.
*
* It is best to override the values as soon as possible.
*/
BPMSegment() : m_iStartRow(-1), m_fBPS(-1.0f) { }
/**
* @brief Creates a BPM Segment with the specified starting row and beats per second.
* @param s the starting row of this segment.
* @param b the beats per second to be turned into beats per minute.
*/
BPMSegment( int s, float b ): m_iStartRow(max(0, s)), m_fBPS(0) { SetBPM( b ); }
/**
* @brief The row in which the BPMSegment activates.
*/
int m_iStartRow;
/**
* @brief The BPS to use when this row is reached.
*/
float m_fBPS;
/**
* @brief Converts the BPS to a BPM.
* @param f The BPM.
*/
void SetBPM( float f ) { m_fBPS = f / 60.0f; }
/**
* @brief Retrieves the BPM from the BPS.
* @return the BPM.
*/
float GetBPM() const { return m_fBPS * 60.0f; }
/**
* @brief Compares two BPMSegments to see if they are equal to each other.
* @param other the other BPMSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const BPMSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fBPS );
return true;
}
/**
* @brief Compares two BPMSegments to see if they are not equal to each other.
* @param other the other BPMSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const BPMSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two BPMSegments to see if one is less than the other.
* @param other the other BPMSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const BPMSegment &other ) const
{
return m_iStartRow < other.m_iStartRow ||
( m_iStartRow == other.m_iStartRow && m_fBPS < other.m_fBPS );
}
/**
* @brief Compares two BPMSegments to see if one is less than or equal to the other.
* @param other the other BPMSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const BPMSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two BPMSegments to see if one is greater than the other.
* @param other the other BPMSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const BPMSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two BPMSegments to see if one is greater than or equal to the other.
* @param other the other BPMSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const BPMSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a song has a stop or a delay.
*
@@ -202,765 +119,6 @@ struct StopSegment
bool operator>=( const StopSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a song changes its time signature.
*
* This only supports simple time signatures. The upper number (called the numerator here, though this isn't
* properly a fraction) is the number of beats per measure. The lower number (denominator here)
* is the note value representing one beat. */
struct TimeSignatureSegment
{
/**
* @brief Creates a simple Time Signature Segment with default values.
*/
TimeSignatureSegment() : m_iStartRow(-1), m_iNumerator(4), m_iDenominator(4) { }
/**
* @brief Creates a Time Signature Segment at the given row with a supplied numerator.
*
* The denominator will be 4 if this is called.
* @param r the starting row of the segment.
* @param n the numerator for the segment.
*/
TimeSignatureSegment( int r, int n ): m_iStartRow(max(0, r)),
m_iNumerator(max(1, n)), m_iDenominator(4) {}
/**
* @brief Creates a Time Signature Segment at the given row with a supplied numerator & denominator.
* @param r the starting row of the segment.
* @param n the numerator for the segment.
* @param d the denonimator for the segment.
*/
TimeSignatureSegment( int r, int n, int d ): m_iStartRow(max(0, r)),
m_iNumerator(max(1, n)), m_iDenominator(max(1, d)) {}
/**
* @brief The row in which the TimeSignatureSegment activates.
*/
int m_iStartRow;
/**
* @brief The numerator of the TimeSignatureSegment.
*/
int m_iNumerator;
/**
* @brief The denominator of the TimeSignatureSegment.
*/
int m_iDenominator;
/**
* @brief Retrieve the number of note rows per measure within the TimeSignatureSegment.
*
* With BeatToNoteRow(1) rows per beat, then we should have BeatToNoteRow(1)*m_iNumerator
* beats per measure. But if we assume that every BeatToNoteRow(1) rows is a quarter note,
* and we want the beats to be 1/m_iDenominator notes, then we should have
* BeatToNoteRow(1)*4 is rows per whole note and thus BeatToNoteRow(1)*4/m_iDenominator is
* rows per beat. Multiplying by m_iNumerator gives rows per measure.
* @returns the number of note rows per measure.
*/
int GetNoteRowsPerMeasure() const { return BeatToNoteRow(1) * 4 * m_iNumerator / m_iDenominator; }
/**
* @brief Compares two TimeSignatureSegments to see if they are equal to each other.
* @param other the other TimeSignatureSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const TimeSignatureSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_iNumerator );
COMPARE( m_iDenominator );
return true;
}
/**
* @brief Compares two TimeSignatureSegments to see if they are not equal to each other.
* @param other the other TimeSignatureSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const TimeSignatureSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two TimeSignatureSegments to see if one is less than the other.
* @param other the other TimeSignatureSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const TimeSignatureSegment &other ) const
{
return m_iStartRow < other.m_iStartRow ||
( m_iStartRow == other.m_iStartRow &&
( m_iNumerator < other.m_iNumerator ||
( m_iNumerator == other.m_iNumerator && m_iDenominator < other.m_iDenominator )));
}
/**
* @brief Compares two TimeSignatureSegments to see if one is less than or equal to the other.
* @param other the other TimeSignatureSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const TimeSignatureSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two TimeSignatureSegments to see if one is greater than the other.
* @param other the other TimeSignatureSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const TimeSignatureSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two TimeSignatureSegments to see if one is greater than or equal to the other.
* @param other the other TimeSignatureSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>= (const TimeSignatureSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a song needs to warp to a new beat.
*
* A warp segment is used to replicate the effects of Negative BPMs without
* abusing negative BPMs. Negative BPMs should be converted to warp segments.
* WarpAt=WarpToRelative is the format, where both are in beats.
* (Technically they're both rows though.) */
struct WarpSegment
{
/**
* @brief Create a simple Warp Segment with default values.
*
* It is best to override the values as soon as possible.
*/
WarpSegment() : m_iStartRow(-1), m_fLengthBeats(-1) { }
/**
* @brief Create a Warp Segment with the specified starting row and row to warp to.
* @param s the starting row of this segment.
* @param r the number of rows to jump ahead.
*/
WarpSegment( int s, int r ): m_iStartRow(s),
m_fLengthBeats(NoteRowToBeat(r)) {}
/**
* @brief Creates a Warp Segment with the specified starting row and beat to warp to.
* @param s the starting row of this segment.
* @param b the number of beats to jump ahead.
*/
WarpSegment( int s, float b ): m_iStartRow(max(0, s)),
m_fLengthBeats(max(0, b)) {}
/**
* @brief Create a Warp Segment with the specified starting beat and row to warp to.
* @param s the starting beat in this segment.
* @param r the number of rows to jump ahead.
*/
WarpSegment( float s, int r ):
m_iStartRow(max(0, BeatToNoteRow(s))),
m_fLengthBeats(max(0, NoteRowToBeat(r))) {}
/**
* @brief Creates a Warp Segment with the specified starting beat and beat to warp to.
* @param s the starting beat of this segment.
* @param b the number of beats to jump ahead.
*/
WarpSegment( float s, float b ):
m_iStartRow(BeatToNoteRow(s)),
m_fLengthBeats(b) {}
/**
* @brief The row in which the WarpSegment activates.
*/
int m_iStartRow;
/**
* @brief The number of beats to warp ahead by.
*/
float m_fLengthBeats;
/**
* @brief Compares two WarpSegments to see if they are equal to each other.
* @param other the other WarpSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const WarpSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fLengthBeats );
return true;
}
/**
* @brief Compares two WarpSegments to see if they are not equal to each other.
* @param other the other WarpSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const WarpSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two WarpSegments to see if one is less than the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const WarpSegment &other ) const
{
return m_iStartRow < other.m_iStartRow ||
( m_iStartRow == other.m_iStartRow && m_fLengthBeats < other.m_fLengthBeats );
}
/**
* @brief Compares two WarpSegments to see if one is less than or equal to the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const WarpSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two WarpSegments to see if one is greater than the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const WarpSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two WarpSegments to see if one is greater than or equal to the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const WarpSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a chart is to have a different tickcount value for hold notes.
*
* A tickcount segment is used to better replicate the checkpoint hold
* system used by various based video games. The number is used to
* represent how many ticks can be counted in one beat.
*/
struct TickcountSegment
{
/**
* @brief Creates a simple Tickcount Segment with default values.
*
* It is best to override the values as soon as possible.
*/
TickcountSegment() : m_iStartRow(-1), m_iTicks(2) { }
/**
* @brief Creates a Tickcount Segment with the specified starting row and beats per second.
* @param s the starting row of this segment.
* @param t the amount of ticks counted per beat.
*/
TickcountSegment( int s, int t ): m_iStartRow(max(0, s)),
m_iTicks(max(0, t)) {}
/**
* @brief The row in which the TickcountSegment activates.
*/
int m_iStartRow;
/**
* @brief The amount of ticks counted per beat.
*/
int m_iTicks;
/**
* @brief Compares two TickcountSegments to see if they are equal to each other.
* @param other the other TickcountSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const TickcountSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_iTicks );
return true;
}
/**
* @brief Compares two TickcountSegments to see if they are not equal to each other.
* @param other the other TickcountSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const TickcountSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two TickcountSegments to see if one is less than the other.
* @param other the other TickcountSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const TickcountSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two TickcountSegments to see if one is less than or equal to the other.
* @param other the other TickcountSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const TickcountSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two TickcountSegments to see if one is greater than the other.
* @param other the other TickcountSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const TickcountSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two TickcountSegments to see if one is greater than or equal to the other.
* @param other the other TickcountSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const TickcountSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a chart is to have a different combo multiplier value.
*
* Admitedly, this would primarily be used for mission mode style charts. However,
* it can have its place during normal gameplay.
*/
struct ComboSegment
{
/**
* @brief Creates a simple Combo Segment with default values.
*
* It is best to override the values as soon as possible.
*/
ComboSegment() : m_iStartRow(-1), m_iCombo(1) { }
/**
* @brief Creates a Combo Segment with the specified starting row and combo factor.
* @param s the starting row of this segment.
* @param t the amount the combo increases on a succesful hit.
*/
ComboSegment( int s, int t ): m_iStartRow(max(0, s)),
m_iCombo(max(0,t)) {}
/**
* @brief The row in which the ComboSegment activates.
*/
int m_iStartRow;
/**
* @brief The amount the combo increases at this point.
*/
int m_iCombo;
/**
* @brief Compares two ComboSegments to see if they are equal to each other.
* @param other the other ComboSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const ComboSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_iCombo );
return true;
}
/**
* @brief Compares two ComboSegments to see if they are not equal to each other.
* @param other the other ComboSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const ComboSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two ComboSegments to see if one is less than the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const ComboSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two ComboSegments to see if one is less than or equal to the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const ComboSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two ComboSegments to see if one is greater than the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const ComboSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two ComboSegments to see if one is greater than or equal to the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const ComboSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a chart is entering a different section.
*
* This is meant for helping to identify different sections of a chart
* versus relying on measures and beats alone.
*/
struct LabelSegment
{
/**
* @brief Creates a simple Label Segment with default values.
*
* It is best to override the values as soon as possible.
*/
LabelSegment() : m_iStartRow(-1), m_sLabel("") { }
/**
* @brief Creates a Label Segment with the specified starting row and label.
* @param s the starting row of this segment.
* @param l the label for this section.
*/
LabelSegment( int s, RString l ): m_iStartRow(max(0, s)),
m_sLabel(l) {}
/**
* @brief Creates a Label Segment with the specified starting beat and label.
* @param s the starting beat of this segment.
* @param l the label for this section.
*/
LabelSegment( float s, RString l ):
m_iStartRow(max(0, BeatToNoteRow(s))), m_sLabel(l) {}
/**
* @brief The row in which the ComboSegment activates.
*/
int m_iStartRow;
/**
* @brief The label/section name for this point.
*/
RString m_sLabel;
/**
* @brief Compares two LabelSegments to see if they are equal to each other.
* @param other the other LabelSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const LabelSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_sLabel );
return true;
}
/**
* @brief Compares two LabelSegments to see if they are not equal to each other.
* @param other the other LabelSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const LabelSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two LabelSegments to see if one is less than the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const LabelSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two LabelSegments to see if one is less than or equal to the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const LabelSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two LabelSegments to see if one is greater than the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const LabelSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two LabelSegments to see if one is greater than or equal to the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const LabelSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when the arrow scroll changes.
*
* SpeedSegments take a Player's scrolling BPM (Step's BPM * speed mod),
* and then multiplies it with the percentage value. No matter the player's
* speed mod, the ratio will be the same. Unlike forced attacks, these
* cannot be turned off at a set time: reset it by setting the precentage
* back to 1.
*
* These were inspired by the Pump It Up series. */
struct SpeedSegment
{
/** @brief Sets up the SpeedSegment with default values. */
SpeedSegment(): m_iStartRow(0),
m_fPercent(1), m_fWait(0), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use. */
SpeedSegment(int i, float p): m_iStartRow(i),
m_fPercent(p), m_fWait(0), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use. */
SpeedSegment(float r, float p): m_iStartRow(BeatToNoteRow(r)),
m_fPercent(p), m_fWait(0), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use.
* @param w The number of beats to wait. */
SpeedSegment(int i, float p, float w): m_iStartRow(i),
m_fPercent(p), m_fWait(w), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use.
* @param w The number of beats to wait. */
SpeedSegment(float r, float p, float w): m_iStartRow(BeatToNoteRow(r)),
m_fPercent(p), m_fWait(w), m_usMode(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use.
* @param w The number of beats/seconds to wait.
* @param k The mode used for the wait variable. */
SpeedSegment(int i, float p, float w, unsigned short k): m_iStartRow(i),
m_fPercent(p), m_fWait(w), m_usMode(k) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use.
* @param w The number of beats/seconds to wait.
* @param k The mode used for the wait variable.*/
SpeedSegment(float r, float p, float w, unsigned short k): m_iStartRow(BeatToNoteRow(r)),
m_fPercent(p), m_fWait(w), m_usMode(k) {}
/** @brief The row in which the ComboSegment activates. */
int m_iStartRow;
/** @brief The percentage to use when multiplying the Player's BPM. */
float m_fPercent;
/**
* @brief The number of beats or seconds to wait for the change to take place.
*
* A value of 0 means this is immediate. */
float m_fWait;
/**
* @brief The mode that this segment uses for the math.
*
* 0: beats
* 1: seconds
* other
*/
unsigned short m_usMode;
/**
* @brief Compares two SpeedSegments to see if they are equal to each other.
* @param other the other SpeedSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const SpeedSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fPercent );
COMPARE( m_usMode );
COMPARE( m_fWait );
return true;
}
/**
* @brief Compares two SpeedSegments to see if they are not equal to each other.
* @param other the other SpeedSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const SpeedSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two SpeedSegments to see if one is less than the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const SpeedSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two SpeedSegments to see if one is less than or equal to the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const SpeedSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two SpeedSegments to see if one is greater than the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const SpeedSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two SpeedSegments to see if one is greater than or equal to the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const SpeedSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when the chart scroll changes.
*
* ScrollSegments adjusts the scrolling speed of the note field.
* Unlike forced attacks, these cannot be turned off at a set time:
* reset it by setting the precentage back to 1.
*
* These were inspired by the Pump It Up series. */
struct ScrollSegment
{
/** @brief Sets up the ScrollSegment with default values. */
ScrollSegment(): m_iStartRow(0), m_fPercent(1) {}
/**
* @brief Sets up the ScrollSegment with specified values.
* @param i The row this activates.
* @param p The percentage to use. */
ScrollSegment(int i, float p): m_iStartRow(i), m_fPercent(p) {}
/**
* @brief Sets up the ScrollSegment with specified values.
* @param r The beat this activates.
* @param p The percentage to use. */
ScrollSegment(float r, float p): m_iStartRow(BeatToNoteRow(r)), m_fPercent(p) {}
/** @brief The row in which the ScrollSegment activates. */
int m_iStartRow;
/** @brief The percentage to use when multiplying the chart's scroll rate. */
float m_fPercent;
/**
* @brief Compares two ScrollSegment to see if they are equal to each other.
* @param other the other ScrollSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const ScrollSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fPercent );
return true;
}
/**
* @brief Compares two ScrollSegment to see if they are not equal to each other.
* @param other the other ScrollSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const ScrollSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two ScrollSegment to see if one is less than the other.
* @param other the other ScrollSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const ScrollSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two ScrollSegment to see if one is less than or equal to the other.
* @param other the other ScrollSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const ScrollSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two ScrollSegment to see if one is greater than the other.
* @param other the other ScrollSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const ScrollSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two ScrollSegment to see if one is greater than or equal to the other.
* @param other the other ScrollSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const ScrollSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a whole region of arrows is to be ignored.
*
* FakeSegments are similar to the Fake Tap Notes in that the contents
* inside are neither for nor against the player. They can be useful for
* mission modes, in conjunction with WarpSegments, or perhaps other
* uses not thought up at the time of this comment. Unlike the Warp
* Segments, these are not magically jumped over: instead, these are
* drawn normally.
*
* These were inspired by the Pump It Up series. */
struct FakeSegment
{
/**
* @brief Create a simple Fake Segment with default values.
*
* It is best to override the values as soon as possible.
*/
FakeSegment() : m_iStartRow(-1), m_fLengthBeats(-1) { }
/**
* @brief Create a Fake Segment with the specified values.
* @param s the starting row of this segment.
* @param r the number of rows this segment lasts.
*/
FakeSegment( int s, int r ): m_iStartRow(s),
m_fLengthBeats(NoteRowToBeat(r)) {}
/**
* @brief Creates a Fake Segment with the specified values.
* @param s the starting row of this segment.
* @param b the number of beats this segment lasts.
*/
FakeSegment( int s, float b ): m_iStartRow(max(0, s)),
m_fLengthBeats(max(0, b)) {}
/**
* @brief Create a Fake Segment with the specified values.
* @param s the starting beat in this segment.
* @param r the number of rows this segment lasts.
*/
FakeSegment( float s, int r ):
m_iStartRow(max(0, BeatToNoteRow(s))),
m_fLengthBeats(max(0, NoteRowToBeat(r))) {}
/**
* @brief Creates a Fake Segment with the specified values.
* @param s the starting beat of this segment.
* @param b the number of beats this segment lasts.
*/
FakeSegment( float s, float b ):
m_iStartRow(BeatToNoteRow(s)),
m_fLengthBeats(b) {}
/**
* @brief The row in which the FakeSegment activates.
*/
int m_iStartRow;
/**
* @brief The number of beats the FakeSegment is alive for.
*/
float m_fLengthBeats;
/**
* @brief Compares two FakeSegments to see if they are equal to each other.
* @param other the other FakeSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const FakeSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_fLengthBeats );
return true;
}
/**
* @brief Compares two FakeSegments to see if they are not equal to each other.
* @param other the other FakeSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const FakeSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two FakeSegments to see if one is less than the other.
* @param other the other FakeSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const FakeSegment &other ) const
{
return m_iStartRow < other.m_iStartRow ||
( m_iStartRow == other.m_iStartRow && m_fLengthBeats < other.m_fLengthBeats );
}
/**
* @brief Compares two FakeSegments to see if one is less than or equal to the other.
* @param other the other FakeSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const FakeSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two FakeSegments to see if one is greater than the other.
* @param other the other FakeSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const FakeSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two FakeSegments to see if one is greater than or equal to the other.
* @param other the other FakeSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const FakeSegment &other ) const { return !operator<(other); }
};
/**
* @brief Holds data for translating beats<->seconds.
*/
+279
View File
@@ -0,0 +1,279 @@
#include "global.h"
#include "TimingSegments.h"
#define LTCOMPARE(x) if(this->x < other.x) return true; if(this->x > other.x) return false;
BaseTimingSegment::~BaseTimingSegment() {}
void BaseTimingSegment::SetRow(const int s)
{
this->startingRow = s;
}
void BaseTimingSegment::SetBeat(const float s)
{
SetRow(BeatToNoteRow(s));
}
int BaseTimingSegment::GetRow() const
{
return this->startingRow;
}
float BaseTimingSegment::GetBeat() const
{
return NoteRowToBeat(GetRow());
}
/* ======================================================
Here comes the actual timing segments implementation!! */
float FakeSegment::GetLength() const
{
return this->lengthBeats;
}
void FakeSegment::SetLength(const float b)
{
this->lengthBeats = b;
}
bool FakeSegment::operator<( const FakeSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetLength());
return false;
}
float WarpSegment::GetLength() const
{
return this->lengthBeats;
}
void WarpSegment::SetLength(const float b)
{
this->lengthBeats = b;
}
bool WarpSegment::operator<( const WarpSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetLength());
return false;
}
int TickcountSegment::GetTicks() const
{
return this->ticks;
}
void TickcountSegment::SetTicks(const int i)
{
this->ticks = i;
}
bool TickcountSegment::operator<( const TickcountSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetTicks());
return false;
}
int ComboSegment::GetCombo() const
{
return this->combo;
}
void ComboSegment::SetCombo(const int i)
{
this->combo = i;
}
bool ComboSegment::operator<( const ComboSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetCombo());
return false;
}
RString LabelSegment::GetLabel() const
{
return this->label;
}
void LabelSegment::SetLabel(const RString l)
{
this->label = l;
}
bool LabelSegment::operator<( const LabelSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetLabel());
return false;
}
float BPMSegment::GetBPM() const
{
return this->bps * 60.0f;
}
void BPMSegment::SetBPM(const float bpm)
{
this->bps = bpm / 60.0f;
}
float BPMSegment::GetBPS() const
{
return this->bps;
}
void BPMSegment::SetBPS(const float newBPS)
{
this->bps = newBPS;
}
bool BPMSegment::operator<( const BPMSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetBPS());
return false;
}
int TimeSignatureSegment::GetNum() const
{
return this->numerator;
}
void TimeSignatureSegment::SetNum(const int i)
{
this->numerator = i;
}
int TimeSignatureSegment::GetDen() const
{
return this->denominator;
}
void TimeSignatureSegment::SetDen(const int i)
{
this->denominator = i;
}
int TimeSignatureSegment::GetNoteRowsPerMeasure() const
{
return BeatToNoteRow(1) * 4 * numerator / denominator;
}
bool TimeSignatureSegment::operator<( const TimeSignatureSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetNum());
LTCOMPARE(GetDen());
return false;
}
float SpeedSegment::GetRatio() const
{
return this->ratio;
}
void SpeedSegment::SetRatio(const float i)
{
this->ratio = i;
}
float SpeedSegment::GetLength() const
{
return this->length;
}
void SpeedSegment::SetLength(const float i)
{
this->length = i;
}
unsigned short SpeedSegment::GetUnit() const
{
return this->unit;
}
void SpeedSegment::SetUnit(const unsigned short i)
{
this->unit = i;
}
void SpeedSegment::SetUnit(const int i)
{
this->unit = static_cast<unsigned short>(i);
}
bool SpeedSegment::operator<( const SpeedSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetRatio());
LTCOMPARE(GetLength());
LTCOMPARE(GetUnit());
return false;
}
float ScrollSegment::GetRatio() const
{
return this->ratio;
}
void ScrollSegment::SetRatio(const float i)
{
this->ratio = i;
}
bool ScrollSegment::operator<( const ScrollSegment &other ) const
{
LTCOMPARE(GetRow());
LTCOMPARE(GetRatio());
return false;
}
/**
* @file
* @author Jason Felds (c) 2011
* @section LICENSE
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+772
View File
@@ -0,0 +1,772 @@
#ifndef TIMING_SEGMENTS_H
#define TIMING_SEGMENTS_H
#include "NoteTypes.h" // Converting rows to beats and vice~versa.
/**
* @brief The base timing segment for all of the changing glory.
*
* Do not derive from this class!! Instead, derive from TimingSegment<DerivedClass>!
*/
struct BaseTimingSegment
{
/** @brief Set up a BaseTimingSegment with default values. */
BaseTimingSegment():
startingRow(-1) {};
/**
* @brief Set up a BaseTimingSegment with specified values.
* @param s the starting row / beat. */
BaseTimingSegment(int s): startingRow(ToNoteRow(s)) {}
BaseTimingSegment(float s): startingRow(ToNoteRow(s)) {}
template <class DerivedSegment>
BaseTimingSegment(const DerivedSegment &other):
startingRow(other.GetRow()) {};
virtual ~BaseTimingSegment();
/**
* @brief Set the starting row of the BaseTimingSegment.
*
* This is virtual to allow other segments to implement validation
* as required by them.
* @param s the supplied row. */
virtual void SetRow( const int s );
/**
* @brief Set the starting beat of the BaseTimingSegment.
*
* @param s the supplied beat. */
void SetBeat( const float s );
/**
* @brief Get the starting row of the BaseTimingSegment.
* @return the starting row. */
int GetRow() const;
/**
* @brief Get the starting beat of the BaseTimingSegment.
* @return the starting beat. */
float GetBeat() const;
private:
/** @brief The row in which this segment activates. */
int startingRow;
};
/**
* @brief The general TimingSegment for all of the changing glory.
*
* Each segment is supposed to derive from this one. */
template <class DerivedSegment>
struct TimingSegment: public BaseTimingSegment
{
TimingSegment(): BaseTimingSegment() {};
TimingSegment(const DerivedSegment &other): BaseTimingSegment(other) {};
template <typename StartType>
TimingSegment(StartType s): BaseTimingSegment(s) {};
/**
* @brief Compares two DrivedSegments to see if one is less than the other.
* @param other the other TimingSegments to compare to.
* @return the truth/falsehood of if the first is less than the second.
*
* This is virtual to allow other segments to implement comparison
* as required by them.
*/
virtual bool operator<( const DerivedSegment &other ) const
{
return this->GetRow() < other.GetRow();
};
/**
* @brief Compares two DrivedSegments to see if they are equal to each other.
* @param other the other FakeSegment to compare to.
* @return the equality of the two segments.
*
* This is virtual to allow other segments to implement comparison
* as required by them.
*/
bool operator==( const DerivedSegment &other ) const
{
return !this->operator<(other) &&
!other.operator<(*static_cast<const DerivedSegment *>(this));
};
/**
* @brief Compares two DrivedSegments to see if they are not equal to each other.
* @param other the other DrivedSegments to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const DerivedSegment &other ) const { return !this->operator==(other); };
/**
* @brief Compares two DrivedSegments to see if one is less than or equal to the other.
* @param other the other DrivedSegments to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const DerivedSegment &other ) const { return !this->operator>(other); };
/**
* @brief Compares two DrivedSegments to see if one is greater than the other.
* @param other the other DrivedSegments to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const DerivedSegment &other ) const
{
return other.operator<(*static_cast<const DerivedSegment *>(this));
};
/**
* @brief Compares two DrivedSegments to see if one is greater than or equal to the other.
* @param other the other DrivedSegments to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const DerivedSegment &other ) const { return !this->operator<(other); };
};
/**
* @brief Identifies when a whole region of arrows is to be ignored.
*
* FakeSegments are similar to the Fake Tap Notes in that the contents
* inside are neither for nor against the player. They can be useful for
* mission modes, in conjunction with WarpSegments, or perhaps other
* uses not thought up at the time of this comment. Unlike the Warp
* Segments, these are not magically jumped over: instead, these are
* drawn normally.
*
* These were inspired by the Pump It Up series. */
struct FakeSegment : public TimingSegment<FakeSegment>
{
/**
* @brief Create a simple Fake Segment with default values.
*
* It is best to override the values as soon as possible.
*/
FakeSegment():
TimingSegment<FakeSegment>(-1), lengthBeats(-1) {};
/**
* @brief Create a copy of another Fake Segment.
* @param other the other fake segment
*/
FakeSegment(const FakeSegment &other):
TimingSegment<FakeSegment>(other),
lengthBeats(other.GetLength()) {};
/**
* @brief Create a Fake Segment with the specified values.
* @param s the starting row of this segment.
* @param r the number of rows this segment lasts.
*/
template <typename StartType, typename LengthType>
FakeSegment( StartType s, LengthType r ):
TimingSegment<FakeSegment>(max((StartType)0, s)),
lengthBeats(ToBeat(max((LengthType)0, r))) {};
/**
* @brief Get the length in beats of the FakeSegment.
* @return the length in beats. */
float GetLength() const;
/**
* @brief Set the length in beats of the FakeSegment.
* @param b the length in beats. */
void SetLength(const float b);
/**
* @brief Compares two FakeSegments to see if one is less than the other.
* @param other the other FakeSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const FakeSegment &other ) const;
private:
/**
* @brief The number of beats the FakeSegment is alive for.
*/
float lengthBeats;
};
/**
* @brief Identifies when a song needs to warp to a new beat.
*
* A warp segment is used to replicate the effects of Negative BPMs without
* abusing negative BPMs. Negative BPMs should be converted to warp segments.
* WarpAt=WarpToRelative is the format, where both are in beats.
* (Technically they're both rows though.) */
struct WarpSegment : public TimingSegment<WarpSegment>
{
/**
* @brief Create a simple Warp Segment with default values.
*
* It is best to override the values as soon as possible.
*/
WarpSegment():
TimingSegment<WarpSegment>(), lengthBeats(-1) {};
/**
* @brief Create a copy of another Warp Segment.
* @param other the other warp segment
*/
WarpSegment(const WarpSegment &other):
TimingSegment<WarpSegment>(other),
lengthBeats(other.GetLength()) {};
/**
* @brief Create a Warp Segment with the specified values.
* @param s the starting row of this segment.
* @param r the number of rows this segment lasts.
*/
template <typename StartType, typename LengthType>
WarpSegment( StartType s, LengthType r ):
TimingSegment<WarpSegment>(s),
lengthBeats(ToBeat(max((LengthType)0, r))) {};
/**
* @brief Get the length in beats of the WarpSegment.
* @return the length in beats. */
float GetLength() const;
/**
* @brief Set the length in beats of the WarpSegment.
* @param b the length in beats. */
void SetLength(const float b);
/*
* @brief Compares two WarpSegments to see if one is less than the other.
* @param other the other WarpSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const WarpSegment &other ) const;
private:
/**
* @brief The number of beats the FakeSegment is alive for.
*/
float lengthBeats;
};
/**
* @brief Identifies when a chart is to have a different tickcount value
* for hold notes.
*
* A tickcount segment is used to better replicate the checkpoint hold
* system used by various based video games. The number is used to
* represent how many ticks can be counted in one beat.
*/
struct TickcountSegment : public TimingSegment<TickcountSegment>
{
/**
* @brief Creates a simple Tickcount Segment with default values.
*
* It is best to override the values as soon as possible.
*/
TickcountSegment():
TimingSegment<TickcountSegment>(), ticks(4) {};
/**
* @brief Create a copy of another Tickcount Segment.
* @param other the other tickcount segment
*/
TickcountSegment(const TickcountSegment &other):
TimingSegment<TickcountSegment>(other),
ticks(other.GetTicks()) {};
/**
* @brief Creates a TickcountSegment with specified values.
* @param s the starting row / beat. */
template <typename StartType>
TickcountSegment( StartType s ):
TimingSegment<TickcountSegment>(max((StartType)0, s)), ticks(4) {};
/**
* @brief Creates a TickcountSegment with specified values.
* @param s the starting row / beat.
* @param t the amount of ticks counted per beat. */
template <typename StartType>
TickcountSegment( StartType s, int t ):
TimingSegment<TickcountSegment>(max((StartType)0, s)), ticks(max(0, t)) {};
/**
* @brief Get the number of ticks in this TickcountSegment.
* @return the tickcount. */
int GetTicks() const;
/**
* @brief Set the number of ticks in this TickcountSegment.
* @param i the tickcount. */
void SetTicks(const int i);
/**
* @brief Compares two TickcountSegments to see if one is less than the other.
* @param other the other TickcountSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const TickcountSegment &other ) const;
private:
/**
* @brief The amount of ticks counted per beat.
*/
int ticks;
};
/**
* @brief Identifies when a chart is to have a different combo multiplier value.
*
* Admitedly, this would primarily be used for mission mode style charts. However,
* it can have its place during normal gameplay.
*/
struct ComboSegment : public TimingSegment<ComboSegment>
{
/**
* @brief Creates a simple Combo Segment with default values.
*
* It is best to override the values as soon as possible.
*/
ComboSegment() :
TimingSegment<ComboSegment>(), combo(1) { }
ComboSegment(const ComboSegment &other) :
TimingSegment<ComboSegment>(other),
combo(other.GetCombo()) {};
/**
* @brief Creates a Combo Segment with the specified values.
* @param s the starting row / beat of this segment.
* @param t the amount the combo increases on a succesful hit.
*/
template <typename StartType>
ComboSegment( StartType s, int t ):
TimingSegment<ComboSegment>(max((StartType)0, s)),
combo(max(0,t)) {}
/**
* @brief Get the combo in this ComboSegment.
* @return the combo. */
int GetCombo() const;
/**
* @brief Set the combo in this ComboSegment.
* @param i the combo. */
void SetCombo(const int i);
/**
* @brief Compares two ComboSegments to see if one is less than the other.
* @param other the other ComboSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const ComboSegment &other ) const;
private:
/**
* @brief The amount the combo increases at this point.
*/
int combo;
};
/**
* @brief Identifies when a chart is entering a different section.
*
* This is meant for helping to identify different sections of a chart
* versus relying on measures and beats alone.
*/
struct LabelSegment : public TimingSegment<LabelSegment>
{
/**
* @brief Creates a simple Label Segment with default values.
*
* It is best to override the values as soon as possible.
*/
LabelSegment() :
TimingSegment<LabelSegment>(), label("") { }
LabelSegment(const LabelSegment &other) :
TimingSegment<LabelSegment>(other),
label(other.GetLabel()) {};
/**
* @brief Creates a Label Segment with the specified values.
* @param s the starting row / beat of this segment.
* @param l the label for this section.
*/
template <typename StartType>
LabelSegment( StartType s, RString l ):
TimingSegment<LabelSegment>(max((StartType)0, s)),
label(l) {}
/**
* @brief Get the label in this LabelSegment.
* @return the label. */
RString GetLabel() const;
/**
* @brief Set the label in this LabelSegment.
* @param l the label. */
void SetLabel(const RString l);
/**
* @brief Compares two LabelSegments to see if one is less than the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const LabelSegment &other ) const;
private:
/**
* @brief The label/section name for this point.
*/
RString label;
};
/**
* @brief Identifies when a song changes its BPM.
*/
struct BPMSegment : public TimingSegment<BPMSegment>
{
/**
* @brief Creates a simple BPM Segment with default values.
*
* It is best to override the values as soon as possible.
*/
BPMSegment() :
TimingSegment<BPMSegment>(-1), bps(-1.0f) { }
BPMSegment(const BPMSegment &other) :
TimingSegment<BPMSegment>(other),
bps(other.GetBPS()) {};
operator int() const { return 1; }
operator float() const { return 2.0f; }
/**
* @brief Creates a BPM Segment with the specified starting row and beats per second.
* @param s the starting row / beat of this segment.
* @param b the beats per minute to be turned into beats per second.
*/
template <typename StartType>
BPMSegment( StartType s, float bpm ):
TimingSegment<BPMSegment>(max((StartType)0, s)), bps(0.0f) { SetBPM(bpm); }
/**
* @brief Get the label in this LabelSegment.
* @return the label. */
float GetBPM() const;
/**
* @brief Set the label in this LabelSegment.
* @param l the label. */
void SetBPM(const float bpm);
/**
* @brief Get the label in this LabelSegment.
* @return the label. */
float GetBPS() const;
/**
* @brief Set the label in this LabelSegment.
* @param l the label. */
void SetBPS(const float newBPS);
/**
* @brief Compares two LabelSegments to see if one is less than the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const BPMSegment &other ) const;
private:
/**
* @brief The label/section name for this point.
*/
float bps;
};
/**
* @brief Identifies when a song changes its time signature.
*
* This only supports simple time signatures. The upper number
* (called the numerator here, though this isn't properly a
* fraction) is the number of beats per measure. The lower number
* (denominator here) is the note value representing one beat. */
struct TimeSignatureSegment : public TimingSegment<TimeSignatureSegment>
{
/**
* @brief Creates a simple Time Signature Segment with default values.
*/
TimeSignatureSegment():
TimingSegment<TimeSignatureSegment>(),
numerator(4), denominator(4) { }
TimeSignatureSegment(const TimeSignatureSegment &other) :
TimingSegment<TimeSignatureSegment>(other),
numerator(other.GetNum()),
denominator(other.GetDen()) {};
/**
* @brief Creates a Time Signature Segment with supplied values.
*
* The denominator will be 4 if this is called.
* @param s the starting row / beat of the segment.
* @param n the numerator for the segment.
*/
template <typename StartType>
TimeSignatureSegment( StartType s, int n ):
TimingSegment<TimeSignatureSegment>(max((StartType)0, s)),
numerator(max(1, n)), denominator(4) {}
/**
* @brief Creates a Time Signature Segment with supplied values.
* @param s the starting row of the segment.
* @param n the numerator for the segment.
* @param d the denonimator for the segment.
*/
template <typename StartType>
TimeSignatureSegment( StartType s, int n, int d ):
TimingSegment<TimeSignatureSegment>(max((StartType)0, s)),
numerator(max(1, n)), denominator(max(1, d)) {}
/**
* @brief Get the numerator in this TimeSignatureSegment.
* @return the numerator. */
int GetNum() const;
/**
* @brief Set the numerator in this TimeSignatureSegment.
* @param i the numerator. */
void SetNum(const int i);
/**
* @brief Get the denominator in this TimeSignatureSegment.
* @return the denominator. */
int GetDen() const;
/**
* @brief Set the denominator in this TimeSignatureSegment.
* @param i the denominator. */
void SetDen(const int i);
/**
* @brief Retrieve the number of note rows per measure within the TimeSignatureSegment.
*
* With BeatToNoteRow(1) rows per beat, then we should have BeatToNoteRow(1)*m_iNumerator
* beats per measure. But if we assume that every BeatToNoteRow(1) rows is a quarter note,
* and we want the beats to be 1/m_iDenominator notes, then we should have
* BeatToNoteRow(1)*4 is rows per whole note and thus BeatToNoteRow(1)*4/m_iDenominator is
* rows per beat. Multiplying by m_iNumerator gives rows per measure.
* @returns the number of note rows per measure.
*/
int GetNoteRowsPerMeasure() const;
/**
* @brief Compares two TimeSignatureSegments to see if one is less than the other.
* @param other the other TimeSignatureSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const TimeSignatureSegment &other ) const;
private:
/**
* @brief The numerator of the TimeSignatureSegment.
*/
int numerator;
/**
* @brief The denominator of the TimeSignatureSegment.
*/
int denominator;
};
/**
* @brief Identifies when the arrow scroll changes.
*
* SpeedSegments take a Player's scrolling BPM (Step's BPM * speed mod),
* and then multiplies it with the percentage value. No matter the player's
* speed mod, the ratio will be the same. Unlike forced attacks, these
* cannot be turned off at a set time: reset it by setting the precentage
* back to 1.
*
* These were inspired by the Pump It Up series. */
struct SpeedSegment : public TimingSegment<SpeedSegment>
{
/** @brief Sets up the SpeedSegment with default values. */
SpeedSegment():
TimingSegment<SpeedSegment>(0),
ratio(1), length(0), unit(0) {}
SpeedSegment(const SpeedSegment &other) :
TimingSegment<SpeedSegment>(other),
ratio(other.GetRatio()),
length(other.GetLength()),
unit(other.GetUnit()) {};
/**
* @brief Sets up the SpeedSegment with specified values.
* @param s The row / beat this activates.
* @param p The percentage to use. */
template <typename StartType>
SpeedSegment( StartType s, float p):
TimingSegment<SpeedSegment>(max((StartType)0, s)),
ratio(p), length(0), unit(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param s The row / beat this activates.
* @param p The percentage to use.
* @param w The number of beats to wait. */
template <typename StartType>
SpeedSegment(StartType s, float p, float w):
TimingSegment<SpeedSegment>(max((StartType)0, s)),
ratio(p), length(w), unit(0) {}
/**
* @brief Sets up the SpeedSegment with specified values.
* @param s The row / beat this activates.
* @param p The percentage to use.
* @param w The number of beats/seconds to wait.
* @param k The mode used for the wait variable. */
template <typename StartType>
SpeedSegment(StartType s, float p, float w, unsigned short k):
TimingSegment<SpeedSegment>(max((StartType)0, s)),
ratio(p), length(w), unit(k) {}
/**
* @brief Get the ratio in this SpeedSegment.
* @return the ratio. */
float GetRatio() const;
/**
* @brief Set the ratio in this SpeedSegment.
* @param i the ratio. */
void SetRatio(const float i);
/**
* @brief Get the length in this SpeedSegment.
* @return the length. */
float GetLength() const;
/**
* @brief Set the length in this SpeedSegment.
* @param i the length. */
void SetLength(const float i);
/**
* @brief Get the unit in this SpeedSegment.
* @return the unit. */
unsigned short GetUnit() const;
/**
* @brief Set the unit in this SpeedSegment.
* @param i the unit. */
void SetUnit(const unsigned short i);
/**
* @brief Set the unit in this SpeedSegment.
*
* This one is offered for quicker compatibility.
* @param i the unit. */
void SetUnit(const int i);
/**
* @brief Compares two SpeedSegments to see if one is less than the other.
* @param other the other SpeedSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const SpeedSegment &other ) const;
private:
/** @brief The percentage (ratio) to use when multiplying the Player's BPM. */
float ratio;
/**
* @brief The number of beats or seconds to wait for the change to take place.
*
* A value of 0 means this is immediate. */
float length;
/**
* @brief The mode that this segment uses for the math.
*
* 0: beats
* 1: seconds
* other values are undetermined at this time, but we're prepared this way.
*/
unsigned short unit;
};
/**
* @brief Identifies when the chart scroll changes.
*
* ScrollSegments adjusts the scrolling speed of the note field.
* Unlike forced attacks, these cannot be turned off at a set time:
* reset it by setting the precentage back to 1.
*
* These were inspired by the Pump It Up series. */
struct ScrollSegment : public TimingSegment<ScrollSegment>
{
/** @brief Sets up the ScrollSegment with default values. */
ScrollSegment(): TimingSegment<ScrollSegment>(0),
ratio(1) {}
/**
* @brief Sets up the ScrollSegment with specified values.
* @param s The row / beat this activates.
* @param p The percentage to use. */
template <typename StartType>
ScrollSegment( StartType s, float p):
TimingSegment<ScrollSegment>(max((StartType)0, s)),
ratio(p) {}
ScrollSegment(const ScrollSegment &other) :
TimingSegment<ScrollSegment>(other),
ratio(other.GetRatio()) {}
/**
* @brief Get the ratio in this SpeedSegment.
* @return the ratio. */
float GetRatio() const;
/**
* @brief Set the ratio in this SpeedSegment.
* @param i the ratio. */
void SetRatio(const float i);
/**
* @brief Compares two ScrollSegment to see if one is less than the other.
* @param other the other ScrollSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const ScrollSegment &other ) const;
private:
/** @brief The ratio / percentage to use when multiplying the chart's scroll rate. */
float ratio;
};
#endif
/**
* @file
* @author Jason Felds (c) 2011
* @section LICENSE
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/