diff --git a/.hgignore b/.hgignore index 2d684e1742..b29a2fa6af 100644 --- a/.hgignore +++ b/.hgignore @@ -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 diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 757f1377ea..6785197f3f 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -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 -------------------------------------------------------------------------------- diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index ef5587c558..1c5d45139a 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1080,6 +1080,7 @@ PercentUntilColorCombo=0.25 ComboStoppedAt=50 AttackRunTimeRandom=6 AttackRunTimeMine=7 +BattleRaveMirror=true [PlayerOptions] RandomSpeedChance=0.2 diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index 37d917deb0..e135889337 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -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 = ""; }; 2B30D6801315EA7E00044B68 /* MouseDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseDevice.cpp; sourceTree = ""; }; 2B30D6811315EA7E00044B68 /* MouseDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MouseDevice.h; sourceTree = ""; }; + 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; }; diff --git a/src/Background.cpp b/src/Background.cpp index 8c5a64c5fa..2761fd3b18 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -426,9 +426,9 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac { vector::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); iGetNoteRowsPerMeasure() ) + for( int i=max(iter->GetRow(),iStartRow); iGetNoteRowsPerMeasure() ) { // 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 ); } } diff --git a/src/Makefile.am b/src/Makefile.am index 178a263f39..2abcf7c4be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/NoteDataUtil.cpp b/src/NoteDataUtil.cpp index c892d3d52b..022691c700 100644 --- a/src/NoteDataUtil.cpp +++ b/src/NoteDataUtil.cpp @@ -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 simultaneousMap; + map simultaneousMapNoHold; + map simultaneousMapTapHoldHead; + map::iterator itr; + for( int t=0; tsecond++; + + 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); } } diff --git a/src/NoteField.cpp b/src/NoteField.cpp index fb1ac42670..1bee23ef11 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -857,16 +857,16 @@ void NoteField::DrawPrimitives() { vector::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() ); } } } diff --git a/src/NoteTypes.h b/src/NoteTypes.h index a91e6aa693..3d99c63252 100644 --- a/src/NoteTypes.h +++ b/src/NoteTypes.h @@ -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 /** diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp index e460a0eaba..4478423e6b 100644 --- a/src/NotesLoaderJson.cpp +++ b/src/NotesLoaderJson.cpp @@ -17,8 +17,8 @@ void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector 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) diff --git a/src/NotesLoaderKSF.cpp b/src/NotesLoaderKSF.cpp index 276f0c1e49..604c049ea1 100644 --- a/src/NotesLoaderKSF.cpp +++ b/src/NotesLoaderKSF.cpp @@ -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" ) diff --git a/src/NotesLoaderMidi.cpp b/src/NotesLoaderMidi.cpp index 9673cdb14d..8a3377b527 100644 --- a/src/NotesLoaderMidi.cpp +++ b/src/NotesLoaderMidi.cpp @@ -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 ); } diff --git a/src/NotesLoaderPMS.cpp b/src/NotesLoaderPMS.cpp index f9ef5bf1cc..749710abde 100644 --- a/src/NotesLoaderPMS.cpp +++ b/src/NotesLoaderPMS.cpp @@ -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 diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 3497af6534..78a6734eec 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -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; } diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 347399adfa..a45a87f9c2 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -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; } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index e73fd69158..04a4fdc167 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -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(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; } diff --git a/src/NotesWriterDWI.cpp b/src/NotesWriterDWI.cpp index 260728a70d..4694c1f6db 100644 --- a/src/NotesWriterDWI.cpp +++ b/src/NotesWriterDWI.cpp @@ -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 &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 &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(); } diff --git a/src/Player.cpp b/src/Player.cpp index 6a9def4af2..5bd48778f8 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -198,6 +198,9 @@ ThemeMetric COMBO_STOPPED_AT ( "Player", "ComboStoppedAt" ); ThemeMetric ATTACK_RUN_TIME_RANDOM ( "Player", "AttackRunTimeRandom" ); ThemeMetric ATTACK_RUN_TIME_MINE ( "Player", "AttackRunTimeMine" ); +/** @brief Will battle modes have their steps mirrored or kept the same? */ +ThemeMetric 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 ) diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index 8106effb3a..ce3874aa5a 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -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 ) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 1eedad0540..695ff7fe63 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -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 ); diff --git a/src/ScreenSyncOverlay.cpp b/src/ScreenSyncOverlay.cpp index 5f5d8e37f4..3596c91e70 100644 --- a/src/ScreenSyncOverlay.cpp +++ b/src/ScreenSyncOverlay.cpp @@ -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; diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index d4a1f01a8a..bcc20ea4b9 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -1524,6 +1524,8 @@ RelativePath="TimingData.h" > + + diff --git a/src/StepMania-net2010.vcxproj b/src/StepMania-net2010.vcxproj index f954c274df..c1aef5d7d2 100644 --- a/src/StepMania-net2010.vcxproj +++ b/src/StepMania-net2010.vcxproj @@ -502,6 +502,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) + @@ -1822,6 +1823,7 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) + @@ -2393,4 +2395,4 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) - \ No newline at end of file + diff --git a/src/StepMania-net2010.vcxproj.filters b/src/StepMania-net2010.vcxproj.filters index 37961b681b..0d28f9a2c7 100644 --- a/src/StepMania-net2010.vcxproj.filters +++ b/src/StepMania-net2010.vcxproj.filters @@ -507,6 +507,9 @@ Data Structures + + Data Structures + Data Structures @@ -2027,6 +2030,9 @@ Data Structures + + Data Structures + Data Structures @@ -3148,4 +3154,4 @@ BaseClasses - \ No newline at end of file + diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 8ad0a813f8..fb84c926ea 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -86,25 +86,24 @@ void TimingData::AddFakeSegment( const FakeSegment &seg ) /* Change an existing BPM segment, merge identical segments together or insert a new one. */ void TimingData::SetBPMAtRow( int iNoteRow, float fBPM ) { - float fBPS = fBPM / 60.0f; unsigned i; for( i=0; i= iNoteRow ) + if( m_BPMSegments[i].GetRow() >= iNoteRow ) break; - if( i == m_BPMSegments.size() || m_BPMSegments[i].m_iStartRow != iNoteRow ) + if( i == m_BPMSegments.size() || m_BPMSegments[i].GetRow() != iNoteRow ) { // There is no BPMSegment at the specified beat. If the BPM being set differs // from the last BPMSegment's BPM, create a new BPMSegment. - if( i == 0 || fabsf(m_BPMSegments[i-1].m_fBPS - fBPS) > 1e-5f ) + if( i == 0 || fabsf(m_BPMSegments[i-1].GetBPM() - fBPM) > 1e-5f ) AddBPMSegment( BPMSegment(iNoteRow, fBPM) ); } else // BPMSegment being modified is m_BPMSegments[i] { - if( i > 0 && fabsf(m_BPMSegments[i-1].m_fBPS - fBPS) < 1e-5f ) + if( i > 0 && fabsf(m_BPMSegments[i-1].GetBPM() - fBPM) < 1e-5f ) m_BPMSegments.erase( m_BPMSegments.begin()+i, m_BPMSegments.begin()+i+1 ); else - m_BPMSegments[i].m_fBPS = fBPS; + m_BPMSegments[i].SetBPM(fBPM); } } @@ -139,47 +138,47 @@ void TimingData::SetTimeSignatureAtRow( int iRow, int iNumerator, int iDenominat unsigned i; for( i = 0; i < m_vTimeSignatureSegments.size(); i++ ) { - if( m_vTimeSignatureSegments[i].m_iStartRow >= iRow) + if( m_vTimeSignatureSegments[i].GetRow() >= iRow) break; // We found our segment. } - if ( i == m_vTimeSignatureSegments.size() || m_vTimeSignatureSegments[i].m_iStartRow != iRow ) + if ( i == m_vTimeSignatureSegments.size() || m_vTimeSignatureSegments[i].GetRow() != iRow ) { // No specific segmeent here: place one if it differs. if( i == 0 || - ( m_vTimeSignatureSegments[i-1].m_iNumerator != iNumerator - || m_vTimeSignatureSegments[i-1].m_iDenominator != iDenominator ) ) + ( m_vTimeSignatureSegments[i-1].GetNum() != iNumerator + || m_vTimeSignatureSegments[i-1].GetDen() != iDenominator ) ) AddTimeSignatureSegment( TimeSignatureSegment(iRow, iNumerator, iDenominator) ); } else // TimeSignatureSegment being modified is m_vTimeSignatureSegments[i] { - if( i > 0 && m_vTimeSignatureSegments[i-1].m_iNumerator == iNumerator - && m_vTimeSignatureSegments[i-1].m_iDenominator == iDenominator ) + if( i > 0 && m_vTimeSignatureSegments[i-1].GetNum() == iNumerator + && m_vTimeSignatureSegments[i-1].GetDen() == iDenominator ) m_vTimeSignatureSegments.erase( m_vTimeSignatureSegments.begin()+i, m_vTimeSignatureSegments.begin()+i+1 ); else { - m_vTimeSignatureSegments[i].m_iNumerator = iNumerator; - m_vTimeSignatureSegments[i].m_iDenominator = iDenominator; + m_vTimeSignatureSegments[i].SetNum(iNumerator); + m_vTimeSignatureSegments[i].SetDen(iDenominator); } } } void TimingData::SetTimeSignatureNumeratorAtRow( int iRow, int iNumerator ) { - SetTimeSignatureAtRow( iRow, iNumerator, GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iRow ) ).m_iDenominator ); + SetTimeSignatureAtRow( iRow, iNumerator, GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iRow ) ).GetDen() ); } void TimingData::SetTimeSignatureDenominatorAtRow( int iRow, int iDenominator ) { - SetTimeSignatureAtRow( iRow, GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iRow ) ).m_iNumerator, iDenominator ); + SetTimeSignatureAtRow( iRow, GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iRow ) ).GetNum(), iDenominator ); } void TimingData::SetWarpAtRow( int iRow, float fNew ) { unsigned i; for( i=0; i 0 && fNew > 0; if( i == m_WarpSegments.size() ) @@ -193,7 +192,7 @@ void TimingData::SetWarpAtRow( int iRow, float fNew ) { if( valid ) { - m_WarpSegments[i].m_fLengthBeats = fNew; + m_WarpSegments[i].SetLength(fNew); } else m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); @@ -205,21 +204,21 @@ void TimingData::SetTickcountAtRow( int iRow, int iTicks ) { unsigned i; for( i=0; i= iRow ) + if( m_TickcountSegments[i].GetRow() >= iRow ) break; - if( i == m_TickcountSegments.size() || m_TickcountSegments[i].m_iStartRow != iRow ) + if( i == m_TickcountSegments.size() || m_TickcountSegments[i].GetRow() != iRow ) { // No TickcountSegment here. Make a new segment if required. - if( i == 0 || m_TickcountSegments[i-1].m_iTicks != iTicks ) + if( i == 0 || m_TickcountSegments[i-1].GetTicks() != iTicks ) AddTickcountSegment( TickcountSegment(iRow, iTicks ) ); } else // TickcountSegment being modified is m_TickcountSegments[i] { - if( i > 0 && m_TickcountSegments[i-1].m_iTicks == iTicks ) + if( i > 0 && m_TickcountSegments[i-1].GetTicks() == iTicks ) m_TickcountSegments.erase( m_TickcountSegments.begin()+i, m_TickcountSegments.begin()+i+1 ); else - m_TickcountSegments[i].m_iTicks = iTicks; + m_TickcountSegments[i].SetTicks(iTicks); } } @@ -227,20 +226,20 @@ void TimingData::SetComboAtRow( int iRow, int iCombo ) { unsigned i; for( i=0; i= iRow ) + if( m_ComboSegments[i].GetRow() >= iRow ) break; - if( i == m_ComboSegments.size() || m_ComboSegments[i].m_iStartRow != iRow ) + if( i == m_ComboSegments.size() || m_ComboSegments[i].GetRow() != iRow ) { - if( i == 0 || m_ComboSegments[i-1].m_iCombo != iCombo ) + if( i == 0 || m_ComboSegments[i-1].GetCombo() != iCombo ) AddComboSegment( ComboSegment(iRow, iCombo ) ); } else { - if( i > 0 && m_ComboSegments[i-1].m_iCombo == iCombo ) + if( i > 0 && m_ComboSegments[i-1].GetCombo() == iCombo ) m_ComboSegments.erase( m_ComboSegments.begin()+i, m_ComboSegments.begin()+i+1 ); else - m_ComboSegments[i].m_iCombo = iCombo; + m_ComboSegments[i].SetCombo(iCombo); } } @@ -248,20 +247,20 @@ void TimingData::SetLabelAtRow( int iRow, const RString sLabel ) { unsigned i; for( i=0; i= iRow ) + if( m_LabelSegments[i].GetRow() >= iRow ) break; - if( i == m_LabelSegments.size() || m_LabelSegments[i].m_iStartRow != iRow ) + if( i == m_LabelSegments.size() || m_LabelSegments[i].GetRow() != iRow ) { - if( i == 0 || m_LabelSegments[i-1].m_sLabel != sLabel ) + if( i == 0 || m_LabelSegments[i-1].GetLabel() != sLabel ) AddLabelSegment( LabelSegment(iRow, sLabel ) ); } else { - if( i > 0 && ( m_LabelSegments[i-1].m_sLabel == sLabel || sLabel == "" ) ) + if( i > 0 && ( m_LabelSegments[i-1].GetLabel() == sLabel || sLabel == "" ) ) m_LabelSegments.erase( m_LabelSegments.begin()+i, m_LabelSegments.begin()+i+1 ); else - m_LabelSegments[i].m_sLabel = sLabel; + m_LabelSegments[i].SetLabel(sLabel); } } @@ -270,27 +269,27 @@ void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait, unsigned unsigned i; for( i = 0; i < m_SpeedSegments.size(); i++ ) { - if( m_SpeedSegments[i].m_iStartRow >= iRow) + if( m_SpeedSegments[i].GetRow() >= iRow) break; } - if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].m_iStartRow != iRow ) + if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].GetRow() != iRow ) { // the core mod itself matters the most for comparisons. - if( i == 0 || m_SpeedSegments[i-1].m_fPercent != fPercent ) + if( i == 0 || m_SpeedSegments[i-1].GetRatio() != fPercent ) AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait, usMode) ); } else { // The others aren't compared: only the mod itself matters. - if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent ) + if( i > 0 && m_SpeedSegments[i-1].GetRatio() == fPercent ) m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 ); else { - m_SpeedSegments[i].m_fPercent = fPercent; - m_SpeedSegments[i].m_fWait = fWait; - m_SpeedSegments[i].m_usMode = usMode; + m_SpeedSegments[i].SetRatio(fPercent); + m_SpeedSegments[i].SetLength(fWait); + m_SpeedSegments[i].SetUnit(usMode); } } } @@ -300,25 +299,25 @@ void TimingData::SetScrollAtRow( int iRow, float fPercent ) unsigned i; for( i = 0; i < m_ScrollSegments.size(); i++ ) { - if( m_ScrollSegments[i].m_iStartRow >= iRow) + if( m_ScrollSegments[i].GetRow() >= iRow) break; } - if ( i == m_ScrollSegments.size() || m_ScrollSegments[i].m_iStartRow != iRow ) + if ( i == m_ScrollSegments.size() || m_ScrollSegments[i].GetRow() != iRow ) { // the core mod itself matters the most for comparisons. - if( i == 0 || m_ScrollSegments[i-1].m_fPercent != fPercent ) + if( i == 0 || m_ScrollSegments[i-1].GetRatio() != fPercent ) AddScrollSegment( ScrollSegment(iRow, fPercent) ); } else { // The others aren't compared: only the mod itself matters. - if( i > 0 && m_ScrollSegments[i-1].m_fPercent == fPercent ) + if( i > 0 && m_ScrollSegments[i-1].GetRatio() == fPercent ) m_ScrollSegments.erase( m_ScrollSegments.begin()+i, m_ScrollSegments.begin()+i+1 ); else { - m_ScrollSegments[i].m_fPercent = fPercent; + m_ScrollSegments[i].SetRatio(fPercent); } } } @@ -327,7 +326,7 @@ void TimingData::SetFakeAtRow( int iRow, float fNew ) { unsigned i; for( i=0; i 0 && fNew > 0; if( i == m_FakeSegments.size() ) @@ -341,7 +340,7 @@ void TimingData::SetFakeAtRow( int iRow, float fNew ) { if( valid ) { - m_FakeSegments[i].m_fLengthBeats = fNew; + m_FakeSegments[i].SetLength(fNew); } else m_FakeSegments.erase( m_FakeSegments.begin()+i, m_FakeSegments.begin()+i+1 ); @@ -352,23 +351,23 @@ void TimingData::SetSpeedPercentAtRow( int iRow, float fPercent ) { SetSpeedAtRow( iRow, fPercent, - GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait, - GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_usMode); + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetLength(), + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetUnit()); } void TimingData::SetSpeedWaitAtRow( int iRow, float fWait ) { SetSpeedAtRow( iRow, - GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetRatio(), fWait, - GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_usMode); + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetUnit()); } void TimingData::SetSpeedModeAtRow( int iRow, unsigned short usMode ) { SetSpeedAtRow( iRow, - GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, - GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait, + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetRatio(), + GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).GetLength(), usMode ); } @@ -398,21 +397,21 @@ float TimingData::GetDelayAtRow( int iRow ) const int TimingData::GetComboAtRow( int iNoteRow ) const { - return m_ComboSegments[GetComboSegmentIndexAtRow( iNoteRow )].m_iCombo; + return m_ComboSegments[GetComboSegmentIndexAtRow( iNoteRow )].GetCombo(); } RString TimingData::GetLabelAtRow( int iRow ) const { - return m_LabelSegments[GetLabelSegmentIndexAtRow( iRow )].m_sLabel; + return m_LabelSegments[GetLabelSegmentIndexAtRow( iRow )].GetLabel(); } float TimingData::GetWarpAtRow( int iWarpRow ) const { for( unsigned i=0; i iStartIndex ) { BPMSegment b = m_BPMSegments[i]; - b.m_iStartRow = iStartIndexNextSegment; + b.SetRow(iStartIndexNextSegment); m_BPMSegments.insert( m_BPMSegments.begin()+i+1, b ); /* Don't apply the BPM change to the first half of the segment we @@ -480,13 +479,13 @@ void TimingData::MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float f if( iStartIndexThisSegment < iEndIndex && iStartIndexNextSegment > iEndIndex ) { BPMSegment b = m_BPMSegments[i]; - b.m_iStartRow = iEndIndex; + b.SetRow(iEndIndex); m_BPMSegments.insert( m_BPMSegments.begin()+i+1, b ); } else if( iStartIndexNextSegment > iEndIndex ) continue; - m_BPMSegments[i].m_fBPS = m_BPMSegments[i].m_fBPS * fFactor; + m_BPMSegments[i].SetBPM(m_BPMSegments[i].GetBPM() * fFactor); } } @@ -494,7 +493,7 @@ float TimingData::GetBPMAtRow( int iNoteRow ) const { unsigned i; for( i=0; i iNoteRow ) + if( m_BPMSegments[i+1].GetRow() > iNoteRow ) break; return m_BPMSegments[i].GetBPM(); } @@ -503,7 +502,7 @@ int TimingData::GetBPMSegmentIndexAtRow( int iNoteRow ) const { unsigned i; for( i=0; i iNoteRow ) + if( m_BPMSegments[i+1].GetRow() > iNoteRow ) break; return static_cast(i); } @@ -526,7 +525,7 @@ int TimingData::GetWarpSegmentIndexAtRow( int iNoteRow ) const for( i=0; i iNoteRow ) + if( s.GetRow() > iNoteRow ) break; } return static_cast(i); @@ -538,7 +537,7 @@ int TimingData::GetFakeSegmentIndexAtRow( int iNoteRow ) const for( i=0; i iNoteRow ) + if( s.GetRow() > iNoteRow ) break; } return static_cast(i); @@ -551,7 +550,8 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const int i = GetWarpSegmentIndexAtRow( iNoteRow ); const WarpSegment& s = m_WarpSegments[i]; - if( s.m_iStartRow <= iNoteRow && iNoteRow < (s.m_iStartRow + BeatToNoteRow(s.m_fLengthBeats) ) ) + float beatRow = NoteRowToBeat(iNoteRow); + if( s.GetBeat() <= beatRow && beatRow < (s.GetBeat() + s.GetLength() ) ) { // Allow stops inside warps to allow things like stop, warp, stop, warp, stop, and so on. if( m_StopSegments.empty() ) @@ -574,7 +574,8 @@ bool TimingData::IsFakeAtRow( int iNoteRow ) const int i = GetFakeSegmentIndexAtRow( iNoteRow ); const FakeSegment& s = m_FakeSegments[i]; - if( s.m_iStartRow <= iNoteRow && iNoteRow < ( s.m_iStartRow + BeatToNoteRow(s.m_fLengthBeats) ) ) + float beatRow = NoteRowToBeat(iNoteRow); + if( s.GetBeat() <= beatRow && beatRow < ( s.GetBeat() + s.GetLength() ) ) { return true; } @@ -585,7 +586,7 @@ int TimingData::GetTimeSignatureSegmentIndexAtRow( int iRow ) const { unsigned i; for (i=0; i < m_vTimeSignatureSegments.size() - 1; i++ ) - if( m_vTimeSignatureSegments[i+1].m_iStartRow > iRow ) + if( m_vTimeSignatureSegments[i+1].GetRow() > iRow ) break; return static_cast(i); } @@ -596,7 +597,7 @@ int TimingData::GetComboSegmentIndexAtRow( int iRow ) const for( i=0; i iRow ) + if( s.GetRow() > iRow ) break; } return static_cast(i); @@ -608,7 +609,7 @@ int TimingData::GetLabelSegmentIndexAtRow( int iRow ) const for( i=0; i iRow ) + if( s.GetRow() > iRow ) break; } return static_cast(i); @@ -618,7 +619,7 @@ int TimingData::GetSpeedSegmentIndexAtRow( int iRow ) const { unsigned i; for (i=0; i < m_SpeedSegments.size() - 1; i++ ) - if( m_SpeedSegments[i+1].m_iStartRow > iRow ) + if( m_SpeedSegments[i+1].GetRow() > iRow ) break; return static_cast(i); } @@ -627,7 +628,7 @@ int TimingData::GetScrollSegmentIndexAtRow( int iRow ) const { unsigned i; for (i=0; i < m_ScrollSegments.size() - 1; i++ ) - if( m_ScrollSegments[i+1].m_iStartRow > iRow ) + if( m_ScrollSegments[i+1].GetRow() > iRow ) break; return static_cast(i); } @@ -646,7 +647,7 @@ TimeSignatureSegment& TimingData::GetTimeSignatureSegmentAtRow( int iRow ) { unsigned i; for( i=0; i iRow ) + if( m_vTimeSignatureSegments[i+1].GetRow() > iRow ) break; return m_vTimeSignatureSegments[i]; } @@ -655,7 +656,7 @@ SpeedSegment& TimingData::GetSpeedSegmentAtRow( int iRow ) { unsigned i; for( i=0; i iRow ) + if( m_SpeedSegments[i+1].GetRow() > iRow ) break; return m_SpeedSegments[i]; } @@ -664,26 +665,26 @@ ScrollSegment& TimingData::GetScrollSegmentAtRow( int iRow ) { unsigned i; for( i=0; i iRow ) + if( m_ScrollSegments[i+1].GetRow() > iRow ) break; return m_ScrollSegments[i]; } int TimingData::GetTimeSignatureNumeratorAtRow( int iRow ) { - return GetTimeSignatureSegmentAtRow( iRow ).m_iNumerator; + return GetTimeSignatureSegmentAtRow( iRow ).GetNum(); } int TimingData::GetTimeSignatureDenominatorAtRow( int iRow ) { - return GetTimeSignatureSegmentAtRow( iRow ).m_iDenominator; + return GetTimeSignatureSegmentAtRow( iRow ).GetDen(); } ComboSegment& TimingData::GetComboSegmentAtRow( int iRow ) { unsigned i; for( i=0; i iRow ) + if( m_ComboSegments[i+1].GetRow() > iRow ) break; return m_ComboSegments[i]; } @@ -692,7 +693,7 @@ LabelSegment& TimingData::GetLabelSegmentAtRow( int iRow ) { unsigned i; for( i=0; i iRow ) + if( m_LabelSegments[i+1].GetRow() > iRow ) break; return m_LabelSegments[i]; } @@ -731,7 +732,7 @@ int TimingData::GetTickcountSegmentIndexAtRow( int iRow ) const { unsigned i; for (i=0; i < m_TickcountSegments.size() - 1; i++ ) - if( m_TickcountSegments[i+1].m_iStartRow > iRow ) + if( m_TickcountSegments[i+1].GetRow() > iRow ) break; return static_cast(i); } @@ -748,7 +749,7 @@ TickcountSegment& TimingData::GetTickcountSegmentAtRow( int iRow ) int TimingData::GetTickcountAtRow( int iRow ) const { - return m_TickcountSegments[GetTickcountSegmentIndexAtRow( iRow )].m_iTicks; + return m_TickcountSegments[GetTickcountSegmentIndexAtRow( iRow )].GetTicks(); } float TimingData::GetPreviousLabelSegmentBeatAtRow( int iRow ) const @@ -756,11 +757,11 @@ float TimingData::GetPreviousLabelSegmentBeatAtRow( int iRow ) const float backup = -1; for (unsigned i = 0; i < m_LabelSegments.size(); i++ ) { - if( m_LabelSegments[i].m_iStartRow >= iRow ) + if( m_LabelSegments[i].GetRow() >= iRow ) { break; } - backup = NoteRowToBeat(m_LabelSegments[i].m_iStartRow); + backup = m_LabelSegments[i].GetBeat(); } return (backup > -1) ? backup : NoteRowToBeat(iRow); } @@ -769,11 +770,11 @@ float TimingData::GetNextLabelSegmentBeatAtRow( int iRow ) const { for (unsigned i = 0; i < m_LabelSegments.size(); i++ ) { - if( m_LabelSegments[i].m_iStartRow <= iRow ) + if( m_LabelSegments[i].GetRow() <= iRow ) { continue; } - return NoteRowToBeat(m_LabelSegments[i].m_iStartRow); + return m_LabelSegments[i].GetBeat(); } return NoteRowToBeat(iRow); } @@ -782,7 +783,7 @@ bool TimingData::DoesLabelExist( RString sLabel ) const { FOREACH_CONST( LabelSegment, m_LabelSegments, seg ) { - if( seg->m_sLabel == sLabel ) + if( seg->GetLabel() == sLabel ) return true; } return false; @@ -833,9 +834,9 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float iEventRow = BeatToNoteRow(fWarpDestination); iEventType = FOUND_WARP_DESTINATION; } - if( itBPMS != m_BPMSegments.end() && itBPMS->m_iStartRow < iEventRow ) + if( itBPMS != m_BPMSegments.end() && itBPMS->GetRow() < iEventRow ) { - iEventRow = itBPMS->m_iStartRow; + iEventRow = itBPMS->GetRow(); iEventType = FOUND_BPM_CHANGE; } if( itSS != m_StopSegments.end() && itSS->m_iStartRow < iEventRow ) @@ -843,9 +844,9 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float iEventRow = itSS->m_iStartRow; iEventType = FOUND_STOP; } - if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) + if( itWS != m_WarpSegments.end() && itWS->GetRow() < iEventRow ) { - iEventRow = itWS->m_iStartRow; + iEventRow = itWS->GetRow(); iEventType = FOUND_WARP; } if( iEventType == NOT_FOUND ) @@ -865,7 +866,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float bIsWarping = false; break; case FOUND_BPM_CHANGE: - fBPS = itBPMS->m_fBPS; + fBPS = itBPMS->GetBPS(); itBPMS ++; break; case FOUND_STOP: @@ -888,7 +889,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float case FOUND_WARP: { bIsWarping = true; - float fWarpSum = itWS->m_fLengthBeats + NoteRowToBeat( itWS->m_iStartRow ); + float fWarpSum = itWS->GetLength() + itWS->GetBeat(); if( fWarpSum > fWarpDestination ) { fWarpDestination = fWarpSum; @@ -935,9 +936,9 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const iEventRow = BeatToNoteRow(fWarpDestination); iEventType = FOUND_WARP_DESTINATION; } - if( itBPMS != m_BPMSegments.end() && itBPMS->m_iStartRow < iEventRow ) + if( itBPMS != m_BPMSegments.end() && itBPMS->GetRow() < iEventRow ) { - iEventRow = itBPMS->m_iStartRow; + iEventRow = itBPMS->GetRow(); iEventType = FOUND_BPM_CHANGE; } if( itSS != m_StopSegments.end() && itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) // delays (come before marker) @@ -955,9 +956,9 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const iEventRow = itSS->m_iStartRow; iEventType = FOUND_STOP; } - if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) + if( itWS != m_WarpSegments.end() && itWS->GetRow() < iEventRow ) { - iEventRow = itWS->m_iStartRow; + iEventRow = itWS->GetRow(); iEventType = FOUND_WARP; } float fTimeToNextEvent = bIsWarping ? 0 : NoteRowToBeat( iEventRow - iLastRow ) / fBPS; @@ -969,7 +970,7 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const bIsWarping = false; break; case FOUND_BPM_CHANGE: - fBPS = itBPMS->m_fBPS; + fBPS = itBPMS->GetBPS(); itBPMS ++; break; case FOUND_STOP: @@ -983,7 +984,7 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const case FOUND_WARP: { bIsWarping = true; - float fWarpSum = itWS->m_fLengthBeats + NoteRowToBeat( itWS->m_iStartRow ); + float fWarpSum = itWS->GetLength() + itWS->GetBeat(); if( fWarpSum > fWarpDestination ) { fWarpDestination = fWarpSum; @@ -1002,10 +1003,13 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const float TimingData::GetDisplayedBeat( float fBeat ) const { unsigned index = GetScrollSegmentIndexAtBeat(fBeat); - float fOutBeat = ( fBeat - NoteRowToBeat(m_ScrollSegments[index].m_iStartRow) ) * m_ScrollSegments[index].m_fPercent; + const ScrollSegment &s = m_ScrollSegments[index]; + float fOutBeat = ( fBeat - s.GetBeat() ) * s.GetRatio(); for( unsigned i = 0; i < index; i ++ ) { - fOutBeat += ( NoteRowToBeat(m_ScrollSegments[i + 1].m_iStartRow) - NoteRowToBeat(m_ScrollSegments[i].m_iStartRow) ) * m_ScrollSegments[i].m_fPercent; + const ScrollSegment &future = m_ScrollSegments[i+1]; + const ScrollSegment ¤t = m_ScrollSegments[i]; + fOutBeat += ( future.GetBeat() - current.GetBeat() ) * current.GetRatio(); } return fOutBeat; } @@ -1018,128 +1022,141 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool for ( unsigned i = 0; i < m_BPMSegments.size(); i++ ) { - const int iSegStart = m_BPMSegments[i].m_iStartRow; + BPMSegment &b = m_BPMSegments[i]; + const int iSegStart = b.GetRow(); if( iSegStart < iStartIndex ) continue; else if( iSegStart > iEndIndex ) - m_BPMSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + b.SetRow( b.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ) ); else - m_BPMSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + b.SetRow( lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex ); } for( unsigned i = 0; i < m_StopSegments.size(); i++ ) { - const int iSegStartRow = m_StopSegments[i].m_iStartRow; + StopSegment &s = m_StopSegments[i]; + const int iSegStartRow = s.m_iStartRow; if( iSegStartRow < iStartIndex ) continue; else if( iSegStartRow > iEndIndex ) - m_StopSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + s.m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); else - m_StopSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + s.m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; } for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) { - const int iSegStartRow = m_vTimeSignatureSegments[i].m_iStartRow; + TimeSignatureSegment &t = m_vTimeSignatureSegments[i]; + const int iSegStartRow = t.GetRow(); if( iSegStartRow < iStartIndex ) continue; else if( iSegStartRow > iEndIndex ) - m_vTimeSignatureSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + t.SetRow(t.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); else - m_vTimeSignatureSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + t.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); } for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) { - const int iSegStartRow = m_WarpSegments[i].m_iStartRow; - const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_WarpSegments[i].m_fLengthBeats ); + WarpSegment &w = m_WarpSegments[i]; + const int iSegStartRow = w.GetRow(); + const int iSegEndRow = iSegStartRow + BeatToNoteRow( w.GetLength() ); if( iSegEndRow >= iStartIndex ) { if( iSegEndRow > iEndIndex ) - m_WarpSegments[i].m_fLengthBeats += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); + w.SetLength(w.GetLength() + + NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1)))); else - m_WarpSegments[i].m_fLengthBeats = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)); + w.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale))); } if( iSegStartRow < iStartIndex ) continue; else if( iSegStartRow > iEndIndex ) - m_WarpSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + w.SetRow(w.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); else - m_WarpSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + w.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); } for ( unsigned i = 0; i < m_TickcountSegments.size(); i++ ) { - const int iSegStart = m_TickcountSegments[i].m_iStartRow; + TickcountSegment &t = m_TickcountSegments[i]; + const int iSegStart = t.GetRow(); if( iSegStart < iStartIndex ) continue; else if( iSegStart > iEndIndex ) - m_TickcountSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + t.SetRow(t.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); else - m_TickcountSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + t.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); } for ( unsigned i = 0; i < m_ComboSegments.size(); i++ ) { - const int iSegStart = m_ComboSegments[i].m_iStartRow; + ComboSegment &c = m_ComboSegments[i]; + const int iSegStart = c.GetRow(); if( iSegStart < iStartIndex ) continue; else if( iSegStart > iEndIndex ) - m_ComboSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + c.SetRow(c.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); else - m_ComboSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + c.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); } for ( unsigned i = 0; i < m_LabelSegments.size(); i++ ) { - const int iSegStart = m_LabelSegments[i].m_iStartRow; + LabelSegment &l = m_LabelSegments[i]; + const int iSegStart = l.GetRow(); if( iSegStart < iStartIndex ) continue; else if( iSegStart > iEndIndex ) - m_LabelSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + l.SetRow(l.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); else - m_LabelSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + l.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); } for ( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) { - const int iSegStart = m_SpeedSegments[i].m_iStartRow; + SpeedSegment &s = m_SpeedSegments[i]; + const int iSegStart = s.GetRow(); if( iSegStart < iStartIndex ) continue; else if( iSegStart > iEndIndex ) - m_SpeedSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + s.SetRow(s.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); else - m_SpeedSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + s.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); } for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) { - const int iSegStartRow = m_FakeSegments[i].m_iStartRow; - const int iSegEndRow = iSegStartRow + BeatToNoteRow( m_FakeSegments[i].m_fLengthBeats ); + FakeSegment &f = m_FakeSegments[i]; + const int iSegStartRow = f.GetRow(); + const int iSegEndRow = iSegStartRow + BeatToNoteRow( f.GetLength() ); if( iSegEndRow >= iStartIndex ) { if( iSegEndRow > iEndIndex ) - m_FakeSegments[i].m_fLengthBeats += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); + f.SetLength(f.GetLength() + + NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1)))); else - m_FakeSegments[i].m_fLengthBeats = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale)); + f.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale))); } if( iSegStartRow < iStartIndex ) continue; else if( iSegStartRow > iEndIndex ) - m_FakeSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + f.SetRow(f.GetRow() + + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); else - m_FakeSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + f.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); } for( unsigned i = 0; i < m_ScrollSegments.size(); i++ ) { - const int iSegStartRow = m_ScrollSegments[i].m_iStartRow; + ScrollSegment &s = m_ScrollSegments[i]; + const int iSegStartRow = s.GetRow(); if( iSegStartRow < iStartIndex ) continue; else if( iSegStartRow > iEndIndex ) - m_ScrollSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + s.SetRow(s.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); else - m_ScrollSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + s.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); } // adjust BPM changes to preserve timing @@ -1151,13 +1168,13 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool // adjust BPM changes "between" iStartIndex and iNewEndIndex for ( unsigned i = 0; i < m_BPMSegments.size(); i++ ) { - const int iSegStart = m_BPMSegments[i].m_iStartRow; + const int iSegStart = m_BPMSegments[i].GetRow(); if( iSegStart <= iStartIndex ) continue; else if( iSegStart >= iNewEndIndex ) continue; else - m_BPMSegments[i].m_fBPS *= fScale; + m_BPMSegments[i].SetBPM( m_BPMSegments[i].GetBPM() * fScale ); } // set BPM at iStartIndex and iNewEndIndex. @@ -1173,9 +1190,9 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) for( unsigned i = 0; i < m_BPMSegments.size(); i++ ) { BPMSegment &bpm = m_BPMSegments[i]; - if( bpm.m_iStartRow < iStartRow ) + if( bpm.GetRow() < iStartRow ) continue; - bpm.m_iStartRow += iRowsToAdd; + bpm.SetRow( bpm.GetRow() + iRowsToAdd ); } for( unsigned i = 0; i < m_StopSegments.size(); i++ ) @@ -1189,64 +1206,64 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) { WarpSegment &warp = m_WarpSegments[i]; - if( warp.m_iStartRow < iStartRow ) + if( warp.GetRow() < iStartRow ) continue; - warp.m_iStartRow += iRowsToAdd; + warp.SetRow(warp.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) { TimeSignatureSegment &time = m_vTimeSignatureSegments[i]; - if( time.m_iStartRow < iStartRow ) + if( time.GetRow() < iStartRow ) continue; - time.m_iStartRow += iRowsToAdd; + time.SetRow(time.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_TickcountSegments.size(); i++ ) { TickcountSegment &tick = m_TickcountSegments[i]; - if( tick.m_iStartRow < iStartRow ) + if( tick.GetRow() < iStartRow ) continue; - tick.m_iStartRow += iRowsToAdd; + tick.SetRow(tick.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_ComboSegments.size(); i++ ) { ComboSegment &comb = m_ComboSegments[i]; - if( comb.m_iStartRow < iStartRow ) + if( comb.GetRow() < iStartRow ) continue; - comb.m_iStartRow += iRowsToAdd; + comb.SetRow(comb.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_LabelSegments.size(); i++ ) { LabelSegment &labl = m_LabelSegments[i]; - if( labl.m_iStartRow < iStartRow ) + if( labl.GetRow() < iStartRow ) continue; - labl.m_iStartRow += iRowsToAdd; + labl.SetRow(labl.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) { SpeedSegment &sped = m_SpeedSegments[i]; - if( sped.m_iStartRow < iStartRow ) + if( sped.GetRow() < iStartRow ) continue; - sped.m_iStartRow += iRowsToAdd; + sped.SetRow(sped.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) { FakeSegment &fake = m_FakeSegments[i]; - if( fake.m_iStartRow < iStartRow ) + if( fake.GetRow() < iStartRow ) continue; - fake.m_iStartRow += iRowsToAdd; + fake.SetRow(fake.GetRow() + iRowsToAdd); } for( unsigned i = 0; i < m_ScrollSegments.size(); i++ ) { ScrollSegment &scrl = m_ScrollSegments[i]; - if( scrl.m_iStartRow < iStartRow ) + if( scrl.GetRow() < iStartRow ) continue; - scrl.m_iStartRow += iRowsToAdd; + scrl.SetRow(scrl.GetRow() + iRowsToAdd); } if( iStartRow == 0 ) @@ -1254,7 +1271,7 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) /* If we're shifting up at the beginning, we just shifted up the first * BPMSegment. That segment must always begin at 0. */ ASSERT( m_BPMSegments.size() > 0 ); - m_BPMSegments[0].m_iStartRow = 0; + m_BPMSegments[0].SetRow(0); } } @@ -1271,11 +1288,11 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) BPMSegment &bpm = m_BPMSegments[i]; // Before deleted region: - if( bpm.m_iStartRow < iStartRow ) + if( bpm.GetRow() < iStartRow ) continue; // Inside deleted region: - if( bpm.m_iStartRow < iStartRow+iRowsToDelete ) + if( bpm.GetRow() < iStartRow+iRowsToDelete ) { m_BPMSegments.erase( m_BPMSegments.begin()+i, m_BPMSegments.begin()+i+1 ); --i; @@ -1283,7 +1300,7 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) } // After deleted region: - bpm.m_iStartRow -= iRowsToDelete; + bpm.SetRow( bpm.GetRow() - iRowsToDelete ); } for( unsigned i = 0; i < m_StopSegments.size(); i++ ) @@ -1309,30 +1326,30 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) { WarpSegment &warp = m_WarpSegments[i]; - - if( warp.m_iStartRow < iStartRow ) + int keyRow = warp.GetRow(); + if( keyRow < iStartRow ) continue; - if( warp.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); --i; continue; } - warp.m_iStartRow -= iRowsToDelete; + warp.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) { TimeSignatureSegment &time = m_vTimeSignatureSegments[i]; - + int keyRow = time.GetRow(); // Before deleted region: - if( time.m_iStartRow < iStartRow ) + if( keyRow < iStartRow ) continue; // Inside deleted region: - if( time.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_vTimeSignatureSegments.erase( m_vTimeSignatureSegments.begin()+i, @@ -1344,19 +1361,19 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) // After deleted region: - time.m_iStartRow -= iRowsToDelete; + time.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_TickcountSegments.size(); i++ ) { TickcountSegment &tick = m_TickcountSegments[i]; - + int keyRow = tick.GetRow(); // Before deleted region: - if( tick.m_iStartRow < iStartRow ) + if( keyRow < iStartRow ) continue; // Inside deleted region: - if( tick.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_TickcountSegments.erase( m_TickcountSegments.begin()+i, m_TickcountSegments.begin()+i+1 ); --i; @@ -1364,19 +1381,19 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) } // After deleted region: - tick.m_iStartRow -= iRowsToDelete; + tick.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_ComboSegments.size(); i++ ) { ComboSegment &comb = m_ComboSegments[i]; - + int keyRow = comb.GetRow(); // Before deleted region: - if( comb.m_iStartRow < iStartRow ) + if( keyRow < iStartRow ) continue; // Inside deleted region: - if( comb.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_ComboSegments.erase( m_ComboSegments.begin()+i, m_ComboSegments.begin()+i+1 ); --i; @@ -1384,72 +1401,72 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) } // After deleted region: - comb.m_iStartRow -= iRowsToDelete; + comb.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_LabelSegments.size(); i++ ) { LabelSegment &labl = m_LabelSegments[i]; - - if( labl.m_iStartRow < iStartRow ) + int keyRow = labl.GetRow(); + if( keyRow < iStartRow ) continue; - if( labl.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_LabelSegments.erase( m_LabelSegments.begin()+i, m_LabelSegments.begin()+i+1 ); --i; continue; } - labl.m_iStartRow -= iRowsToDelete; + labl.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) { SpeedSegment &sped = m_SpeedSegments[i]; - - if( sped.m_iStartRow < iStartRow ) + int keyRow = sped.GetRow(); + if( keyRow < iStartRow ) continue; - if( sped.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 ); --i; continue; } - sped.m_iStartRow -= iRowsToDelete; + sped.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) { FakeSegment &fake = m_FakeSegments[i]; - - if( fake.m_iStartRow < iStartRow ) + int keyRow = fake.GetRow(); + if( keyRow < iStartRow ) continue; - if( fake.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_FakeSegments.erase( m_FakeSegments.begin()+i, m_FakeSegments.begin()+i+1 ); --i; continue; } - fake.m_iStartRow -= iRowsToDelete; + fake.SetRow(keyRow - iRowsToDelete); } for( unsigned i = 0; i < m_ScrollSegments.size(); i++ ) { ScrollSegment &scrl = m_ScrollSegments[i]; - - if( scrl.m_iStartRow < iStartRow ) + int keyRow = scrl.GetRow(); + if( keyRow < iStartRow ) continue; - if( scrl.m_iStartRow < iStartRow+iRowsToDelete ) + if( keyRow < iStartRow+iRowsToDelete ) { m_ScrollSegments.erase( m_ScrollSegments.begin()+i, m_ScrollSegments.begin()+i+1 ); --i; continue; } - scrl.m_iStartRow -= iRowsToDelete; + scrl.SetRow(keyRow - iRowsToDelete); } this->SetBPMAtRow( iStartRow, fNewBPM ); @@ -1463,38 +1480,39 @@ float TimingData::GetDisplayedSpeedPercent( float fSongBeat, float fMusicSeconds const int index = GetSpeedSegmentIndexAtBeat( fSongBeat ); const SpeedSegment &seg = m_SpeedSegments[index]; - float fStartBeat = NoteRowToBeat(seg.m_iStartRow); + float fStartBeat = seg.GetBeat(); float fStartTime = GetElapsedTimeFromBeat( fStartBeat ) - GetDelayAtBeat( fStartBeat ); float fEndTime; float fCurTime = fMusicSeconds; - if( seg.m_usMode == 1 ) // seconds + if( seg.GetUnit() == 1 ) // seconds { - fEndTime = fStartTime + seg.m_fWait; + fEndTime = fStartTime + seg.GetLength(); } else { - fEndTime = GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ) - GetDelayAtBeat( fStartBeat + seg.m_fWait ); + fEndTime = GetElapsedTimeFromBeat( fStartBeat + seg.GetLength() ) + - GetDelayAtBeat( fStartBeat + seg.GetLength() ); } - if( ( index == 0 && m_SpeedSegments[0].m_fWait > 0.0 ) && fCurTime < fStartTime ) + if( ( index == 0 && m_SpeedSegments[0].GetLength() > 0.0 ) && fCurTime < fStartTime ) { return 1.0; } - else if( fEndTime >= fCurTime && ( index > 0 || m_SpeedSegments[0].m_fWait > 0.0 ) ) + else if( fEndTime >= fCurTime && ( index > 0 || m_SpeedSegments[0].GetLength() > 0.0 ) ) { - const float fPriorSpeed = ( index == 0 ? 1 : m_SpeedSegments[index - 1].m_fPercent ); + const float fPriorSpeed = ( index == 0 ? 1 : m_SpeedSegments[index - 1].GetRatio() ); float fTimeUsed = fCurTime - fStartTime; float fDuration = fEndTime - fStartTime; float fRatioUsed = fDuration == 0.0 ? 1 : fTimeUsed / fDuration; - float fDistance = fPriorSpeed - seg.m_fPercent; + float fDistance = fPriorSpeed - seg.GetRatio(); float fRatioNeed = fRatioUsed * -fDistance; return (fPriorSpeed + fRatioNeed); } else { - return seg.m_fPercent; + return seg.GetRatio(); } } @@ -1510,8 +1528,8 @@ void TimingData::TidyUpData() } // Make sure the first BPM segment starts at beat 0. - if( m_BPMSegments[0].m_iStartRow != 0 ) - m_BPMSegments[0].m_iStartRow = 0; + if( m_BPMSegments[0].GetRow() != 0 ) + m_BPMSegments[0].SetRow(0); // If no time signature specified, assume 4/4 time for the whole song. if( m_vTimeSignatureSegments.empty() ) @@ -1600,14 +1618,14 @@ void TimingData::NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, i { vector::const_iterator next = iter; next++; - int iSegmentEndRow = (next == m_vTimeSignatureSegments.end()) ? INT_MAX : next->m_iStartRow; + int iSegmentEndRow = (next == m_vTimeSignatureSegments.end()) ? INT_MAX : next->GetRow(); int iRowsPerMeasureThisSegment = iter->GetNoteRowsPerMeasure(); - if( iNoteRow >= iter->m_iStartRow ) + if( iNoteRow >= iter->GetRow() ) { // iNoteRow lands in this segment - int iNumRowsThisSegment = iNoteRow - iter->m_iStartRow; + int iNumRowsThisSegment = iNoteRow - iter->GetRow(); int iNumMeasuresThisSegment = (iNumRowsThisSegment) / iRowsPerMeasureThisSegment; // don't round up iMeasureIndexOut += iNumMeasuresThisSegment; iBeatIndexOut = iNumRowsThisSegment / iRowsPerMeasureThisSegment; @@ -1617,7 +1635,7 @@ void TimingData::NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, i else { // iNoteRow lands after this segment - int iNumRowsThisSegment = iSegmentEndRow - iter->m_iStartRow; + int iNumRowsThisSegment = iSegmentEndRow - iter->GetRow(); int iNumMeasuresThisSegment = (iNumRowsThisSegment + iRowsPerMeasureThisSegment - 1) / iRowsPerMeasureThisSegment; // round up iMeasureIndexOut += iNumMeasuresThisSegment; } @@ -1685,8 +1703,8 @@ public: vector vLabels; FOREACH_CONST( LabelSegment, p->m_LabelSegments, seg ) { - const float fStartRow = NoteRowToBeat(seg->m_iStartRow); - const RString sLabel = seg->m_sLabel; + const float fStartRow = seg->GetBeat(); + const RString sLabel = seg->GetLabel(); vLabels.push_back( ssprintf("%f=%s", fStartRow, sLabel.c_str()) ); } LuaHelpers::CreateTableFromArray(vLabels, L); @@ -1697,7 +1715,7 @@ public: vector vBPMs; FOREACH_CONST( BPMSegment, p->m_BPMSegments, seg ) { - const float fStartRow = NoteRowToBeat(seg->m_iStartRow); + const float fStartRow = seg->GetBeat(); const float fBPM = seg->GetBPM(); vBPMs.push_back( ssprintf("%f=%f", fStartRow, fBPM) ); } diff --git a/src/TimingData.h b/src/TimingData.h index e65bcfbf16..ff876a9c5f 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -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. */ diff --git a/src/TimingSegments.cpp b/src/TimingSegments.cpp new file mode 100644 index 0000000000..8d6db81913 --- /dev/null +++ b/src/TimingSegments.cpp @@ -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(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. + */ diff --git a/src/TimingSegments.h b/src/TimingSegments.h new file mode 100644 index 0000000000..eedf256c62 --- /dev/null +++ b/src/TimingSegments.h @@ -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! + */ +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 + 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 +struct TimingSegment: public BaseTimingSegment +{ + + TimingSegment(): BaseTimingSegment() {}; + TimingSegment(const DerivedSegment &other): BaseTimingSegment(other) {}; + + template + 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(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(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 +{ + /** + * @brief Create a simple Fake Segment with default values. + * + * It is best to override the values as soon as possible. + */ + FakeSegment(): + TimingSegment(-1), lengthBeats(-1) {}; + + /** + * @brief Create a copy of another Fake Segment. + * @param other the other fake segment + */ + FakeSegment(const FakeSegment &other): + TimingSegment(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 + FakeSegment( StartType s, LengthType r ): + TimingSegment(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 +{ + /** + * @brief Create a simple Warp Segment with default values. + * + * It is best to override the values as soon as possible. + */ + WarpSegment(): + TimingSegment(), lengthBeats(-1) {}; + + /** + * @brief Create a copy of another Warp Segment. + * @param other the other warp segment + */ + WarpSegment(const WarpSegment &other): + TimingSegment(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 + WarpSegment( StartType s, LengthType r ): + TimingSegment(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 +{ + /** + * @brief Creates a simple Tickcount Segment with default values. + * + * It is best to override the values as soon as possible. + */ + TickcountSegment(): + TimingSegment(), ticks(4) {}; + + /** + * @brief Create a copy of another Tickcount Segment. + * @param other the other tickcount segment + */ + TickcountSegment(const TickcountSegment &other): + TimingSegment(other), + ticks(other.GetTicks()) {}; + + /** + * @brief Creates a TickcountSegment with specified values. + * @param s the starting row / beat. */ + template + TickcountSegment( StartType s ): + TimingSegment(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 + TickcountSegment( StartType s, int t ): + TimingSegment(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 +{ + /** + * @brief Creates a simple Combo Segment with default values. + * + * It is best to override the values as soon as possible. + */ + ComboSegment() : + TimingSegment(), combo(1) { } + + ComboSegment(const ComboSegment &other) : + TimingSegment(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 + ComboSegment( StartType s, int t ): + TimingSegment(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 +{ + /** + * @brief Creates a simple Label Segment with default values. + * + * It is best to override the values as soon as possible. + */ + LabelSegment() : + TimingSegment(), label("") { } + + LabelSegment(const LabelSegment &other) : + TimingSegment(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 + LabelSegment( StartType s, RString l ): + TimingSegment(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 +{ + /** + * @brief Creates a simple BPM Segment with default values. + * + * It is best to override the values as soon as possible. + */ + BPMSegment() : + TimingSegment(-1), bps(-1.0f) { } + + BPMSegment(const BPMSegment &other) : + TimingSegment(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 + BPMSegment( StartType s, float bpm ): + TimingSegment(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 +{ + /** + * @brief Creates a simple Time Signature Segment with default values. + */ + TimeSignatureSegment(): + TimingSegment(), + numerator(4), denominator(4) { } + + TimeSignatureSegment(const TimeSignatureSegment &other) : + TimingSegment(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 + TimeSignatureSegment( StartType s, int n ): + TimingSegment(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 + TimeSignatureSegment( StartType s, int n, int d ): + TimingSegment(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 +{ + /** @brief Sets up the SpeedSegment with default values. */ + SpeedSegment(): + TimingSegment(0), + ratio(1), length(0), unit(0) {} + + SpeedSegment(const SpeedSegment &other) : + TimingSegment(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 + SpeedSegment( StartType s, float p): + TimingSegment(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 + SpeedSegment(StartType s, float p, float w): + TimingSegment(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 + SpeedSegment(StartType s, float p, float w, unsigned short k): + TimingSegment(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 +{ + /** @brief Sets up the ScrollSegment with default values. */ + ScrollSegment(): TimingSegment(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 + ScrollSegment( StartType s, float p): + TimingSegment(max((StartType)0, s)), + ratio(p) {} + + ScrollSegment(const ScrollSegment &other) : + TimingSegment(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. + */