From 36f728d88e6378c798df4a76a2a8637d2f3c3108 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 19:22:11 -0400 Subject: [PATCH 01/40] Start of a new branch "warps". Ensure that all warps are forward facing for now. --- src/TimingData.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TimingData.h b/src/TimingData.h index 655a9087fb..6e9dec85b1 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -328,8 +328,8 @@ struct WarpSegment * @param s the starting row of this segment. * @param r the row to warp to. */ - WarpSegment( int s, int r ): m_iStartRow(max(0, s)), - m_fWarpBeats(max(0, NoteRowToBeat(r))) {} + WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r)), + m_fWarpBeats(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @brief Creates a Warp Segment with the specified starting row and beat to warp to. * @param s the starting row of this segment. From 5287e730814445b2505b08a9fac5987933719332 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 19:36:43 -0400 Subject: [PATCH 02/40] [warps] ...yeah, whoops. --- src/TimingData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TimingData.h b/src/TimingData.h index 6e9dec85b1..c03d67965b 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -328,7 +328,7 @@ struct WarpSegment * @param s the starting row of this segment. * @param r the row to warp to. */ - WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r)), + WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), m_fWarpBeats(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @brief Creates a Warp Segment with the specified starting row and beat to warp to. From f6acec176e0ec141373f6ec6695f1b9c1481c126 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 19:44:47 -0400 Subject: [PATCH 03/40] [warps] Warnings are getting in my way... --- src/LuaManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index 65796fcbac..e61352d9c0 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -864,8 +864,8 @@ void LuaHelpers::ParseCommandList( Lua *L, const RString &sCommands, const RStri FOREACH_CONST( Command, cmds.v, c ) { const Command& cmd = (*c); - RString sName = cmd.GetName(); - s << "\tself:" << sName << "("; + RString local_sName = cmd.GetName(); + s << "\tself:" << local_sName << "("; for( unsigned i=1; i Date: Thu, 24 Mar 2011 19:47:04 -0400 Subject: [PATCH 04/40] [warps] More setting up. --- src/NotesLoaderSSC.h | 3 +++ src/Song.cpp | 2 +- src/Song.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/NotesLoaderSSC.h b/src/NotesLoaderSSC.h index ae8f00bc9c..ff44a23cb5 100644 --- a/src/NotesLoaderSSC.h +++ b/src/NotesLoaderSSC.h @@ -21,7 +21,10 @@ enum SSCLoadingStates NUM_SSCLoadingStates /**< The number of states used. */ }; +/** @brief The version where fakes started to be used as a radar category. */ const float VERSION_RADAR_FAKE = 0.53f; +/** @brief The version where WarpSegments started to be utilized. */ +const float VERSION_WARP_SEGMENT = 0.56f; /** * @brief The SSCLoader handles all of the parsing needed for .ssc files. diff --git a/src/Song.cpp b/src/Song.cpp index ff686d6e25..b9d15c3ea8 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 166; +const int FILE_CACHE_VERSION = 167; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; diff --git a/src/Song.h b/src/Song.h index 74d1159b73..4e90fe3c18 100644 --- a/src/Song.h +++ b/src/Song.h @@ -17,7 +17,7 @@ struct lua_State; struct BackgroundChange; /** @brief The version of the .ssc file format. */ -const static float STEPFILE_VERSION_NUMBER = 0.55f; +const static float STEPFILE_VERSION_NUMBER = 0.56f; /** @brief How many edits for this song can each profile have? */ const int MAX_EDITS_PER_SONG_PER_PROFILE = 5; From 42d73895abff35ecc6db916895930240f7ae6644 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 19:51:46 -0400 Subject: [PATCH 05/40] [warps] Prepare the writer. --- src/NotesWriterSSC.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index c736104ae8..3f6acabab2 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -144,7 +144,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) } f.PutLine( ";" ); - /* + f.Write( "#WARPS:" ); for( unsigned i=0; i asWarpValues; + for( unsigned i=0; i asTimeSigValues; FOREACH_CONST( TimeSignatureSegment, in.m_Timing.m_vTimeSignatureSegments, iter ) From 9d456125a1b27026b5e95fe5485df3a25572e38e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 19:58:36 -0400 Subject: [PATCH 06/40] [warps] Load the warps. Now, the fun part...implementation. --- src/NotesLoaderSSC.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 3901ecde6e..6a98aa0acd 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -485,6 +485,35 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach } } } + + else if( sValueName=="WARPS" ) + { + vector arrayWarpExpressions; + split( sParams[1], ",", arrayWarpExpressions ); + + for( unsigned b=0; b arrayWarpValues; + split( arrayWarpExpressions[b], "=", arrayWarpValues ); + // XXX: Hard to tell which file caused this. + if( arrayWarpValues.size() != 2 ) + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", + sValueName.c_str(), arrayWarpExpressions[b].c_str() ); + continue; + } + + const float fBeat = StringToFloat( arrayWarpValues[0] ); + const float fNewBeat = StringToFloat( arrayWarpValues[1] ); + + if(fNewBeat > fBeat) + out.m_Timing.AddWarpSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat) ); + else + { + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat ); + } + } + } else if( sValueName=="TIMESIGNATURES" ) { From 35a880f2ee43ba4b5e67875e3d2699b77b99fd59 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 20:09:20 -0400 Subject: [PATCH 07/40] [warps] Restore this function for consistency. --- src/Song.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Song.h b/src/Song.h index 4e90fe3c18..d9b1d18c1f 100644 --- a/src/Song.h +++ b/src/Song.h @@ -307,7 +307,7 @@ public: void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); } void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); } - //void AddWarpSegment( const WarpSegment &seg ) { m_Timing.AddWarpSegment( seg ); } + void AddWarpSegment( const WarpSegment &seg ) { m_Timing.AddWarpSegment( seg ); } void AddBackgroundChange( BackgroundLayer blLayer, BackgroundChange seg ); void AddForegroundChange( BackgroundChange seg ); void AddLyricSegment( LyricSegment seg ); From e592be406b39d8dc5459f30784b673db15b06bba Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 20:21:43 -0400 Subject: [PATCH 08/40] [warps] More prep work, add lua binding. --- src/TimingData.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 9704ac00c3..7eb82e36eb 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -683,6 +683,14 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) stop.m_iStartRow += iRowsToAdd; } + for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) + { + WarpSegment &warp = m_WarpSegments[i]; + if (warp.m_iStartRow < iStartRow ) + continue; + warp.m_iStartRow += iRowsToAdd; + } + for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) { TimeSignatureSegment &time = m_vTimeSignatureSegments[i]; @@ -764,6 +772,23 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) stop.m_iStartRow -= iRowsToDelete; } + for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) + { + WarpSegment &warp = m_WarpSegments[i]; + + if( warp.m_iStartRow < iStartRow ) + continue; + + if( warp.m_iStartRow < iStartRow+iRowsToDelete ) + { + m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); + --i; + continue; + } + + warp.m_iStartRow -= iRowsToDelete; + } + for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) { TimeSignatureSegment &time = m_vTimeSignatureSegments[i]; @@ -891,6 +916,7 @@ class LunaTimingData: public Luna public: static int HasStops( T* p, lua_State *L ) { lua_pushboolean(L, p->HasStops()); return 1; } static int HasBPMChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasBpmChanges()); return 1; } + static int HasWarps( T* p, lua_State *L ) { lua_pushboolean(L, p->HasWarps()); return 1; } static int GetStops( T* p, lua_State *L ) { vector vStops; @@ -965,6 +991,7 @@ public: { ADD_METHOD( HasStops ); ADD_METHOD( HasBPMChanges ); + ADD_METHOD( HasWarps ); ADD_METHOD( GetStops ); ADD_METHOD( GetDelays ); ADD_METHOD( GetBPMs ); From 621dfa050ee97700edbeb3f5e77a8e7768ce4478 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 24 Mar 2011 20:41:35 -0400 Subject: [PATCH 09/40] [warps] Prepare text code. --- Themes/_fallback/metrics.ini | 3 +++ src/NoteField.cpp | 33 +++++++++++++++++++++++++++++++++ src/NoteField.h | 1 + 3 files changed, 37 insertions(+) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index b37ce668a6..5fdc7704e8 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -963,6 +963,7 @@ RoutineNoteSkinP2=RoutineSkinP2() BPMColor=color("1,0,0,1") StopColor=color("0.8,0.8,0,1") DelayColor=color("0,0.8,0.8,1") +WarpColor=color("1,0,0.5,1") TimeSignatureColor=color("1,0.55,0,1") TickcountColor=color("0,1,0,1") ComboColor=color("0.55,1,0,1") @@ -970,6 +971,7 @@ ComboColor=color("0.55,1,0,1") BPMIsLeftSide=true StopIsLeftSide=true DelayIsLeftSide=true +WarpIsLeftSide=false TimeSignatureIsLeftSide=true TickcountIsLeftSide=false ComboIsLeftSide=false @@ -977,6 +979,7 @@ ComboIsLeftSide=false BPMOffsetX=60 StopOffsetX=10 DelayOffsetX=10 +WarpOffsetX=60 TimeSignatureOffsetX=30 TickcountOffsetX=10 ComboOffsetX=30 diff --git a/src/NoteField.cpp b/src/NoteField.cpp index d809cf7242..08d86b9441 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -422,18 +422,21 @@ void NoteField::DrawAreaHighlight( int iStartBeat, int iEndBeat ) static ThemeMetric BPM_COLOR ( "NoteField", "BPMColor" ); static ThemeMetric STOP_COLOR ( "NoteField", "StopColor" ); static ThemeMetric DELAY_COLOR ( "NoteField", "DelayColor" ); +static ThemeMetric WARP_COLOR ( "NoteField", "WarpColor" ); static ThemeMetric TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" ); static ThemeMetric TICKCOUNT_COLOR ( "NoteField", "TickcountColor" ); static ThemeMetric COMBO_COLOR ( "NoteField", "ComboColor" ); static ThemeMetric BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" ); static ThemeMetric STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" ); static ThemeMetric DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" ); +static ThemeMetric WARP_IS_LEFT_SIDE ( "NoteField", "WarpIsLeftSide" ); static ThemeMetric TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" ); static ThemeMetric TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" ); static ThemeMetric COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" ); static ThemeMetric BPM_OFFSETX ( "NoteField", "BPMOffsetX" ); static ThemeMetric STOP_OFFSETX ( "NoteField", "StopOffsetX" ); static ThemeMetric DELAY_OFFSETX ( "NoteField", "DelayOffsetX" ); +static ThemeMetric WARP_OFFSETX ( "NoteField", "WarpOffsetX" ); static ThemeMetric TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" ); static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); @@ -481,6 +484,23 @@ void NoteField::DrawFreezeText( const float fBeat, const float fSecs, const floa m_textMeasureNumber.Draw(); } +void NoteField::DrawWarpText( const float fBeat, const float fNewBeat ) +{ + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); + const float xBase = GetWidth()/2.f; + const float xOffset = WARP_OFFSETX * fZoom; + + m_textMeasureNumber.SetZoom( fZoom ); + m_textMeasureNumber.SetHorizAlign( WARP_IS_LEFT_SIDE ? align_right : align_left ); + m_textMeasureNumber.SetDiffuse( WARP_COLOR ); + m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); + m_textMeasureNumber.SetText( ssprintf("%.3f", fNewBeat) ); + m_textMeasureNumber.SetXY( (WARP_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); + m_textMeasureNumber.Draw(); +} + void NoteField::DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); @@ -770,6 +790,19 @@ void NoteField::DrawPrimitives() DrawFreezeText( fBeat, aStopSegments[i].m_fStopSeconds, aStopSegments[i].m_bDelay ); } } + + // Warp text + const vector &aWarpSegments = GAMESTATE->m_pCurSong->m_Timing.m_WarpSegments; + for( unsigned i=0; i= iFirstRowToDraw && + aWarpSegments[i].m_iStartRow <= iLastRowToDraw) + { + float fBeat = NoteRowToBeat(aWarpSegments[i].m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawWarpText( fBeat, aWarpSegments[i].m_fWarpBeats ); + } + } // Time Signature text const vector &vTimeSignatureSegments = GAMESTATE->m_pCurSong->m_Timing.m_vTimeSignatureSegments; diff --git a/src/NoteField.h b/src/NoteField.h index 0c4f03c990..08a83e11aa 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -57,6 +57,7 @@ protected: void DrawAreaHighlight( int iStartBeat, int iEndBeat ); void DrawBPMText( const float fBeat, const float fBPM ); void DrawFreezeText( const float fBeat, const float fBPM, const float bDelay ); + void DrawWarpText( const float fBeat, const float fNewBeat ); void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ); void DrawTickcountText( const float fBeat, int iTicks ); void DrawComboText( const float fBeat, int iCombo ); From db429e11cc44ff17c58cc8ed7872b961e323a8d2 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 00:54:33 -0400 Subject: [PATCH 10/40] [warps] View the list. 1) Add functions similar to the other Segments. 2) Use a better named member variable. 3) TimingData cleanup. --- src/NoteField.cpp | 2 +- src/NotesWriterSSC.cpp | 2 +- src/TimingData.cpp | 112 ++++++++++++++++++++++++++++------------- src/TimingData.h | 64 ++++++++++++++++++----- 4 files changed, 130 insertions(+), 50 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 08d86b9441..241c782310 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -800,7 +800,7 @@ void NoteField::DrawPrimitives() { float fBeat = NoteRowToBeat(aWarpSegments[i].m_iStartRow); if( IS_ON_SCREEN(fBeat) ) - DrawWarpText( fBeat, aWarpSegments[i].m_fWarpBeats ); + DrawWarpText( fBeat, aWarpSegments[i].m_fEndBeat ); } } diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3f6acabab2..36c170b475 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -150,7 +150,7 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) { const WarpSegment &ws = out.m_Timing.m_WarpSegments[i]; - f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(ws.m_iStartRow), ws.m_fWarpBeats ) ); + f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(ws.m_iStartRow), ws.m_fEndBeat ) ); if( i != out.m_Timing.m_WarpSegments.size()-1 ) f.Write( "," ); } diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 7eb82e36eb..a8eaaf2704 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -150,12 +150,30 @@ void TimingData::SetTimeSignatureDenominatorAtRow( int iRow, int iDenominator ) SetTimeSignatureAtRow( iRow, GetTimeSignatureSegmentAtBeat( NoteRowToBeat( iRow ) ).m_iNumerator, iDenominator ); } -/* -void TimingData::SetWarpAtRow( int iRowAt, float fLengthBeats ) +void TimingData::SetWarpAtRow( int iRow, float fNew ) { - // todo: code this -aj + unsigned i; + for( i=0; i 0 && NoteRowToBeat(iRow) < fNew; + if( i == m_WarpSegments.size() ) + { + if( valid ) + { + AddWarpSegment( WarpSegment(iRow, fNew) ); + } + } + else + { + if( valid ) + { + m_WarpSegments[i].m_fEndBeat = fNew; + } + else + m_WarpSegments.erase( m_WarpSegments.begin()+i, m_WarpSegments.begin()+i+1 ); + } } -*/ /* Change an existing Tickcount segment, merge identical segments together or insert a new one. */ void TimingData::SetTickcountAtRow( int iRow, int iTicks ) @@ -229,13 +247,13 @@ int TimingData::GetComboAtRow( int iNoteRow ) const return m_ComboSegments[GetComboSegmentIndexAtRow( iNoteRow )].m_iCombo; } -int TimingData::GetWarpToRow( int iWarpBeginRow ) const +float TimingData::GetWarpAtRow( int iWarpRow ) const { for( unsigned i=0; i iNoteRow ) break; - return (int)i; + return static_cast(i); } int TimingData::GetStopSegmentIndexAtRow( int iNoteRow, bool bDelay ) const @@ -308,16 +326,50 @@ int TimingData::GetStopSegmentIndexAtRow( int iNoteRow, bool bDelay ) const if( s.m_iStartRow > iNoteRow && s.m_bDelay == bDelay ) break; } - return (int)i; + return static_cast(i); +} + +int TimingData::GetWarpSegmentIndexAtRow( int iNoteRow ) const +{ + unsigned i; + for( i=0; i iNoteRow ) + break; + } + return static_cast(i); } int TimingData::GetTimeSignatureSegmentIndexAtRow( int iRow ) const { - int i; - for (i=0; i < (int)(m_vTimeSignatureSegments.size()) - 1; i++ ) + unsigned i; + for (i=0; i < m_vTimeSignatureSegments.size() - 1; i++ ) if( m_vTimeSignatureSegments[i+1].m_iStartRow > iRow ) break; - return i; + return static_cast(i); +} + +int TimingData::GetComboSegmentIndexAtRow( int iRow ) const +{ + unsigned i; + for( i=0; i iRow ) + break; + } + return static_cast(i); +} + +BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow ) +{ + static BPMSegment empty; + if( m_BPMSegments.empty() ) + return empty; + + int i = GetBPMSegmentIndexAtRow( iNoteRow ); + return m_BPMSegments[i]; } TimeSignatureSegment& TimingData::GetTimeSignatureSegmentAtRow( int iRow ) @@ -339,28 +391,6 @@ int TimingData::GetTimeSignatureDenominatorAtRow( int iRow ) return GetTimeSignatureSegmentAtRow( iRow ).m_iDenominator; } -int TimingData::GetComboSegmentIndexAtRow( int iRow ) const -{ - unsigned i; - for( i=0; i iRow ) - break; - } - return (int)i; -} - -BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow ) -{ - static BPMSegment empty; - if( m_BPMSegments.empty() ) - return empty; - - int i = GetBPMSegmentIndexAtRow( iNoteRow ); - return m_BPMSegments[i]; -} - ComboSegment& TimingData::GetComboSegmentAtRow( int iRow ) { unsigned i; @@ -380,6 +410,16 @@ StopSegment& TimingData::GetStopSegmentAtRow( int iNoteRow, bool bDelay ) return m_StopSegments[i]; } +WarpSegment& TimingData::GetWarpSegmentAtRow( int iRow ) +{ + static WarpSegment empty; + if( m_WarpSegments.empty() ) + return empty; + + int i = GetWarpSegmentIndexAtRow( iRow ); + return m_WarpSegments[i]; +} + int TimingData::GetTickcountSegmentIndexAtRow( int iRow ) const { int i; @@ -478,7 +518,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float */ // the freeze segment is <= current time - //fElapsedTime -= m_WarpSegments[j].m_fWarpBeats; + //fElapsedTime -= m_WarpSegments[j].m_fEndBeat; // this warp lies within this BPMSegment. /* @@ -492,7 +532,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float bFreezeOut = false; bDelayOut = false; iWarpBeginOut = m_WarpSegments[j].m_iStartRow; - fWarpLengthOut = m_WarpSegments[j].m_fWarpBeats; + fWarpLengthOut = m_WarpSegments[j].m_fEndBeat; return; } */ diff --git a/src/TimingData.h b/src/TimingData.h index c03d67965b..b2300d61a1 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -322,21 +322,21 @@ struct WarpSegment * * It is best to override the values as soon as possible. */ - WarpSegment() : m_iStartRow(-1), m_fWarpBeats(-1) { } + WarpSegment() : m_iStartRow(-1), m_fEndBeat(-1) { } /** * @brief Creates a Warp Segment with the specified starting row and row to warp to. * @param s the starting row of this segment. * @param r the row to warp to. */ WarpSegment( int s, int r ): m_iStartRow(max(0, (s < r ? s : r))), - m_fWarpBeats(max(0, NoteRowToBeat((r > s ? r : s)))) {} + m_fEndBeat(max(0, NoteRowToBeat((r > s ? r : s)))) {} /** * @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 beat to warp to. */ WarpSegment( int s, float b ): m_iStartRow(max(0, s)), - m_fWarpBeats(max(0, b)) {} + m_fEndBeat(max(0, b)) {} /** * @brief The row in which the WarpSegment activates. */ @@ -344,7 +344,7 @@ struct WarpSegment /** * @brief The beat to warp to. */ - float m_fWarpBeats; + float m_fEndBeat; /** * @brief Compares two WarpSegments to see if they are equal to each other. * @param other the other WarpSegment to compare to. @@ -353,7 +353,7 @@ struct WarpSegment bool operator==( const WarpSegment &other ) const { COMPARE( m_iStartRow ); - COMPARE( m_fWarpBeats ); + COMPARE( m_fEndBeat ); return true; } /** @@ -370,7 +370,7 @@ struct WarpSegment bool operator<( const WarpSegment &other ) const { return m_iStartRow < other.m_iStartRow || - ( m_iStartRow == other.m_iStartRow && m_fWarpBeats < other.m_fWarpBeats ); + ( m_iStartRow == other.m_iStartRow && m_fEndBeat < other.m_fEndBeat ); } /** * @brief Compares two WarpSegments to see if one is less than or equal to the other. @@ -875,19 +875,59 @@ public: * @param seg the new TimeSignatureSegment. */ void AddTimeSignatureSegment( const TimeSignatureSegment &seg ); - /** - * @brief Determine the row to warp to. - * @param iWarpBeginRow The row you start on. - * @return the row you warp to. + * @brief Determine the beat to warp to. + * @param iRow The row you start on. + * @return the beat you warp to. */ - int GetWarpToRow( int iWarpBeginRow ) const; + float GetWarpAtRow( int iRow ) const; + /** + * @brief Determine the beat to warp to. + * @param fBeat The beat you start on. + * @return the beat you warp to. + */ + float GetWarpAtBeat( float fBeat ) const { return GetWarpAtRow( BeatToNoteRow( fBeat ) ); } + /** + * @brief Set the beat to warp to given a starting row. + * @param iRow The row to start on. + * @param fNew The destination beat. + */ + void SetWarpAtRow( int iRow, float fNew ); + /** + * @brief Set the beat to warp to given a starting beat. + * @param fBeat The beat to start on. + * @param fNew The destination beat. + */ + void SetWarpAtBeat( float fBeat, float fNew ) { SetWarpAtRow( BeatToNoteRow( fBeat ), fNew ); } + /** + * @brief Retrieve the WarpSegment at the specified row. + * @param iRow the row to focus on. + * @return the WarpSegment in question. + */ + WarpSegment& GetWarpSegmentAtRow( int iRow ); + /** + * @brief Retrieve the WarpSegment at the specified beat. + * @param fBeat the beat to focus on. + * @return the WarpSegment in question. + */ + WarpSegment& GetWarpSegmentAtBeat( float fBeat ) { return GetWarpSegmentAtRow( BeatToNoteRow( fBeat ) ); } + /** + * @brief Retrieve the index of the WarpSegment at the specified row. + * @param iRow the row to focus on. + * @return the index in question. + */ + int GetWarpSegmentIndexAtRow( int iRow ) const; + /** + * @brief Retrieve the index of the WarpSegment at the specified beat. + * @param fBeat the beat to focus on. + * @return the index in question. + */ + int GetWarpSegmentIndexAtBeat( float fBeat ) const { return GetWarpSegmentIndexAtRow( BeatToNoteRow( fBeat ) ); } /** * @brief Add the WarpSegment to the TimingData. * @param seg the new WarpSegment. */ void AddWarpSegment( const WarpSegment &seg ); - /** * @brief Retrieve the Tickcount at the given row. * @param iNoteRow the row in question. From 92e3ab338d7f64fa13a66d90bbe39c8b5bc677e7 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 01:52:14 -0400 Subject: [PATCH 11/40] [warps] More consistent naming. Now to make changes... --- src/GameState.cpp | 17 +++++++++++------ src/GameState.h | 5 +++-- src/Player.cpp | 12 ++++++------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index c1f5b0b0f4..7bceea64db 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -897,7 +897,7 @@ void GameState::ResetMusicStatistics() m_bFreeze = false; m_bDelay = false; m_iWarpBeginRow = -1; // Set to -1 because some song may want to warp to row 0. -aj - m_fWarpLength = -1; // Set when a warp is encountered. also see above. -aj + m_fWarpDestination = -1; // Set when a warp is encountered. also see above. -aj m_fMusicSecondsVisible = 0; m_fSongBeatVisible = 0; Actor::SetBGMTime( 0, 0, 0, 0 ); @@ -943,7 +943,7 @@ void GameState::ResetStageStatistics() } static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); -// todo: modify for warps -aj + void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) { if( !timestamp.IsZero() ) @@ -957,16 +957,21 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) ); */ - timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpLength ); + timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpDestination ); // "Crash reason : -243478.890625 -48695.773438" ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); //if( m_iWarpBeginRow != -1 || m_iWarpEndRow == -1 ) - if( m_iWarpBeginRow != -1 && m_fWarpLength > 0.0f ) + + if( m_iWarpBeginRow != -1 && m_fWarpDestination > 0.0f ) { + float fWarpLength = m_fWarpDestination-NoteRowToBeat(m_iWarpBeginRow); // There is a warp in this section. - LOG->Trace("warp at %i lasts for %f, jumps to %i",m_iWarpBeginRow,m_fWarpLength,m_iWarpBeginRow+BeatToNoteRow(m_fWarpLength)); - //fPositionSeconds += (m_fWarpLength * m_fCurBPS); + LOG->Trace("warp at row %i lasts for %f beats, jumps to row %i", + m_iWarpBeginRow, + fWarpLength, + BeatToNoteRow(m_fWarpDestination)); + fPositionSeconds += (fWarpLength * m_fCurBPS); } m_fMusicSeconds = fPositionSeconds; diff --git a/src/GameState.h b/src/GameState.h index d26fe5b308..406e4784b1 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -208,9 +208,10 @@ public: bool m_bFreeze; /** @brief A flag to determine if we're in the middle of a delay (Pump style stop). */ bool m_bDelay; - // used for warping: + /** @brief The row used to start a warp. */ int m_iWarpBeginRow; - float m_fWarpLength; + /** @brief The beat to warp to afterwards. */ + float m_fWarpDestination; RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update BroadcastOnChange m_bGameplayLeadIn; diff --git a/src/Player.cpp b/src/Player.cpp index 2f505d391a..92ef0dc81d 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2551,8 +2551,8 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) if( !NeedsTapJudging(tn) ) continue; - // warp hackery - if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() <= (GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) ) + // Ignore all notes that are skipped via WARPS. + if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) continue; if( tn.type == TapNote::mine ) @@ -2570,7 +2570,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) { // warp hackery: don't score notes within the warp region. // (Only useful when QuirksMode is enabled.) -aj - if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() <= (GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) ) + if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) continue; tn.result.tns = TNS_Miss; @@ -2593,7 +2593,7 @@ void Player::UpdateJudgedRows() // if row is within a warp section, ignore it. -aj if( iRow >= GAMESTATE->m_iWarpBeginRow && - iRow <= (GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) ) + iRow < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) continue; if( iLastSeenRow != iRow ) @@ -2929,7 +2929,7 @@ void Player::HandleTapRowScore( unsigned row ) // more warp hackery. -aj if( row >= (unsigned)GAMESTATE->m_iWarpBeginRow && - row <= (unsigned)(GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) ) + row < (unsigned)(BeatToNoteRow(GAMESTATE->m_fWarpDestination)) ) return; if( GAMESTATE->m_bDemonstrationOrJukebox ) @@ -3034,7 +3034,7 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH // more warp hackery. -aj if( iRow >= GAMESTATE->m_iWarpBeginRow && - iRow <= (GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) ) + iRow < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) return; // don't accumulate combo if AutoPlay is on. From 4316579e897b6730abfc178dcbcd77d0d4e67b2f Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Fri, 25 Mar 2011 23:19:31 +0700 Subject: [PATCH 12/40] [warps] my attempt at making warps work. see commit message. + TimingData: rewrote GetBeatAndBPSFromElapsedTimeNoOffset and GetBeatFromElapsedTimeNoOffset to make it simpler and compute times correctly, by going through 3 arrays at the same time. + TimingData: added TimingData::IsWarpAtRow(int) just in case. + The skipping part is now handled by TimingData. Current issues: + the rewritten function does not check if the vectors are sorted. + if you press the notes after the skip before the skip is reached, the notes in the warp range got hit instead because m_iWarpBeginRow was not set before the warp is reached. + the notes after the skipped part are not judged if hit before the warp is reached and the warp is big enough. --- src/GameState.cpp | 4 +- src/Player.cpp | 9 +- src/TimingData.cpp | 357 +++++++++++++++++++++++---------------------- src/TimingData.h | 8 +- 4 files changed, 196 insertions(+), 182 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 7bceea64db..581c882b08 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -962,7 +962,8 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); //if( m_iWarpBeginRow != -1 || m_iWarpEndRow == -1 ) - + + /* if( m_iWarpBeginRow != -1 && m_fWarpDestination > 0.0f ) { float fWarpLength = m_fWarpDestination-NoteRowToBeat(m_iWarpBeginRow); @@ -973,6 +974,7 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti BeatToNoteRow(m_fWarpDestination)); fPositionSeconds += (fWarpLength * m_fCurBPS); } + */ m_fMusicSeconds = fPositionSeconds; diff --git a/src/Player.cpp b/src/Player.cpp index 92ef0dc81d..da11ff8cdf 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2522,8 +2522,8 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) { //LOG->Trace( "Steps::UpdateTapNotesMissedOlderThan(%f)", fMissIfOlderThanThisBeat ); int iMissIfOlderThanThisRow; + const float fEarliestTime = GAMESTATE->m_fMusicSeconds - fMissIfOlderThanSeconds; { - const float fEarliestTime = GAMESTATE->m_fMusicSeconds - fMissIfOlderThanSeconds; bool bFreeze, bDelay; float fMissIfOlderThanThisBeat; float fThrowAway; @@ -2550,7 +2550,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) if( !NeedsTapJudging(tn) ) continue; - + // Ignore all notes that are skipped via WARPS. if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) continue; @@ -2568,11 +2568,6 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) } else { - // warp hackery: don't score notes within the warp region. - // (Only useful when QuirksMode is enabled.) -aj - if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) - continue; - tn.result.tns = TNS_Miss; } } diff --git a/src/TimingData.cpp b/src/TimingData.cpp index a8eaaf2704..ea0c30b937 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -341,6 +341,18 @@ int TimingData::GetWarpSegmentIndexAtRow( int iNoteRow ) const return static_cast(i); } +bool TimingData::IsWarpAtRow( int iNoteRow ) const +{ + unsigned i; + for( i=0; i= iNoteRow ) + return iNoteRow < BeatToNoteRow(m_WarpSegments[i].m_fEndBeat); + } + return false; +} + int TimingData::GetTimeSignatureSegmentIndexAtRow( int iRow ) const { unsigned i; @@ -451,150 +463,116 @@ void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatO GetBeatAndBPSFromElapsedTimeNoOffset( fElapsedTime, fBeatOut, fBPSOut, bFreezeOut, bDelayOut, iWarpBeginOut, fWarpLengthOut ); } -void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const +enum { -// LOG->Trace( "GetBeatAndBPSFromElapsedTime( fElapsedTime = %f )", fElapsedTime ); - const float fTime = fElapsedTime; - fElapsedTime += m_fBeat0OffsetInSeconds; + FOUND_WARP, + FOUND_WARP_DESTINATION, + FOUND_BPM_CHANGE, + FOUND_STOP, + FOUND_MARKER, + NOT_FOUND +}; - for( unsigned i=0; i::const_iterator itBPMS = m_BPMSegments.begin(); + vector::const_iterator itWS = m_WarpSegments.begin(); + vector::const_iterator itSS = m_StopSegments.begin(); + + bFreezeOut = false; + bDelayOut = false; + + iWarpBeginOut = -1; + + int iLastRow = 0; + float fLastTime = -m_fBeat0OffsetInSeconds; + float fBPS = GetBPMAtRow(0) / 60.0; + + float bIsWarping = false; + float fWarpDestination = 0.0; + + for( ;; ) { - const int iStartRowThisSegment = m_BPMSegments[i].m_iStartRow; - const float fStartBeatThisSegment = NoteRowToBeat( iStartRowThisSegment ); - const bool bIsFirstBPMSegment = i==0; - const bool bIsLastBPMSegment = i==m_BPMSegments.size()-1; - const int iStartRowNextSegment = bIsLastBPMSegment ? MAX_NOTE_ROW : m_BPMSegments[i+1].m_iStartRow; - const float fStartBeatNextSegment = NoteRowToBeat( iStartRowNextSegment ); - const float fBPS = m_BPMSegments[i].m_fBPS; - - for( unsigned j=0; j= m_StopSegments[j].m_iStartRow ) - continue; - if( !bIsLastBPMSegment && m_StopSegments[j].m_iStartRow > iStartRowNextSegment ) - continue; - - // this freeze lies within this BPMSegment - const int iRowsBeatsSinceStartOfSegment = m_StopSegments[j].m_iStartRow - iStartRowThisSegment; - const float fBeatsSinceStartOfSegment = NoteRowToBeat(iRowsBeatsSinceStartOfSegment); - const float fFreezeStartSecond = fBeatsSinceStartOfSegment / fBPS; - - // modified for delays - if( !bIsDelay && fFreezeStartSecond >= fElapsedTime ) - break; - if( bIsDelay && fFreezeStartSecond > fElapsedTime ) - break; - - // the freeze segment is <= current time - fElapsedTime -= m_StopSegments[j].m_fStopSeconds; - - if( (fFreezeStartSecond >= fElapsedTime && !bIsDelay) || - (fFreezeStartSecond > fElapsedTime && bIsDelay) ) + iEventRow = BeatToNoteRow(fWarpDestination); + iEventType = FOUND_WARP_DESTINATION; + } + if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) + { + iEventRow = itWS->m_iStartRow; + iEventType = FOUND_WARP; + } + if( itBPMS != m_BPMSegments.end() && itBPMS->m_iStartRow < iEventRow ) + { + iEventRow = itBPMS->m_iStartRow; + iEventType = FOUND_BPM_CHANGE; + } + if( itSS != m_StopSegments.end() && itSS->m_iStartRow < iEventRow ) + { + iEventRow = itSS->m_iStartRow; + iEventType = FOUND_STOP; + } + if( iEventType == NOT_FOUND ) + { + break; + } + float fTimeToNextEvent = bIsWarping ? 0 : NoteRowToBeat( iEventRow - iLastRow ) / fBPS; + float fNextEventTime = fLastTime + fTimeToNextEvent; + if ( fElapsedTime < fNextEventTime ) + { + break; + } + fLastTime = fNextEventTime; + switch( iEventType ) + { + case FOUND_WARP_DESTINATION: + bIsWarping = false; + break; + case FOUND_WARP: + bIsWarping = true; + if( itWS->m_fEndBeat > fWarpDestination ) + { + fWarpDestination = itWS->m_fEndBeat; + } + iWarpBeginOut = iEventRow; + fWarpDestinationOut = fWarpDestination; + itWS ++; + break; + case FOUND_BPM_CHANGE: + fBPS = itBPMS->m_fBPS; + itBPMS ++; + break; + case FOUND_STOP: + fTimeToNextEvent = bIsWarping ? 0 : itSS->m_fStopSeconds; + fNextEventTime = fLastTime + fTimeToNextEvent; + const bool bIsDelay = itSS->m_bDelay; + if ( fElapsedTime < fNextEventTime ) { - // The time lies within the stop. - fBeatOut = NoteRowToBeat(m_StopSegments[j].m_iStartRow); - fBPSOut = fBPS; bFreezeOut = !bIsDelay; - bDelayOut = bIsDelay; - //iWarpBeginOut = -1; - //fWarpLengthOut = -1; + bDelayOut = bIsDelay; + fBeatOut = NoteRowToBeat( itSS->m_iStartRow ); + fBPSOut = fBPS; return; } + fLastTime = fNextEventTime; + itSS ++; + break; } - - // by this point we should have the warps in their own place. - for( unsigned j=0; j= m_WarpSegments[j].m_iStartRow ) - continue; - if( !bIsLastBPMSegment && m_WarpSegments[j].m_iStartRow > iStartRowNextSegment ) - continue; - - /* - const int iRowsBeatsSinceStartOfSegment = m_WarpSegments[j].m_iStartRow - iStartRowThisSegment; - const float fBeatsSinceStartOfSegment = NoteRowToBeat(iRowsBeatsSinceStartOfSegment); - const float fWarpStartSecond = fBeatsSinceStartOfSegment / fBPS; - */ - - // the freeze segment is <= current time - //fElapsedTime -= m_WarpSegments[j].m_fEndBeat; - - // this warp lies within this BPMSegment. - /* - if( fWarpStartSecond >= fElapsedTime ) - { - // this WarpSegment IS the current segment. - // don't know how to properly handle beatout -aj - //fBeatOut = NoteRowToBeat(m_WarpSegments[j].m_iStartRow); - fBeatOut = fStartBeatThisSegment + fElapsedTime*fBPS; - fBPSOut = m_BPMSegments[i+1].m_fBPS; - bFreezeOut = false; - bDelayOut = false; - iWarpBeginOut = m_WarpSegments[j].m_iStartRow; - fWarpLengthOut = m_WarpSegments[j].m_fEndBeat; - return; - } - */ - } - - const float fBeatsInThisSegment = fStartBeatNextSegment - fStartBeatThisSegment; - const float fSecondsInThisSegment = fBeatsInThisSegment / fBPS; - //if(fBPS < 0.0f) - /* - if(fStartBeatThisSegment == 445.500f || fStartBeatThisSegment == 449.500) - { - LOG->Trace( ssprintf("segment (beat %f) beats: %f / seconds: %f / BPS: %f",fStartBeatThisSegment,fBeatsInThisSegment,fSecondsInThisSegment,fBPS) ); - } - */ - if( bIsLastBPMSegment || fElapsedTime <= fSecondsInThisSegment ) - { - // this BPMSegment IS the current segment. - fBeatOut = fStartBeatThisSegment + fElapsedTime*fBPS; - fBPSOut = fBPS; - bFreezeOut = false; - bDelayOut = false; - //iWarpBeginOut; - //fWarpLengthOut; - return; - } - - // this BPMSegment is NOT the current segment. - fElapsedTime -= fSecondsInThisSegment; - // xxx: negative testing [aj] - /* - //if(fBPS < 0.0f) - if( (fStartBeatNextSegment >= 445.490f && fStartBeatNextSegment <= 453.72f) || fBPS < 0.0f ) - { - //LOG->Trace( ssprintf("beat %f is %f BPS (%f BPM)",fBeatOut,fBPSOut,fBPSOut*60.0f) ); - //LOG->Trace( ssprintf("start beat %f + elapsed time %f",fStartBeatThisSegment,fElapsedTime) ); - //LOG->Trace( ssprintf("elapsed time is now %f",fElapsedTime) ); - } - */ + iLastRow = iEventRow; } - // If we get here, something has gone wrong. Is everything sorted? - vector vBPMS = m_BPMSegments; - vector vSS = m_StopSegments; - vector vWS = m_WarpSegments; - vector vTSS = m_vTimeSignatureSegments; - vector vTS = m_TickcountSegments; - vector vCS = m_ComboSegments; - sort( vBPMS.begin(), vBPMS.end() ); - sort( vSS.begin(), vSS.end() ); - sort( vWS.begin(), vWS.end() ); - sort( vTSS.begin(), vTSS.end() ); - sort( vTS.begin(), vTS.end() ); - sort( vCS.begin(), vCS.end() ); - ASSERT_M( vBPMS == m_BPMSegments, "The BPM segments were not sorted!" ); - ASSERT_M( vSS == m_StopSegments, "The Stop segments were not sorted!" ); - ASSERT_M( vWS == m_WarpSegments, "The Warp segments were not sorted!" ); - ASSERT_M( vTSS == m_vTimeSignatureSegments, "The Time Signature segments were not sorted!" ); - ASSERT_M( vTS == m_TickcountSegments, "The Tickcount segments were not sorted!" ); - ASSERT_M( vCS == m_ComboSegments, "The Combo segments were not sorted!" ); - FAIL_M( ssprintf("Failed to find the appropriate segment for elapsed time %f.", fTime) ); + + fBeatOut = NoteRowToBeat( iLastRow ) + (fElapsedTime - fLastTime) * fBPS; + fBPSOut = fBPS; + } + + float TimingData::GetElapsedTimeFromBeat( float fBeat ) const { return TimingData::GetElapsedTimeFromBeatNoOffset( fBeat ) - PREFSMAN->m_fGlobalOffsetSeconds; @@ -602,53 +580,86 @@ float TimingData::GetElapsedTimeFromBeat( float fBeat ) const float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const { - float fElapsedTime = 0; - fElapsedTime -= m_fBeat0OffsetInSeconds; - int iRow = BeatToNoteRow(fBeat); - for( unsigned j=0; j::const_iterator itBPMS = m_BPMSegments.begin(); + vector::const_iterator itWS = m_WarpSegments.begin(); + vector::const_iterator itSS = m_StopSegments.begin(); + + int iLastRow = 0; + float fLastTime = -m_fBeat0OffsetInSeconds; + float fBPS = GetBPMAtRow(0) / 60.0; + + float bIsWarping = false; + float fWarpDestination = 0.0; + + for( ;; ) { - /* A traditional stop has the beat happening before the stop. (>=) - * A Pump delay acts differently: the pause is before the beat. (>) - */ - if( ( m_StopSegments[j].m_iStartRow >= iRow && !m_StopSegments[j].m_bDelay ) || - ( m_StopSegments[j].m_iStartRow > iRow && m_StopSegments[j].m_bDelay ) ) + int iEventRow = INT_MAX; + int iEventType = NOT_FOUND; + if( bIsWarping && BeatToNoteRow(fWarpDestination) < iEventRow ) + { + iEventRow = BeatToNoteRow(fWarpDestination); + iEventType = FOUND_WARP_DESTINATION; + } + if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) + { + iEventRow = itWS->m_iStartRow; + iEventType = FOUND_WARP; + } + if( itBPMS != m_BPMSegments.end() && itBPMS->m_iStartRow < iEventRow ) + { + iEventRow = itBPMS->m_iStartRow; + iEventType = FOUND_BPM_CHANGE; + } + if( itSS != m_StopSegments.end() && itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) + { + iEventRow = itSS->m_iStartRow; + iEventType = FOUND_STOP; + } + if( BeatToNoteRow(fBeat) < iEventRow ) + { + iEventRow = BeatToNoteRow(fBeat); + iEventType = FOUND_MARKER; + } + if( itSS != m_StopSegments.end() && !itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) + { + iEventRow = itSS->m_iStartRow; + iEventType = FOUND_STOP; + } + float fTimeToNextEvent = bIsWarping ? 0 : NoteRowToBeat( iEventRow - iLastRow ) / fBPS; + float fNextEventTime = fLastTime + fTimeToNextEvent; + fLastTime = fNextEventTime; + switch( iEventType ) + { + case FOUND_WARP_DESTINATION: + bIsWarping = false; break; - fElapsedTime += m_StopSegments[j].m_fStopSeconds; - } - - for( unsigned i=0; im_fEndBeat > fWarpDestination ) + { + fWarpDestination = itWS->m_fEndBeat; + } + itWS ++; + break; + case FOUND_BPM_CHANGE: + fBPS = itBPMS->m_fBPS; + itBPMS ++; + break; + case FOUND_STOP: + fTimeToNextEvent = bIsWarping ? 0 : itSS->m_fStopSeconds; + fNextEventTime = fLastTime + fTimeToNextEvent; + fLastTime = fNextEventTime; + itSS ++; + break; + case FOUND_MARKER: + return fLastTime; } - else - { - const int iStartIndexThisSegment = m_BPMSegments[i].m_iStartRow; - const int iStartIndexNextSegment = m_BPMSegments[i+1].m_iStartRow; - const int iRowsInThisSegment = min( iStartIndexNextSegment - iStartIndexThisSegment, iRow ); - fElapsedTime += NoteRowToBeat( iRowsInThisSegment ) / fBPS; - iRow -= iRowsInThisSegment; - } - - if( iRow <= 0 ) - return fElapsedTime; + iLastRow = iEventRow; } - - /* - for( unsigned i=0; i Date: Fri, 25 Mar 2011 23:40:03 +0700 Subject: [PATCH 13/40] [warps] Fix IsWarpAtRow. --- src/Player.cpp | 3 +-- src/TimingData.cpp | 14 ++++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index da11ff8cdf..194676330c 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2587,8 +2587,7 @@ void Player::UpdateJudgedRows() int iRow = iter.Row(); // if row is within a warp section, ignore it. -aj - if( iRow >= GAMESTATE->m_iWarpBeginRow && - iRow < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iRow) ) continue; if( iLastSeenRow != iRow ) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index ea0c30b937..9af8b6d11b 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -343,14 +343,12 @@ int TimingData::GetWarpSegmentIndexAtRow( int iNoteRow ) const bool TimingData::IsWarpAtRow( int iNoteRow ) const { - unsigned i; - for( i=0; i= iNoteRow ) - return iNoteRow < BeatToNoteRow(m_WarpSegments[i].m_fEndBeat); - } - return false; + if( m_WarpSegments.empty() ) + return false; + + int i = GetWarpSegmentIndexAtRow( iNoteRow ); + const WarpSegment& s = m_WarpSegments[i]; + return s.m_iStartRow <= iNoteRow && iNoteRow < BeatToNoteRow(s.m_fEndBeat); } int TimingData::GetTimeSignatureSegmentIndexAtRow( int iRow ) const From b94ff7785fd8716ea2792a02509407d332974f51 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 16:33:57 -0400 Subject: [PATCH 14/40] [warps] Add comment for thing to fix. --- src/TimingData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 9af8b6d11b..baf3e0c3a6 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -544,7 +544,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float fBPS = itBPMS->m_fBPS; itBPMS ++; break; - case FOUND_STOP: + case FOUND_STOP: // TODO: update for Delays. fTimeToNextEvent = bIsWarping ? 0 : itSS->m_fStopSeconds; fNextEventTime = fLastTime + fTimeToNextEvent; const bool bIsDelay = itSS->m_bDelay; From c8a6f4c41d13842d6e3ecc6882c4ad7280775e3e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 17:40:56 -0400 Subject: [PATCH 15/40] [warps] Allow for editing warps. TODO: Ensure warps get erased if they go backwards. --- Themes/_fallback/Languages/en.ini | 2 ++ src/ScreenEdit.cpp | 22 +++++++++++++++++++++- src/ScreenEdit.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 4e465f8675..2b44eee848 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -843,6 +843,7 @@ Edit time signature (top)=Edit time signature (beats per measure) Edit time signature (bottom)=Edit time signature (single beat note value) Edit tickcount=Edit tickcount Edit combo=Edit combo +Edit warp=Edit warp Editor options=Options EditorShowBGChangesPlay=Show Backgrounds Effect=Effect @@ -1209,6 +1210,7 @@ Enter a new Time Signature numerator value.=Enter the number of beats per measur Enter a new Time Signature denominator value.=Enter the note value that represents one beat. Enter a new Tickcount value.=Enter a new Tickcount value. Enter a new Combo value.=Enter a new Combo value. +Enter a new Warp value.=Enter the beat you will warp to when you reach this point. Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. Enter a new genre.=Enter a new genre. diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 213cc01028..6c09391967 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -80,6 +80,7 @@ AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange ); AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange ); AutoScreenMessage( SM_BackFromTickcountChange ); AutoScreenMessage( SM_BackFromComboChange ); +AutoScreenMessage( SM_BackFromWarpChange ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); AutoScreenMessage( SM_SaveSuccessful ); @@ -549,7 +550,8 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ) + MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL ) ); enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none }; @@ -2639,6 +2641,13 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } SetDirty( true ); } + else if ( SM == SM_BackFromWarpChange ) + { + float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); + if( fWarp > GAMESTATE->m_fSongBeat ) + m_pSong->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); + SetDirty( true ); + } else if( SM == SM_BackFromBGChange ) { HandleBGChangeChoice( (BGChangeChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers ); @@ -3176,6 +3185,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) ); EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } @@ -3609,6 +3619,7 @@ static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Ent static LocalizedString ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature denominator value." ); static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tickcount value." ); static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." ); +static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { switch( c ) @@ -3673,6 +3684,15 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice 4 ); break; + case warp: + // todo: Call a screen with class ScreenTextEntry instead. -aj + ScreenTextEntry::TextEntry( + SM_BackFromWarpChange, + ENTER_WARP_VALUE, + ssprintf( "%.4f", m_pSong->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ), + 10 + ); + break; } } diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 200a3979f0..1f79b78528 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -456,6 +456,7 @@ public: time_signature_denominator, tickcount, combo, + warp, NUM_TIMING_DATA_INFORMATION_CHOICES }; From 5126e21377566a4ff6207a0add361e08e8aeb5eb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 17:48:05 -0400 Subject: [PATCH 16/40] [warps] do validation in SetWarpAtRow, not here. --- src/ScreenEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 6c09391967..d11c08f2bc 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -2644,7 +2644,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) else if ( SM == SM_BackFromWarpChange ) { float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer ); - if( fWarp > GAMESTATE->m_fSongBeat ) + if( fWarp > 0 ) m_pSong->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp ); SetDirty( true ); } From c6ec8dbb743b52017feef5a5811b7a36a00859ef Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 18:02:56 -0400 Subject: [PATCH 17/40] [warps] Make Delays and Stops easier to find. --- Themes/_fallback/metrics.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index ae4abb4569..3cacf67bed 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -977,8 +977,8 @@ TickcountIsLeftSide=false ComboIsLeftSide=false # BPMOffsetX=60 -StopOffsetX=10 -DelayOffsetX=10 +StopOffsetX=50 +DelayOffsetX=120 WarpOffsetX=60 TimeSignatureOffsetX=30 TickcountOffsetX=10 From dd868637d2674525c938462c2076bd63b1fb5b8c Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Fri, 25 Mar 2011 19:11:34 -0500 Subject: [PATCH 18/40] [br:Warps] swap condition/code on Negative Stops; gonna hopefully work on this some more --- src/NotesLoaderSM.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 8a280ec723..e95c725a32 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -141,12 +141,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); new_seg.m_fStopSeconds = fFreezeSeconds; - if(fFreezeSeconds > 0.0f) - { - // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); - } - else + if(fFreezeSeconds < 0.0f) { // negative stops (hi JS!) -aj if( PREFSMAN->m_bQuirksMode ) @@ -157,6 +152,11 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) else LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); } + else + { + // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); + out.AddStopSegment( new_seg ); + } } } else if( sValueName=="DELAYS" ) @@ -216,7 +216,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) BPMSegment new_seg; new_seg.m_iStartRow = BeatToNoteRow(fBeat); new_seg.SetBPM( fNewBPM ); - + // convert negative BPMs into Warp segments if( fNewBPM < 0.0f ) { @@ -231,7 +231,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) // tJumpPos = (tPosBPS-abs(negBPS)) + (gPosBPMPosition - fNegPosition) float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat); //float fWarpLengthBeats = fNextPositiveBeat + fDeltaBeat; - WarpSegment wsTemp(BeatToNoteRow(fBeat),fDeltaBeat); + WarpSegment wsTemp( BeatToNoteRow(fBeat), BeatToNoteRow(fNextPositiveBeat+fDeltaBeat) ); arrayWarpsFromNegativeBPMs.push_back(wsTemp); /* From 9af2e9620437e249699c1dcfb26c5bd237c0613a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 21:14:24 -0400 Subject: [PATCH 19/40] [warps] Already added. --- src/NoteField.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 241c782310..958866b0a5 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -843,8 +843,6 @@ void NoteField::DrawPrimitives() } } - // todo: add warp text -aj - // Course mods text const Course *pCourse = GAMESTATE->m_pCurCourse; if( pCourse ) From 0692da91c6c3451eb248dfcc6496ae0450ad5d7a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 21:31:33 -0400 Subject: [PATCH 20/40] [warps] Be consistent, include Row and Beat. --- src/TimingData.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/TimingData.h b/src/TimingData.h index a43021acf8..6f43a3b818 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -929,6 +929,12 @@ public: * @return true if the row is inside a warp, false otherwise. */ bool IsWarpAtRow( int iRow ) const; + /** + * @brief Checks if the beat is inside a warp. + * @param fBeat the beat to focus on. + * @return true if the row is inside a warp, false otherwise. + */ + bool IsWarpAtBeat( float fBeat ) const { return IsWarpAtRow( BeatToNoteRow( fBeat ) ); } /** * @brief Add the WarpSegment to the TimingData. * @param seg the new WarpSegment. From 7e59c6094475044818f5a91b0c163665807f34a1 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 25 Mar 2011 21:31:47 -0400 Subject: [PATCH 21/40] [warps] Ignore all mines during a warp. --- src/Player.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Player.cpp b/src/Player.cpp index 194676330c..8f727a35d7 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2040,7 +2040,9 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b { case TapNote::mine: // Stepped too close to mine? - if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) && fSecondsFromExact <= GetWindowSeconds(TW_Mine) ) + if( !bRelease && ( REQUIRE_STEP_ON_MINES == !bHeld ) && + fSecondsFromExact <= GetWindowSeconds(TW_Mine) && + !GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iSongRow) ) score = TNS_HitMine; break; From fff2c5948e7dc340eb1d205f929f59ad062fff0c Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Fri, 25 Mar 2011 22:46:45 -0500 Subject: [PATCH 22/40] [br:warps] still doesn't do anything, but latest work on negstops (does not make WarpSegments yet) --- src/NotesLoaderSM.cpp | 162 ++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 76 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index e95c725a32..74f119b403 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -117,82 +117,6 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) { out.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] ); } - else if( sValueName=="STOPS" || sValueName=="FREEZES" ) - { - vector arrayFreezeExpressions; - split( sParams[1], ",", arrayFreezeExpressions ); - - for( unsigned f=0; f arrayFreezeValues; - split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); - if( arrayFreezeValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayFreezeExpressions[f].c_str() ); - continue; - } - - const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); - // XXX: Remove Negatives Bug? - new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); - new_seg.m_fStopSeconds = fFreezeSeconds; - - if(fFreezeSeconds < 0.0f) - { - // negative stops (hi JS!) -aj - if( PREFSMAN->m_bQuirksMode ) - { - // LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); - } - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); - } - else - { - // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); - } - } - } - else if( sValueName=="DELAYS" ) - { - vector arrayDelayExpressions; - split( sParams[1], ",", arrayDelayExpressions ); - - for( unsigned f=0; f arrayDelayValues; - split( arrayDelayExpressions[f], "=", arrayDelayValues ); - if( arrayDelayValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayDelayExpressions[f].c_str() ); - continue; - } - - const float fFreezeBeat = StringToFloat( arrayDelayValues[0] ); - const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); - - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true ); - // XXX: Remove Negatives Bug? - new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); - new_seg.m_fStopSeconds = fFreezeSeconds; - - // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - - if(fFreezeSeconds > 0.0f) - out.AddStopSegment( new_seg ); - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); - } - } - else if( sValueName=="BPMS" ) { vector arrayBPMChangeExpressions; @@ -282,6 +206,92 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) } } + else if( sValueName=="STOPS" || sValueName=="FREEZES" ) + { + vector arrayFreezeExpressions; + split( sParams[1], ",", arrayFreezeExpressions ); + + for( unsigned f=0; f arrayFreezeValues; + split( arrayFreezeExpressions[f], "=", arrayFreezeValues ); + if( arrayFreezeValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", + sValueName.c_str(), arrayFreezeExpressions[f].c_str() ); + continue; + } + + const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] ); + const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); + StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); + // XXX: Remove Negatives Bug? + new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); + new_seg.m_fStopSeconds = fFreezeSeconds; + + if(fFreezeSeconds < 0.0f) + { + // Convert negative Stops into Warps. + // 60/BPM = quarter note value (in seconds) + // quarter note value * 4 = number of measures to skip + // (WinDEU's guide says 8, but this may not be right.) + + // get BPM at current row: + BPMSegment curBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(fFreezeBeat)); + float fQuarterNoteVal = 60 / curBPM.m_fBPS; + float fSkipToSeconds = fQuarterNoteVal * 4; + + if( PREFSMAN->m_bQuirksMode ) + { + // LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); + out.AddStopSegment( new_seg ); + } + else + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); + } + else + { + // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); + out.AddStopSegment( new_seg ); + } + } + } + + else if( sValueName=="DELAYS" ) + { + vector arrayDelayExpressions; + split( sParams[1], ",", arrayDelayExpressions ); + + for( unsigned f=0; f arrayDelayValues; + split( arrayDelayExpressions[f], "=", arrayDelayValues ); + if( arrayDelayValues.size() != 2 ) + { + // XXX: Hard to tell which file caused this. + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", + sValueName.c_str(), arrayDelayExpressions[f].c_str() ); + continue; + } + + const float fFreezeBeat = StringToFloat( arrayDelayValues[0] ); + const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); + + StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true ); + // XXX: Remove Negatives Bug? + new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); + new_seg.m_fStopSeconds = fFreezeSeconds; + + // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); + + if(fFreezeSeconds > 0.0f) + out.AddStopSegment( new_seg ); + else + LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); + } + } + else if( sValueName=="TIMESIGNATURES" ) { vector vs1; From 3447567a61598640c6bb98436a375e0da94625b2 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Fri, 25 Mar 2011 23:04:41 -0500 Subject: [PATCH 23/40] [br:warps] ignore mines if they are within a warp section; untested but should work in theory --- src/Player.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Player.cpp b/src/Player.cpp index 8f727a35d7..fdf02b8fc6 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2639,6 +2639,10 @@ void Player::UpdateJudgedRows() int iRow = iter.Row(); TapNote &tn = *iter; + // if row is within a warp section, ignore it. -aj + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iRow) ) + continue; + if( iRow != iLastSeenRow ) { iLastSeenRow = iRow; From 97e9e63d5c9aeb88debb6e9bcabb81327e77edfd Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Fri, 25 Mar 2011 23:07:13 -0500 Subject: [PATCH 24/40] revert unneeded code --- src/Player.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index fdf02b8fc6..8f727a35d7 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2639,10 +2639,6 @@ void Player::UpdateJudgedRows() int iRow = iter.Row(); TapNote &tn = *iter; - // if row is within a warp section, ignore it. -aj - if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow(iRow) ) - continue; - if( iRow != iLastSeenRow ) { iLastSeenRow = iRow; From 53421eea4ffaa28f11a856eb050b77576b699b33 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 26 Mar 2011 00:17:42 -0500 Subject: [PATCH 25/40] [br:warps] more work on NotesLoaderSM, re: warps from Negative Stops --- src/NotesLoaderSM.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 74f119b403..f01caa1198 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -105,7 +105,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) out.m_vTimeSignatureSegments.clear(); vector arrayWarpsFromNegativeBPMs; - //vector arrayWarpsFromNegativeStops; + vector arrayWarpsFromNegativeStops; for( unsigned i=0; im_bQuirksMode ) { From 417848ce4e6a84399df1340651f1bbc28c0e131a Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 26 Mar 2011 00:19:30 -0500 Subject: [PATCH 26/40] [br:warps] better variable name for FreezeSeconds/SecondsPerBeat --- src/NotesLoaderSM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index f01caa1198..8d4cbe7ed9 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -238,7 +238,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) BPMSegment curBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(fFreezeBeat)); float fSecondsPerBeat = 60 / curBPM.m_fBPS; // stop length (# measures to skip) = secsPerBeat * 8 - float fSkipToSeconds = fFreezeSeconds/fSecondsPerBeat; + float fSkipBeats = fFreezeSeconds/fSecondsPerBeat; // location - stoplength = time to subtract from current. // WarpSegment wsTemp( BeatToNoteRow(fFreezeBeat), [unknown] ); From 784dcb5f607689414305f15ba926c4a6e6dd3168 Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 26 Mar 2011 00:25:56 -0500 Subject: [PATCH 27/40] [br:warps] just come cleanups --- src/NotesLoaderSM.cpp | 55 ++++--------------------------------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 8d4cbe7ed9..6232593e7f 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -239,7 +239,6 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) float fSecondsPerBeat = 60 / curBPM.m_fBPS; // stop length (# measures to skip) = secsPerBeat * 8 float fSkipBeats = fFreezeSeconds/fSecondsPerBeat; - // location - stoplength = time to subtract from current. // WarpSegment wsTemp( BeatToNoteRow(fFreezeBeat), [unknown] ); // arrayWarpsFromNegativeStops.push_back( wsTemp ); @@ -284,7 +283,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) // XXX: Remove Negatives Bug? new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); new_seg.m_fStopSeconds = fFreezeSeconds; - + // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); if(fFreezeSeconds > 0.0f) @@ -338,12 +337,12 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) out.AddTimeSignatureSegment( seg ); } } - + else if( sValueName=="TICKCOUNTS" ) { vector arrayTickcountExpressions; split( sParams[1], ",", arrayTickcountExpressions ); - + for( unsigned f=0; f arrayTickcountValues; @@ -355,7 +354,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) sValueName.c_str(), arrayTickcountExpressions[f].c_str() ); continue; } - + const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] ); int iTicks = atoi( arrayTickcountValues[1] ); // you're lazy, let SM do the work for you... -DaisuMaster @@ -379,53 +378,9 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) } } - // warps (replacement for Negative BPM and Negative Stops) - /* - else if( sValueName=="WARPS" ) - { - vector arrayWarpExpressions; - split( sParams[1], ",", arrayWarpExpressions ); - - for( unsigned f=0; f arrayWarpValues; - split( arrayWarpExpressions[f], "=", arrayWarpValues ); - if( arrayWarpValues.size() != 2 ) - { - // XXX: Hard to tell which file caused this. - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.", - sValueName.c_str(), arrayWarpExpressions[f].c_str() ); - continue; - } - - const float fWarpStart = StringToFloat( arrayWarpValues[0] ); - const float fWarpBeats = StringToFloat( arrayWarpValues[1] ); - - if( fWarpStart > 0.0f && fWarpBeats > 0.0f ) - { - WarpSegment new_seg( BeatToNoteRow(fWarpStart), fWarpBeats ); - out.AddWarpSegment( new_seg ); - } - else - { - // Currently disallow negative warps, to prevent the same - // kind of problem that happened when Negative/Subtractive - // BPMs arrived on the StepMania scene. -aj - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid warp at beat %f lasting %f beats.", fWarpStart, fWarpBeats ); - } - } - } - */ - - // Note: Even though it is possible to have Negative BPMs and Stops in - // a song along with Warps, we should not support files that contain - // both styles of warp tricks (Negatives vs. #WARPS). - // If Warps have been populated from Negative BPMs, then go through that - // instead of using the data in the Warps tag. This should be above, - // but it breaks compiling so... + // Convert Negative BPMs and Negative Stops to WarpSegments. if(arrayWarpsFromNegativeBPMs.size() > 0) { - // zomg we already have some warps... for( unsigned j=0; j Date: Sat, 26 Mar 2011 01:07:14 -0500 Subject: [PATCH 28/40] [br:warps] ignore .lnk; should be in default --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index ea6889df61..aac27be6ce 100644 --- a/.hgignore +++ b/.hgignore @@ -72,6 +72,7 @@ Data/SpeedMods.txt Program/StepMania*.lib crashinfo.txt Utils/temp* +*.lnk syntax: regexp .*\#.*\#$ From aac5710fb482e3a3f957ee63932e50e7a74e4a5c Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 26 Mar 2011 01:08:05 -0500 Subject: [PATCH 29/40] [br:warps] my changes to NotesLoaderSM for Negative Stops -> Warps. (still not working, sadly) --- src/NotesLoaderSM.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 6232593e7f..65fdaaab86 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -236,12 +236,11 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) // get BPM at current row: BPMSegment curBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(fFreezeBeat)); - float fSecondsPerBeat = 60 / curBPM.m_fBPS; - // stop length (# measures to skip) = secsPerBeat * 8 + float fSecondsPerBeat = 60 / curBPM.GetBPM(); float fSkipBeats = fFreezeSeconds/fSecondsPerBeat; - // WarpSegment wsTemp( BeatToNoteRow(fFreezeBeat), [unknown] ); - // arrayWarpsFromNegativeStops.push_back( wsTemp ); + WarpSegment wsTemp( BeatToNoteRow(fFreezeBeat), BeatToNoteRow(fFreezeBeat+fSkipBeats) ); + arrayWarpsFromNegativeStops.push_back( wsTemp ); if( PREFSMAN->m_bQuirksMode ) { @@ -386,8 +385,17 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) out.AddWarpSegment( arrayWarpsFromNegativeBPMs[j] ); } } - // warp sorting will need to take place. - //sort(out.m_WarpSegments.begin(), out.m_WarpSegments.end()); + // do the same for Warps from Negative Stops. + /* + if(arrayWarpsFromNegativeStops.size() > 0) + { + for( unsigned j=0; j Date: Sat, 26 Mar 2011 02:36:44 -0400 Subject: [PATCH 30/40] [warps] Negative BPMs converted to Warps. --- src/NotesLoaderSM.cpp | 98 ++++++++++++------------------------------- 1 file changed, 27 insertions(+), 71 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 65fdaaab86..05a71f7621 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -104,7 +104,6 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) out.m_WarpSegments.clear(); out.m_vTimeSignatureSegments.clear(); - vector arrayWarpsFromNegativeBPMs; vector arrayWarpsFromNegativeStops; for( unsigned i=0; i arrayBPMChangeExpressions; split( sParams[1], ",", arrayBPMChangeExpressions ); + // prepare storage variables for negative BPMs -> Warps. + float negBeat = -1; + float negBPM = 1; + for( unsigned b=0; b arrayBPMChangeValues; @@ -136,72 +139,33 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) const float fBeat = StringToFloat( arrayBPMChangeValues[0] ); const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] ); - // XXX: Remove Negatives Bug? - BPMSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(fBeat); - new_seg.SetBPM( fNewBPM ); - - // convert negative BPMs into Warp segments + if( fNewBPM < 0.0f ) - { - vector arrayNextBPMChangeValues; - // get next bpm in sequence - if((b+1) < arrayBPMChangeExpressions.size()) - { - split( arrayBPMChangeExpressions[b+1], "=", arrayNextBPMChangeValues ); - const float fNextPositiveBeat = StringToFloat( arrayNextBPMChangeValues[0] ); - const float fNextPositiveBPM = StringToFloat( arrayNextBPMChangeValues[1] ); - - // tJumpPos = (tPosBPS-abs(negBPS)) + (gPosBPMPosition - fNegPosition) - float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat); - //float fWarpLengthBeats = fNextPositiveBeat + fDeltaBeat; - WarpSegment wsTemp( BeatToNoteRow(fBeat), BeatToNoteRow(fNextPositiveBeat+fDeltaBeat) ); - arrayWarpsFromNegativeBPMs.push_back(wsTemp); - - /* - LOG->Trace( ssprintf("==NotesLoSM negbpm==\nfnextposbeat = %f, fnextposbpm = %f,\nfdelta = %f, fwarpto = %f", - fNextPositiveBeat, - fNextPositiveBPM, - fDeltaBeat, - fWarpToBeat - ) ); - */ - /* - LOG->Trace( ssprintf("==Negative/Subtractive BPM in NotesLoader==\nNegBPM has noterow = %i, BPM = %f\nNextBPM @ noterow %i\nDelta value = %i noterows\nThis warp will have us end up at noterow %i", - BeatToNoteRow(fBeat), fNewBPM, - BeatToNoteRow(fNextPositiveBeat), - BeatToNoteRow(fDeltaBeat), - BeatToNoteRow(fWarpToBeat)) - ); - */ - //float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat); - /* - LOG->Trace( ssprintf("==NotesLoader Delta as NoteRows==\nfDeltaBeat = %f (beat)\nfDeltaBeat = (NextBPMSeg %f - abs(fBPS %f)) + (nextStartRow %i - thisRow %i)", - fDeltaBeat,(fNextPositiveBPM/60.0f),abs(fNewBPM/60.0f),BeatToNoteRow(fNextPositiveBeat),BeatToNoteRow(fBeat)) - ); - */ - - out.AddBPMSegment( new_seg ); - - continue; - } - else - { - // last BPM is a negative one? ugh. -aj (MAX_NOTE_ROW exists btw) - out.AddBPMSegment( new_seg ); - } - } - - if(fNewBPM > 0.0f) - out.AddBPMSegment( new_seg ); - else { out.m_bHasNegativeBpms = true; - // only add Negative BPMs in quirks mode -aj - if( PREFSMAN->m_bQuirksMode ) - out.AddBPMSegment( new_seg ); + negBeat = fBeat; + negBPM = fNewBPM; + } + else if( fNewBPM > 0.0f ) + { + // add in a warp. + if( negBPM < 0 ) + { + WarpSegment new_seg; + new_seg.m_iStartRow = BeatToNoteRow(negBeat); + new_seg.m_fEndBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); + out.AddWarpSegment( new_seg ); + + negBeat = -1; + negBPM = 1; + } else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid BPM change at beat %f, BPM %f.", fBeat, fNewBPM ); + { + BPMSegment new_seg; + new_seg.m_iStartRow = BeatToNoteRow(fBeat); + new_seg.SetBPM( fNewBPM ); + out.AddBPMSegment( new_seg ); + } } } } @@ -377,14 +341,6 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) } } - // Convert Negative BPMs and Negative Stops to WarpSegments. - if(arrayWarpsFromNegativeBPMs.size() > 0) - { - for( unsigned j=0; j 0) From e66b0cbf39bb1f96d0980559f9dec5b115e21df1 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 26 Mar 2011 13:42:41 +0700 Subject: [PATCH 31/40] [warps] judgement fix + iStepSearchRows is now seconds-based. + GetClosestNonEmptyRowDirectional and GetClosestNoteDirectional no longer return row in warps. --- src/Player.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Player.cpp b/src/Player.cpp index 8f727a35d7..102652e074 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1520,6 +1520,8 @@ int Player::GetClosestNoteDirectional( int col, int iStartRow, int iEndRow, bool // Is this the row we want? do { const TapNote &tn = begin->second; + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( begin->first ) ) + break; if( tn.type == TapNote::empty ) break; if( !bAllowGraded && tn.result.tns != TNS_None ) @@ -1569,6 +1571,11 @@ int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool b ++iter; continue; } + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iter.Row() ) ) + { + ++iter; + continue; + } return iter.Row(); } } @@ -1966,7 +1973,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b * Either option would fundamentally change the grading of two quick notes * "jack hammers." Hmm. */ - const int iStepSearchRows = BeatToNoteRow( StepSearchDistance * GAMESTATE->m_fCurBPS * GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate ); + const int iStepSearchRows = BeatToNoteRow( GAMESTATE->m_pCurSong->m_Timing.GetBeatFromElapsedTime( GAMESTATE->m_fMusicSeconds + StepSearchDistance ) ) - iSongRow; int iRowOfOverlappingNoteOrRow = row; if( row == -1 ) { From eed0be6fe05805f506a79738bd1f99ee8220fc50 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 26 Mar 2011 14:21:06 +0700 Subject: [PATCH 32/40] [warps] ScaleRegion, InsertRows, DeleteRows to make it point warps to the right place. --- src/ScreenEdit.cpp | 2 +- src/TimingData.cpp | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index d11c08f2bc..8707da7293 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3503,7 +3503,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns // don't move the step from where it is, just move everything later NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); - m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopSeconds) ); + m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) ); } break; case undo: diff --git a/src/TimingData.cpp b/src/TimingData.cpp index baf3e0c3a6..d7a9ccb3cf 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -676,7 +676,7 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool else m_BPMSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; } - + for( unsigned i = 0; i < m_StopSegments.size(); i++ ) { const int iSegStartRow = m_StopSegments[i].m_iStartRow; @@ -688,6 +688,25 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool m_StopSegments[i].m_iStartRow = 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 = BeatToNoteRow( m_WarpSegments[i].m_fEndBeat ); + if( iSegEndRow >= iStartIndex ) + { + if( iSegEndRow > iEndIndex ) + m_WarpSegments[i].m_fEndBeat += NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1))); + else + m_WarpSegments[i].m_fEndBeat = NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale) + iStartIndex); + } + if( iSegStartRow < iStartIndex ) + continue; + else if( iSegStartRow > iEndIndex ) + m_WarpSegments[i].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); + else + m_WarpSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; + } + // adjust BPM changes to preserve timing if( bAdjustBPM ) { @@ -735,7 +754,9 @@ 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( BeatToNoteRow(warp.m_fEndBeat) >= iStartRow ) + warp.m_fEndBeat += NoteRowToBeat(iRowsToAdd); + if( warp.m_iStartRow < iStartRow ) continue; warp.m_iStartRow += iRowsToAdd; } @@ -825,6 +846,9 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) { WarpSegment &warp = m_WarpSegments[i]; + if( BeatToNoteRow(warp.m_fEndBeat) >= iStartRow ) + warp.m_fEndBeat = max( NoteRowToBeat(iStartRow), warp.m_fEndBeat - NoteRowToBeat(iRowsToDelete) ); + if( warp.m_iStartRow < iStartRow ) continue; From 337fa2f8012241a9e8895bedd0fb9849bb304567 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 26 Mar 2011 03:37:37 -0400 Subject: [PATCH 33/40] [warps] Negative Stops turn to Warps now. --- src/NotesLoaderSM.cpp | 80 ++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 05a71f7621..35336f7056 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -104,8 +104,6 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) out.m_WarpSegments.clear(); out.m_vTimeSignatureSegments.clear(); - vector arrayWarpsFromNegativeStops; - for( unsigned i=0; i arrayFreezeExpressions; split( sParams[1], ",", arrayFreezeExpressions ); + // Prepare variables for negative stop conversion. + float negBeat = -1; + float negPause = 0; + for( unsigned f=0; f arrayFreezeValues; @@ -189,36 +191,46 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] ); const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ); - StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); - // XXX: Remove Negatives Bug? - new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); - new_seg.m_fStopSeconds = fFreezeSeconds; - - if(fFreezeSeconds < 0.0f) + + // Process the prior stop. + if( negPause > 0 ) { - // Convert negative Stops into Warps. - - // get BPM at current row: - BPMSegment curBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(fFreezeBeat)); - float fSecondsPerBeat = 60 / curBPM.GetBPM(); - float fSkipBeats = fFreezeSeconds/fSecondsPerBeat; - - WarpSegment wsTemp( BeatToNoteRow(fFreezeBeat), BeatToNoteRow(fFreezeBeat+fSkipBeats) ); - arrayWarpsFromNegativeStops.push_back( wsTemp ); - - if( PREFSMAN->m_bQuirksMode ) - { - // LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); - } - else - LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds ); + BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); + float fSecondsPerBeat = 60 / oldBPM.GetBPM(); + float fSkipBeats = negPause / fSecondsPerBeat; + + if( negBeat + fSkipBeats > fFreezeBeat ) + fSkipBeats = fFreezeBeat - negBeat; + + WarpSegment ws( BeatToNoteRow(negBeat), negBeat + fSkipBeats); + out.AddWarpSegment( ws ); + + negBeat = -1; + negPause = 0; } - else + + if( fFreezeSeconds < 0.0f ) { - // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); - out.AddStopSegment( new_seg ); + negBeat = fFreezeBeat; + negPause = -fFreezeSeconds; } + else if( fFreezeSeconds > 0.0f ) + { + StopSegment ss( BeatToNoteRow(fFreezeBeat), fFreezeSeconds ); + out.AddStopSegment( ss ); + } + + } + + // Process the prior stop if there was one. + if( negPause > 0 ) + { + BPMSegment oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); + float fSecondsPerBeat = 60 / oldBPM.GetBPM(); + float fSkipBeats = negPause / fSecondsPerBeat; + + WarpSegment ws( BeatToNoteRow(negBeat), negBeat + fSkipBeats); + out.AddWarpSegment( ws ); } } @@ -340,17 +352,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) } } } - - // do the same for Warps from Negative Stops. - /* - if(arrayWarpsFromNegativeStops.size() > 0) - { - for( unsigned j=0; j Date: Sat, 26 Mar 2011 14:51:30 +0700 Subject: [PATCH 34/40] [warps] Some simfiles change BPM after the warp, so should keep the positive BPM changes. Example simfile: Tsusurvivorgamush. --- src/NotesLoaderSM.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 05a71f7621..b949d8e2cc 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -159,7 +159,6 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) negBeat = -1; negBPM = 1; } - else { BPMSegment new_seg; new_seg.m_iStartRow = BeatToNoteRow(fBeat); From ac336215bd96a85d13335b554d501b05cc6b4bbd Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 26 Mar 2011 22:07:24 +0700 Subject: [PATCH 35/40] [warps] allow stops inside warps and convert high bpm to warps + sometimes there are delays/stops in high BPM sections, they have to be handled inside a warp to be able to convert it easily. + on the stopped / delayed rows with warps, judging become enabled for that row. Issues: + the bpm threshould is hardcoded (right now it's 400000.0). someone change it please. + slight off-sync from conversion. haven't figured out how to work around it yet. --- src/GameState.cpp | 15 -------- src/NotesLoaderSM.cpp | 26 +++++++++++--- src/Player.cpp | 8 ++--- src/TimingData.cpp | 84 ++++++++++++++++++++++++------------------- 4 files changed, 73 insertions(+), 60 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 581c882b08..1a3f2d0793 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -961,21 +961,6 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti // "Crash reason : -243478.890625 -48695.773438" ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); - //if( m_iWarpBeginRow != -1 || m_iWarpEndRow == -1 ) - - /* - if( m_iWarpBeginRow != -1 && m_fWarpDestination > 0.0f ) - { - float fWarpLength = m_fWarpDestination-NoteRowToBeat(m_iWarpBeginRow); - // There is a warp in this section. - LOG->Trace("warp at row %i lasts for %f beats, jumps to row %i", - m_iWarpBeginRow, - fWarpLength, - BeatToNoteRow(m_fWarpDestination)); - fPositionSeconds += (fWarpLength * m_fCurBPS); - } - */ - m_fMusicSeconds = fPositionSeconds; m_fLightSongBeat = timing.GetBeatFromElapsedTime( fPositionSeconds + g_fLightsAheadSeconds ); diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 71c52691fc..412807800f 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -122,6 +122,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) // prepare storage variables for negative BPMs -> Warps. float negBeat = -1; float negBPM = 1; + float highspeedBeat = -1; for( unsigned b=0; b 400000.0 ) { - BPMSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(fBeat); - new_seg.SetBPM( fNewBPM ); - out.AddBPMSegment( new_seg ); + highspeedBeat = fBeat; + } + else + { + // add in a warp. + if( highspeedBeat > 0 ) + { + WarpSegment new_seg; + new_seg.m_iStartRow = BeatToNoteRow(highspeedBeat); + new_seg.m_fEndBeat = fBeat; + out.AddWarpSegment( new_seg ); + highspeedBeat = -1; + } + { + BPMSegment new_seg; + new_seg.m_iStartRow = BeatToNoteRow(fBeat); + new_seg.SetBPM( fNewBPM ); + out.AddBPMSegment( new_seg ); + } } } } diff --git a/src/Player.cpp b/src/Player.cpp index 102652e074..13bae07600 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -2561,7 +2561,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) continue; // Ignore all notes that are skipped via WARPS. - if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iter.Row() ) ) continue; if( tn.type == TapNote::mine ) @@ -2931,8 +2931,7 @@ void Player::HandleTapRowScore( unsigned row ) #endif // more warp hackery. -aj - if( row >= (unsigned)GAMESTATE->m_iWarpBeginRow && - row < (unsigned)(BeatToNoteRow(GAMESTATE->m_fWarpDestination)) ) + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( row ) ) return; if( GAMESTATE->m_bDemonstrationOrJukebox ) @@ -3036,8 +3035,7 @@ void Player::HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumH #endif // more warp hackery. -aj - if( iRow >= GAMESTATE->m_iWarpBeginRow && - iRow < BeatToNoteRow(GAMESTATE->m_fWarpDestination) ) + if( GAMESTATE->m_pCurSong->m_Timing.IsWarpAtRow( iRow ) ) return; // don't accumulate combo if AutoPlay is on. diff --git a/src/TimingData.cpp b/src/TimingData.cpp index d7a9ccb3cf..00da97017b 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -348,7 +348,19 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const int i = GetWarpSegmentIndexAtRow( iNoteRow ); const WarpSegment& s = m_WarpSegments[i]; - return s.m_iStartRow <= iNoteRow && iNoteRow < BeatToNoteRow(s.m_fEndBeat); + if( s.m_iStartRow <= iNoteRow && iNoteRow < BeatToNoteRow(s.m_fEndBeat) ) + { + if( m_StopSegments.empty() ) + { + return true; + } + if( GetStopAtRow(iNoteRow) != 0.0f ) + { + return false; + } + return true; + } + return false; } int TimingData::GetTimeSignatureSegmentIndexAtRow( int iRow ) const @@ -499,11 +511,6 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float iEventRow = BeatToNoteRow(fWarpDestination); iEventType = FOUND_WARP_DESTINATION; } - if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) - { - iEventRow = itWS->m_iStartRow; - iEventType = FOUND_WARP; - } if( itBPMS != m_BPMSegments.end() && itBPMS->m_iStartRow < iEventRow ) { iEventRow = itBPMS->m_iStartRow; @@ -514,6 +521,11 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float iEventRow = itSS->m_iStartRow; iEventType = FOUND_STOP; } + if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) + { + iEventRow = itWS->m_iStartRow; + iEventType = FOUND_WARP; + } if( iEventType == NOT_FOUND ) { break; @@ -530,22 +542,12 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float case FOUND_WARP_DESTINATION: bIsWarping = false; break; - case FOUND_WARP: - bIsWarping = true; - if( itWS->m_fEndBeat > fWarpDestination ) - { - fWarpDestination = itWS->m_fEndBeat; - } - iWarpBeginOut = iEventRow; - fWarpDestinationOut = fWarpDestination; - itWS ++; - break; case FOUND_BPM_CHANGE: fBPS = itBPMS->m_fBPS; itBPMS ++; break; case FOUND_STOP: // TODO: update for Delays. - fTimeToNextEvent = bIsWarping ? 0 : itSS->m_fStopSeconds; + fTimeToNextEvent = itSS->m_fStopSeconds; fNextEventTime = fLastTime + fTimeToNextEvent; const bool bIsDelay = itSS->m_bDelay; if ( fElapsedTime < fNextEventTime ) @@ -559,6 +561,16 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float fLastTime = fNextEventTime; itSS ++; break; + case FOUND_WARP: + bIsWarping = true; + if( itWS->m_fEndBeat > fWarpDestination ) + { + fWarpDestination = itWS->m_fEndBeat; + } + iWarpBeginOut = iEventRow; + fWarpDestinationOut = fWarpDestination; + itWS ++; + break; } iLastRow = iEventRow; } @@ -599,17 +611,12 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const iEventRow = BeatToNoteRow(fWarpDestination); iEventType = FOUND_WARP_DESTINATION; } - if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) - { - iEventRow = itWS->m_iStartRow; - iEventType = FOUND_WARP; - } if( itBPMS != m_BPMSegments.end() && itBPMS->m_iStartRow < iEventRow ) { iEventRow = itBPMS->m_iStartRow; iEventType = FOUND_BPM_CHANGE; } - if( itSS != m_StopSegments.end() && itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) + if( itSS != m_StopSegments.end() && itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) // delays (come before marker) { iEventRow = itSS->m_iStartRow; iEventType = FOUND_STOP; @@ -619,11 +626,16 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const iEventRow = BeatToNoteRow(fBeat); iEventType = FOUND_MARKER; } - if( itSS != m_StopSegments.end() && !itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) + if( itSS != m_StopSegments.end() && !itSS->m_bDelay && itSS->m_iStartRow < iEventRow ) // stops (come after marker) { iEventRow = itSS->m_iStartRow; iEventType = FOUND_STOP; } + if( itWS != m_WarpSegments.end() && itWS->m_iStartRow < iEventRow ) + { + iEventRow = itWS->m_iStartRow; + iEventType = FOUND_WARP; + } float fTimeToNextEvent = bIsWarping ? 0 : NoteRowToBeat( iEventRow - iLastRow ) / fBPS; float fNextEventTime = fLastTime + fTimeToNextEvent; fLastTime = fNextEventTime; @@ -632,6 +644,18 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const case FOUND_WARP_DESTINATION: bIsWarping = false; break; + case FOUND_BPM_CHANGE: + fBPS = itBPMS->m_fBPS; + itBPMS ++; + break; + case FOUND_STOP: + fTimeToNextEvent = itSS->m_fStopSeconds; + fNextEventTime = fLastTime + fTimeToNextEvent; + fLastTime = fNextEventTime; + itSS ++; + break; + case FOUND_MARKER: + return fLastTime; case FOUND_WARP: bIsWarping = true; if( itWS->m_fEndBeat > fWarpDestination ) @@ -640,18 +664,6 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const } itWS ++; break; - case FOUND_BPM_CHANGE: - fBPS = itBPMS->m_fBPS; - itBPMS ++; - break; - case FOUND_STOP: - fTimeToNextEvent = bIsWarping ? 0 : itSS->m_fStopSeconds; - fNextEventTime = fLastTime + fTimeToNextEvent; - fLastTime = fNextEventTime; - itSS ++; - break; - case FOUND_MARKER: - return fLastTime; } iLastRow = iEventRow; } From d44f42968dfae47cac63ebeab55d97f1f582cb1a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 26 Mar 2011 11:14:55 -0400 Subject: [PATCH 36/40] [warps] Use the value from SM4's recent betas. --- src/NotesLoaderSM.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 412807800f..632a00c2fe 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -12,7 +12,13 @@ #include "Steps.h" #include "PrefsManager.h" +/** @brief The maximum file size for edits. */ const int MAX_EDIT_STEPS_SIZE_BYTES = 60*1024; // 60KB +/** + * @brief The highest allowable speed before Warps come in. + * + * This was brought in from StepMania 4's recent betas. */ +const float FAST_BPM_WARP = 9999999.f; void SMLoader::LoadFromSMTokens( RString sStepsType, @@ -159,7 +165,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) negBPM = 1; } // too fast. make it a warp. - if( fNewBPM > 400000.0 ) + if( fNewBPM > FAST_BPM_WARP ) { highspeedBeat = fBeat; } From c1f2cc2400dc5f1c0cd3331d4be6b8f969bf224b Mon Sep 17 00:00:00 2001 From: AJ Kelly Date: Sat, 26 Mar 2011 11:59:48 -0500 Subject: [PATCH 37/40] [br:warps] Fix compile by easing scope --- src/TimingData.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 00da97017b..1ddb2d6ad1 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -547,19 +547,21 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float itBPMS ++; break; case FOUND_STOP: // TODO: update for Delays. - fTimeToNextEvent = itSS->m_fStopSeconds; - fNextEventTime = fLastTime + fTimeToNextEvent; - const bool bIsDelay = itSS->m_bDelay; - if ( fElapsedTime < fNextEventTime ) { - bFreezeOut = !bIsDelay; - bDelayOut = bIsDelay; - fBeatOut = NoteRowToBeat( itSS->m_iStartRow ); - fBPSOut = fBPS; - return; + fTimeToNextEvent = itSS->m_fStopSeconds; + fNextEventTime = fLastTime + fTimeToNextEvent; + const bool bIsDelay = itSS->m_bDelay; + if ( fElapsedTime < fNextEventTime ) + { + bFreezeOut = !bIsDelay; + bDelayOut = bIsDelay; + fBeatOut = NoteRowToBeat( itSS->m_iStartRow ); + fBPSOut = fBPS; + return; + } + fLastTime = fNextEventTime; + itSS ++; } - fLastTime = fNextEventTime; - itSS ++; break; case FOUND_WARP: bIsWarping = true; From 8b7435a50c4a2a2cc3e83cd1a6ec238f22852c82 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 26 Mar 2011 13:44:47 -0400 Subject: [PATCH 38/40] [warps] Make our mark on #WARPS history. --- Docs/Changelog_sm-ssc.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Docs/Changelog_sm-ssc.txt b/Docs/Changelog_sm-ssc.txt index af644b111f..d6bac8ebd2 100644 --- a/Docs/Changelog_sm-ssc.txt +++ b/Docs/Changelog_sm-ssc.txt @@ -13,6 +13,11 @@ _____________________________________________________________________________ sm-ssc v1.2.4 | 2011032? -------------------------------------------------------------------------------- +20110326 +-------- +* [NotesLoaderSM, NotesWriterSSC] Officially add the #WARPS tag. The negative + tricks of the past are now officially standardized. [AJ, Thai, Wolfman2000] + 20110320 -------- * [PlayerOptions] Added SetNoteSkin(string) Lua binding. [AJ] From 64619f98191435663f4f35bbafd888819d5b80eb Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 26 Mar 2011 14:27:06 -0400 Subject: [PATCH 39/40] [warps] Add more flexible constructors. --- src/NotesLoaderSM.cpp | 13 +++++-------- src/NotesLoaderSSC.cpp | 2 +- src/TimingData.h | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 632a00c2fe..4937e37b52 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -156,9 +156,8 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) // add in a warp. if( negBPM < 0 ) { - WarpSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(negBeat); - new_seg.m_fEndBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); + float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); + WarpSegment new_seg(negBeat, endBeat); out.AddWarpSegment( new_seg ); negBeat = -1; @@ -174,9 +173,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) // add in a warp. if( highspeedBeat > 0 ) { - WarpSegment new_seg; - new_seg.m_iStartRow = BeatToNoteRow(highspeedBeat); - new_seg.m_fEndBeat = fBeat; + WarpSegment new_seg(highspeedBeat, fBeat); out.AddWarpSegment( new_seg ); highspeedBeat = -1; } @@ -225,7 +222,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) if( negBeat + fSkipBeats > fFreezeBeat ) fSkipBeats = fFreezeBeat - negBeat; - WarpSegment ws( BeatToNoteRow(negBeat), negBeat + fSkipBeats); + WarpSegment ws( negBeat, negBeat + fSkipBeats); out.AddWarpSegment( ws ); negBeat = -1; @@ -252,7 +249,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) float fSecondsPerBeat = 60 / oldBPM.GetBPM(); float fSkipBeats = negPause / fSecondsPerBeat; - WarpSegment ws( BeatToNoteRow(negBeat), negBeat + fSkipBeats); + WarpSegment ws( negBeat, negBeat + fSkipBeats); out.AddWarpSegment( ws ); } } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 6a98aa0acd..1868dfd19d 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -507,7 +507,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach const float fNewBeat = StringToFloat( arrayWarpValues[1] ); if(fNewBeat > fBeat) - out.m_Timing.AddWarpSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat) ); + out.m_Timing.AddWarpSegment( WarpSegment(fBeat, fNewBeat) ); else { LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Warp at beat %f, BPM %f.", fBeat, fNewBeat ); diff --git a/src/TimingData.h b/src/TimingData.h index 6f43a3b818..f61afb6d9c 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -318,13 +318,13 @@ struct TimeSignatureSegment struct WarpSegment { /** - * @brief Creates a simple Warp Segment with default values. + * @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_fEndBeat(-1) { } /** - * @brief Creates a Warp Segment with the specified starting row and row to warp to. + * @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 row to warp to. */ @@ -337,6 +337,22 @@ struct WarpSegment */ WarpSegment( int s, float b ): m_iStartRow(max(0, s)), m_fEndBeat(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 row to warp to. + */ + WarpSegment( float s, int r ): + m_iStartRow(max(0, BeatToNoteRow(s))), + m_fEndBeat(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 beat to warp to. + */ + WarpSegment( float s, float b ): + m_iStartRow(max(0, BeatToNoteRow((s < b ? s : b)))), + m_fEndBeat(max(0, (b > s ? b : s))) {} /** * @brief The row in which the WarpSegment activates. */ From 1671337612fcf512456a4fbacae7490d0da3728b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 27 Mar 2011 03:09:36 -0400 Subject: [PATCH 40/40] [warps] Update changelogs. --- Docs/Changelog_SSCformat.txt | 3 +++ Docs/Changelog_sm-ssc.txt | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Docs/Changelog_SSCformat.txt b/Docs/Changelog_SSCformat.txt index c50c25737f..6bacef7c8d 100644 --- a/Docs/Changelog_SSCformat.txt +++ b/Docs/Changelog_SSCformat.txt @@ -9,6 +9,9 @@ change to JSON, but it is unsure if this will be done. Implement .ssc at your own risk. ________________________________________________________________________________ +[v0.66] - Wolfman2000 +* Implement #WARPS tag to replace negative bpm/stop gimmicks. + [v0.55] - Wolfman2000 * Add #COMBOS tag to the Song and Steps (does nothing here). diff --git a/Docs/Changelog_sm-ssc.txt b/Docs/Changelog_sm-ssc.txt index d6bac8ebd2..9abe52b9d6 100644 --- a/Docs/Changelog_sm-ssc.txt +++ b/Docs/Changelog_sm-ssc.txt @@ -16,7 +16,9 @@ sm-ssc v1.2.4 | 2011032? 20110326 -------- * [NotesLoaderSM, NotesWriterSSC] Officially add the #WARPS tag. The negative - tricks of the past are now officially standardized. [AJ, Thai, Wolfman2000] + tricks of the past are now officially standardized. Please tell us about + files which have broken sync or are otherwise unplayable/incorrect. + [AJ, Thai, Wolfman2000] 20110320 --------