From 9ffe6166e2927df4065584d1141003079892ae57 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sun, 15 May 2011 13:48:10 -0400 Subject: [PATCH] [splittiming] Implement, add lua hook. --- Docs/Luadoc/Lua.xml | 1 + Docs/Luadoc/LuaDocumentation.xml | 3 + src/TimingData.cpp | 124 ++++++++++++++++++++++++++++++- src/TimingData.h | 99 ++++++++++++++++++++++++ 4 files changed, 226 insertions(+), 1 deletion(-) diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index f41bb848cb..966502afbc 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -1405,6 +1405,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 39df9f4188..24492431aa 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -3516,6 +3516,9 @@ Returns true if the TimingData contains warps. + + Returns true if the TimingData contains speed scrolling changes. + diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 2f93424bc7..45302128b8 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -68,6 +68,11 @@ void TimingData::AddLabelSegment( const LabelSegment &seg ) m_LabelSegments.insert( upper_bound(m_LabelSegments.begin(), m_LabelSegments.end(), seg), seg ); } +void TimingData::AddSpeedSegment( const SpeedSegment &seg ) +{ + m_SpeedSegments.insert( upper_bound(m_SpeedSegments.begin(), m_SpeedSegments.end(), seg), seg ); +} + /* Change an existing BPM segment, merge identical segments together or insert a new one. */ void TimingData::SetBPMAtRow( int iNoteRow, float fBPM ) { @@ -250,6 +255,47 @@ void TimingData::SetLabelAtRow( int iRow, const RString sLabel ) } } +void TimingData::SetSpeedAtRow( int iRow, float fPercent, float fWait ) +{ + unsigned i; + for( i = 0; i < m_SpeedSegments.size(); i++ ) + { + if( m_SpeedSegments[i].m_iStartRow >= iRow) + break; + } + + if ( i == m_SpeedSegments.size() || m_SpeedSegments[i].m_iStartRow != iRow ) + { + if( i == 0 || + ( m_SpeedSegments[i-1].m_fPercent != fPercent + || m_SpeedSegments[i-1].m_fWait != fWait ) ) + AddSpeedSegment( SpeedSegment(iRow, fPercent, fWait) ); + } + else + { + if( i > 0 && m_SpeedSegments[i-1].m_fPercent == fPercent + && m_SpeedSegments[i-1].m_fWait == fWait ) + m_SpeedSegments.erase( m_SpeedSegments.begin()+i, + m_SpeedSegments.begin()+i+1 ); + else + { + m_SpeedSegments[i].m_fPercent = fPercent; + m_SpeedSegments[i].m_fWait = fWait; + } + } +} + +void TimingData::SetSpeedPercentAtRow( int iRow, float fPercent ) +{ + SetSpeedAtRow( iRow, fPercent, GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fWait ); +} + +void TimingData::SetSpeedWaitAtRow( int iRow, float fWait ) +{ + SetSpeedAtRow( iRow, GetSpeedSegmentAtBeat( NoteRowToBeat( iRow ) ).m_fPercent, fWait ); +} + + float TimingData::GetStopAtRow( int iNoteRow, bool bDelay ) const { for( unsigned i=0; i(i); } +int TimingData::GetSpeedSegmentIndexAtRow( int iRow ) const +{ + unsigned i; + for (i=0; i < m_SpeedSegments.size() - 1; i++ ) + if( m_SpeedSegments[i+1].m_iStartRow > iRow ) + break; + return static_cast(i); +} + BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow ) { static BPMSegment empty; @@ -451,6 +516,15 @@ TimeSignatureSegment& TimingData::GetTimeSignatureSegmentAtRow( int iRow ) return m_vTimeSignatureSegments[i]; } +SpeedSegment& TimingData::GetSpeedSegmentAtRow( int iRow ) +{ + unsigned i; + for( i=0; i iRow ) + break; + return m_SpeedSegments[i]; +} + int TimingData::GetTimeSignatureNumeratorAtRow( int iRow ) { return GetTimeSignatureSegmentAtRow( iRow ).m_iNumerator; @@ -845,6 +919,17 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool m_LabelSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; } + for ( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) + { + const int iSegStart = m_SpeedSegments[i].m_iStartRow; + if( iSegStart < iStartIndex ) + continue; + else if( iSegStart > iEndIndex ) + m_SpeedSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + else + m_SpeedSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; + } + // adjust BPM changes to preserve timing if( bAdjustBPM ) { @@ -929,6 +1014,14 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) continue; labl.m_iStartRow += iRowsToAdd; } + + for( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) + { + SpeedSegment &sped = m_SpeedSegments[i]; + if( sped.m_iStartRow < iStartRow ) + continue; + sped.m_iStartRow += iRowsToAdd; + } if( iStartRow == 0 ) { @@ -1086,6 +1179,22 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) } labl.m_iStartRow -= iRowsToDelete; } + + for( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) + { + SpeedSegment &sped = m_SpeedSegments[i]; + + if( sped.m_iStartRow < iStartRow ) + continue; + + if( sped.m_iStartRow < iStartRow+iRowsToDelete ) + { + m_SpeedSegments.erase( m_SpeedSegments.begin()+i, m_SpeedSegments.begin()+i+1 ); + --i; + continue; + } + sped.m_iStartRow -= iRowsToDelete; + } this->SetBPMAtRow( iStartRow, fNewBPM ); } @@ -1133,7 +1242,13 @@ void TimingData::TidyUpData() LabelSegment seg(0, "Song Start"); m_LabelSegments.push_back( seg ); } - + + // Always be sure there is a starting speed. + if( m_SpeedSegments.empty() ) + { + SpeedSegment seg(0, 1, 0); + m_SpeedSegments.push_back( seg ); + } } @@ -1155,6 +1270,11 @@ bool TimingData::HasWarps() const return m_WarpSegments.size()>0; } +bool TimingData::HasSpeedChanges() const +{ + return m_SpeedSegments.size()>1; +} + void TimingData::NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const { iMeasureIndexOut = 0; @@ -1201,6 +1321,7 @@ 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 HasSpeedChanges( T* p, lua_State *L ) { lua_pushboolean(L, p->HasSpeedChanges()); return 1; } static int GetStops( T* p, lua_State *L ) { vector vStops; @@ -1288,6 +1409,7 @@ public: ADD_METHOD( HasStops ); ADD_METHOD( HasBPMChanges ); ADD_METHOD( HasWarps ); + ADD_METHOD( HasSpeedChanges ); ADD_METHOD( GetStops ); ADD_METHOD( GetDelays ); ADD_METHOD( GetBPMs ); diff --git a/src/TimingData.h b/src/TimingData.h index c1d1b2ea87..d68e2ec98e 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1339,6 +1339,101 @@ public: */ float GetNextLabelSegmentBeatAtBeat( float fBeat ) const { return GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); } + + /** + * @brief Retrieve the Speed's percent at the given row. + * @param iNoteRow the row in question. + * @return the percent. + */ + float GetSpeedPercentAtRow( int iNoteRow ); + /** + * @brief Retrieve the Speed's percent at the given beat. + * @param fBeat the beat in question. + * @return the percent. + */ + float GetSpeedPercentAtBeat( float fBeat ) { return GetSpeedPercentAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Retrieve the Speed's wait at the given row. + * @param iNoteRow the row in question. + * @return the wait. + */ + float GetSpeedWaitAtRow( int iNoteRow ); + /** + * @brief Retrieve the Speed's wait at the given beat. + * @param fBeat the beat in question. + * @return the wait. + */ + float GetSpeedWaitAtBeat( float fBeat ) { return GetSpeedWaitAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Set the row to have the new Speed. + * @param iNoteRow the row to have the new Speed. + * @param fPercent the percent. + * @param fWait the wait. + */ + void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait ); + /** + * @brief Set the beat to have the new Speed. + * @param fBeat the beat to have the new Speed. + * @param fPercent the percent. + * @param fWait the wait. + */ + void SetSpeedAtBeat( float fBeat, float fPercent, float fWait ) { SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait ); } + /** + * @brief Set the row to have the new Speed percent. + * @param iNoteRow the row to have the new Speed percent. + * @param fPercent the percent. + */ + void SetSpeedPercentAtRow( int iNoteRow, float fPercent ); + /** + * @brief Set the beat to have the new Speed percent. + * @param fBeat the beat to have the new Speed percent. + * @param fPercent the percent. + */ + void SetSpeedPercentAtBeat( float fBeat, float fPercent ) { SetSpeedPercentAtRow( BeatToNoteRow(fBeat), fPercent); } + /** + * @brief Set the row to have the new Speed wait. + * @param iNoteRow the row to have the new Speed wait. + * @param fWait the wait. + */ + void SetSpeedWaitAtRow( int iNoteRow, float fWait ); + /** + * @brief Set the beat to have the new Speed wait. + * @param fBeat the beat to have the new Speed wait. + * @param fWait the wait. + */ + void SetSpeedWaitAtBeat( float fBeat, float fWait ) { SetSpeedWaitAtRow( BeatToNoteRow(fBeat), fWait); } + /** + * @brief Retrieve the SpeedSegment at the specified row. + * @param iNoteRow the row that has a SpeedSegment. + * @return the SpeedSegment in question. + */ + SpeedSegment& GetSpeedSegmentAtRow( int iNoteRow ); + /** + * @brief Retrieve the SpeedSegment at the specified beat. + * @param fBeat the beat that has a SpeedSegment. + * @return the SpeedSegment in question. + */ + SpeedSegment& GetSpeedSegmentAtBeat( float fBeat ) { return GetSpeedSegmentAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Retrieve the index of the SpeedSegments at the specified row. + * @param iNoteRow the row that has a SpeedSegment. + * @return the SpeedSegment's index in question. + */ + int GetSpeedSegmentIndexAtRow( int iNoteRow ) const; + /** + * @brief Retrieve the index of the SpeedSegments at the specified beat. + * @param fBeat the beat that has a SpeedSegment. + * @return the SpeedSegment's index in question. + */ + int GetSpeedSegmentIndexAtBeat( float fBeat ) const { return GetSpeedSegmentIndexAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Add the SpeedSegment to the TimingData. + * @param seg the new SpeedSegment. + */ + void AddSpeedSegment( const SpeedSegment &seg ); + + + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const; @@ -1381,6 +1476,10 @@ public: * @return true if there is at least one warp, false otherwise. */ bool HasWarps() const; + /** + * @brief View the TimingData to see if a song changes its speed scrolling at any point. + * @return true if there is at least one change, false otherwise. */ + bool HasSpeedChanges() const; /** * @brief Compare two sets of timing data to see if they are equal. * @param other the other TimingData.