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
+3
View File
@@ -87,6 +87,9 @@ BuildLog.htm
.hgrc
src/UpgradeLog*.XML
src/_UpgradeReport_Files
src/*/sm-ssc.lib
src/*/StepMania.lib
src/libtom*/*/libtom*.lib
syntax: regexp
.*\#.*\#$
glob:Cache/Banners/AdditionalSongs_Airspace Preview_Derailed_Derailed bn.png
+10
View File
@@ -4,6 +4,16 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes
from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt.
________________________________________________________________________________
================================================================================
StepMania 5.0 ????????? | 20110???
--------------------------------------------------------------------------------
2011/05/31
----------
* [Player] Added the BattleRaveMirror metric. This determines if Battle and
Rave mode will have the two players with mirrored charts or not. By default,
this is set to true, preserving the ITG style behavior. [Wolfman2000]
================================================================================
StepMania 5.0 Preview 1 | 20110529
--------------------------------------------------------------------------------
+1
View File
@@ -1080,6 +1080,7 @@ PercentUntilColorCombo=0.25
ComboStoppedAt=50
AttackRunTimeRandom=6
AttackRunTimeMine=7
BattleRaveMirror=true
[PlayerOptions]
RandomSpeedChance=0.2
+15 -6
View File
@@ -25,6 +25,8 @@
1215D7A208C6559A00B87D8B /* ScreenGameplayNormal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1215D7A008C6559A00B87D8B /* ScreenGameplayNormal.cpp */; };
2B30D6821315EA7E00044B68 /* MouseDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B30D6801315EA7E00044B68 /* MouseDevice.cpp */; };
2B30D6831315EA7E00044B68 /* MouseDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B30D6811315EA7E00044B68 /* MouseDevice.h */; };
2B43509513949F37006FA051 /* TimingSegments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B43509313949F37006FA051 /* TimingSegments.h */; };
2B43509613949F37006FA051 /* TimingSegments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B43509413949F37006FA051 /* TimingSegments.cpp */; };
2B76698B132FF71500586512 /* NotesLoaderSMA.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B766989132FF71500586512 /* NotesLoaderSMA.h */; };
2B76698C132FF71500586512 /* NotesLoaderSMA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */; };
2B9C2E8D137A138B004C92F3 /* NotesLoaderJson.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */; };
@@ -1802,6 +1804,8 @@
29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
2B30D6801315EA7E00044B68 /* MouseDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseDevice.cpp; sourceTree = "<group>"; };
2B30D6811315EA7E00044B68 /* MouseDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MouseDevice.h; sourceTree = "<group>"; };
2B43509313949F37006FA051 /* TimingSegments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimingSegments.h; path = ../src/TimingSegments.h; sourceTree = SOURCE_ROOT; };
2B43509413949F37006FA051 /* TimingSegments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TimingSegments.cpp; path = ../src/TimingSegments.cpp; sourceTree = SOURCE_ROOT; };
2B766989132FF71500586512 /* NotesLoaderSMA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotesLoaderSMA.h; path = ../src/NotesLoaderSMA.h; sourceTree = SOURCE_ROOT; };
2B76698A132FF71500586512 /* NotesLoaderSMA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderSMA.cpp; path = ../src/NotesLoaderSMA.cpp; sourceTree = SOURCE_ROOT; };
2B9C2E89137A138B004C92F3 /* NotesLoaderJson.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotesLoaderJson.cpp; path = ../src/NotesLoaderJson.cpp; sourceTree = SOURCE_ROOT; };
@@ -3961,6 +3965,8 @@
AA21D5A10712AE16008B825F /* ThemeMetric.h */,
AA729C420599B50D00779F33 /* TimingData.cpp */,
AA729C430599B50D00779F33 /* TimingData.h */,
2B43509413949F37006FA051 /* TimingSegments.cpp */,
2B43509313949F37006FA051 /* TimingSegments.h */,
AA6EFE0E04770C79005F316C /* TitleSubstitution.cpp */,
AA6EFE0F04770C79005F316C /* TitleSubstitution.h */,
AA70E3650663112800DAE1FD /* Trail.cpp */,
@@ -5065,6 +5071,7 @@
B75CE3B5137963350076A82D /* SongPosition.h in Headers */,
2B9C2E8E137A138B004C92F3 /* NotesLoaderJson.h in Headers */,
2B9C2E90137A138B004C92F3 /* NotesWriterJson.h in Headers */,
2B43509513949F37006FA051 /* TimingSegments.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -5901,6 +5908,7 @@
AA29CD410558741A00961A51 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
comments = "We need a better way of organizing compile order here.";
files = (
B7B0914B1393481B00C33E6B /* glew.c in Sources */,
AA29CD520558741A00961A51 /* RageUtil.cpp in Sources */,
@@ -5935,10 +5943,16 @@
AA29CD660558741A00961A51 /* NotesLoader.cpp in Sources */,
AA29CD670558741A00961A51 /* NotesLoaderBMS.cpp in Sources */,
AA29CD680558741A00961A51 /* NotesLoaderDWI.cpp in Sources */,
2B9C2E8D137A138B004C92F3 /* NotesLoaderJson.cpp in Sources */,
AA29CD690558741A00961A51 /* NotesLoaderKSF.cpp in Sources */,
EE2153A910A75BEE0074B01B /* NotesLoaderPMS.cpp in Sources */,
AA29CD6A0558741A00961A51 /* NotesLoaderSM.cpp in Sources */,
2B76698C132FF71500586512 /* NotesLoaderSMA.cpp in Sources */,
2BA7925E1304F20D002BD8E1 /* NotesLoaderSSC.cpp in Sources */,
AA29CD6B0558741A00961A51 /* NotesWriterDWI.cpp in Sources */,
2B9C2E8F137A138B004C92F3 /* NotesWriterJson.cpp in Sources */,
AA29CD6C0558741A00961A51 /* NotesWriterSM.cpp in Sources */,
B75CE3B6137963350076A82D /* SongPosition.cpp in Sources */,
AA29CD6D0558741A00961A51 /* NoteTypes.cpp in Sources */,
AA29CD6E0558741A00961A51 /* Player.cpp in Sources */,
AA29CD6F0558741A00961A51 /* PlayerAI.cpp in Sources */,
@@ -6293,19 +6307,16 @@
3659B56F0F902143002B6B68 /* CommandLineActions.cpp in Sources */,
36CA531C0F91564A0063D59D /* ScreenOptionsCourseOverview.cpp in Sources */,
36CA53200F9156860063D59D /* ScreenOptionsEditCourse.cpp in Sources */,
EE2153A910A75BEE0074B01B /* NotesLoaderPMS.cpp in Sources */,
EEA7C84310A805A300082E7B /* ScreenPackagesSSC.cpp in Sources */,
36C6888311297FFE00453295 /* RageFileDriverReadAhead.cpp in Sources */,
36C6888511297FFE00453295 /* RageFileManager_ReadAhead.cpp in Sources */,
EE906F6612BF3A1B00146C96 /* ScreenInstallOverlay.cpp in Sources */,
EE906F8212BF3AF800146C96 /* JsonUtil.cpp in Sources */,
EE906F8A12BF3C7C00146C96 /* FileDownload.cpp in Sources */,
2BA7925E1304F20D002BD8E1 /* NotesLoaderSSC.cpp in Sources */,
2BA792601304F20D002BD8E1 /* NotesWriterSSC.cpp in Sources */,
2B30D6821315EA7E00044B68 /* MouseDevice.cpp in Sources */,
EE879B60132DEE720078FDDC /* RageDisplay_Legacy_Helpers.cpp in Sources */,
EE879B62132DEE720078FDDC /* RageDisplay_Legacy.cpp in Sources */,
2B76698C132FF71500586512 /* NotesLoaderSMA.cpp in Sources */,
2BD06FF1137242680018CB9F /* json_reader.cpp in Sources */,
2BD06FF2137242680018CB9F /* json_value.cpp in Sources */,
2BD06FF4137242680018CB9F /* json_writer.cpp in Sources */,
@@ -6324,9 +6335,7 @@
2BC6133813773C8E00CC8BBD /* pngwrite.c in Sources */,
2BC6133913773C8E00CC8BBD /* pngwtran.c in Sources */,
2BC6133A13773C8E00CC8BBD /* pngwutil.c in Sources */,
B75CE3B6137963350076A82D /* SongPosition.cpp in Sources */,
2B9C2E8D137A138B004C92F3 /* NotesLoaderJson.cpp in Sources */,
2B9C2E8F137A138B004C92F3 /* NotesWriterJson.cpp in Sources */,
2B43509613949F37006FA051 /* TimingSegments.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+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.
*/