From 68f95ce0564bf43564fbdc969f281ee21eb99e09 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sun, 26 Jun 2011 13:43:30 +0700 Subject: [PATCH] Refactor TimingData::ScaleRegion(), fixes 297. --- src/NoteTypes.h | 18 +++++- src/TimingData.cpp | 135 +++++------------------------------------ src/TimingSegments.cpp | 29 ++++++++- src/TimingSegments.h | 12 ++++ 4 files changed, 70 insertions(+), 124 deletions(-) diff --git a/src/NoteTypes.h b/src/NoteTypes.h index cd00810e0a..795eef7131 100644 --- a/src/NoteTypes.h +++ b/src/NoteTypes.h @@ -334,7 +334,23 @@ static inline float ToBeat(int row) { return NoteRowToBeat(row); } */ static inline float ToBeat(float beat) { return beat; } - +/** + * @brief Scales the position. + * @param T start - the starting row of the scaling region + * @param T length - the length of the scaling region + * @param T newLength - the new length of the scaling region + * @param T position - the position to scale + * @return T the scaled position + */ +template +inline T ScalePosition( T start, T length, T newLength, T position ) +{ + if( position < start ) + return position; + if( position >= start + length ) + return position - length + newLength; + return start + (position - start) * newLength / length; +} #endif diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 579d11c635..20f9e47642 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1026,149 +1026,43 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool ASSERT( iStartIndex >= 0 ); ASSERT( iStartIndex < iEndIndex ); + int length = iEndIndex - iStartIndex; + int newLength = lrintf( fScale * length ); + for ( unsigned i = 0; i < m_BPMSegments.size(); i++ ) - { - BPMSegment &b = m_BPMSegments[i]; - const int iSegStart = b.GetRow(); - if( iSegStart < iStartIndex ) - continue; - else if( iSegStart > iEndIndex ) - b.SetRow( b.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ) ); - else - b.SetRow( lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex ); - } + m_BPMSegments[i].Scale( iStartIndex, length, newLength ); for( unsigned i = 0; i < m_StopSegments.size(); i++ ) - { - StopSegment &s = m_StopSegments[i]; - const int iSegStartRow = s.GetRow(); - if( iSegStartRow < iStartIndex ) - continue; - else if( iSegStartRow > iEndIndex ) - s.SetRow(s.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); - else - s.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); - } + m_StopSegments[i].Scale( iStartIndex, length, newLength ); for( unsigned i = 0; i < m_vTimeSignatureSegments.size(); i++ ) - { - TimeSignatureSegment &t = m_vTimeSignatureSegments[i]; - const int iSegStartRow = t.GetRow(); - if( iSegStartRow < iStartIndex ) - continue; - else if( iSegStartRow > iEndIndex ) - t.SetRow(t.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); - else - t.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); - } + m_vTimeSignatureSegments[i].Scale( iStartIndex, length, newLength ); for( unsigned i = 0; i < m_WarpSegments.size(); i++ ) - { - WarpSegment &w = m_WarpSegments[i]; - const int iSegStartRow = w.GetRow(); - const int iSegEndRow = iSegStartRow + BeatToNoteRow( w.GetLength() ); - if( iSegEndRow >= iStartIndex ) - { - if( iSegEndRow > iEndIndex ) - w.SetLength(w.GetLength() + - NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1)))); - else - w.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale))); - } - if( iSegStartRow < iStartIndex ) - continue; - else if( iSegStartRow > iEndIndex ) - w.SetRow(w.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); - else - w.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); - } + m_WarpSegments[i].Scale( iStartIndex, length, newLength ); for ( unsigned i = 0; i < m_TickcountSegments.size(); i++ ) - { - TickcountSegment &t = m_TickcountSegments[i]; - const int iSegStart = t.GetRow(); - if( iSegStart < iStartIndex ) - continue; - else if( iSegStart > iEndIndex ) - t.SetRow(t.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); - else - t.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); - } + m_TickcountSegments[i].Scale( iStartIndex, length, newLength ); for ( unsigned i = 0; i < m_ComboSegments.size(); i++ ) - { - ComboSegment &c = m_ComboSegments[i]; - const int iSegStart = c.GetRow(); - if( iSegStart < iStartIndex ) - continue; - else if( iSegStart > iEndIndex ) - c.SetRow(c.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); - else - c.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); - } + m_ComboSegments[i].Scale( iStartIndex, length, newLength ); for ( unsigned i = 0; i < m_LabelSegments.size(); i++ ) - { - LabelSegment &l = m_LabelSegments[i]; - const int iSegStart = l.GetRow(); - if( iSegStart < iStartIndex ) - continue; - else if( iSegStart > iEndIndex ) - l.SetRow(l.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); - else - l.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); - } + m_LabelSegments[i].Scale( iStartIndex, length, newLength ); for ( unsigned i = 0; i < m_SpeedSegments.size(); i++ ) - { - SpeedSegment &s = m_SpeedSegments[i]; - const int iSegStart = s.GetRow(); - if( iSegStart < iStartIndex ) - continue; - else if( iSegStart > iEndIndex ) - s.SetRow(s.GetRow() + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) )); - else - s.SetRow(lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex); - } + m_SpeedSegments[i].Scale( iStartIndex, length, newLength ); for( unsigned i = 0; i < m_FakeSegments.size(); i++ ) - { - FakeSegment &f = m_FakeSegments[i]; - const int iSegStartRow = f.GetRow(); - const int iSegEndRow = iSegStartRow + BeatToNoteRow( f.GetLength() ); - if( iSegEndRow >= iStartIndex ) - { - if( iSegEndRow > iEndIndex ) - f.SetLength(f.GetLength() - + NoteRowToBeat(lrintf((iEndIndex - iStartIndex) * (fScale - 1)))); - else - f.SetLength(NoteRowToBeat(lrintf((iSegEndRow - iStartIndex) * fScale))); - } - if( iSegStartRow < iStartIndex ) - continue; - else if( iSegStartRow > iEndIndex ) - f.SetRow(f.GetRow() - + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); - else - f.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); - } + m_FakeSegments[i].Scale( iStartIndex, length, newLength ); for( unsigned i = 0; i < m_ScrollSegments.size(); i++ ) - { - ScrollSegment &s = m_ScrollSegments[i]; - const int iSegStartRow = s.GetRow(); - if( iSegStartRow < iStartIndex ) - continue; - else if( iSegStartRow > iEndIndex ) - s.SetRow(s.GetRow() + lrintf((iEndIndex - iStartIndex) * (fScale - 1))); - else - s.SetRow(lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex); - } + m_ScrollSegments[i].Scale( iStartIndex, length, newLength ); // adjust BPM changes to preserve timing if( bAdjustBPM ) { - int iNewEndIndex = lrintf( (iEndIndex - iStartIndex) * fScale ) + iStartIndex; + int iNewEndIndex = iStartIndex + newLength; float fEndBPMBeforeScaling = GetBPMAtRow(iNewEndIndex); // adjust BPM changes "between" iStartIndex and iNewEndIndex @@ -1186,7 +1080,6 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool // set BPM at iStartIndex and iNewEndIndex. SetBPMAtRow( iStartIndex, GetBPMAtRow(iStartIndex) * fScale ); SetBPMAtRow( iNewEndIndex, fEndBPMBeforeScaling ); - } } diff --git a/src/TimingSegments.cpp b/src/TimingSegments.cpp index 64aeee8b01..6a0e0eec57 100644 --- a/src/TimingSegments.cpp +++ b/src/TimingSegments.cpp @@ -5,7 +5,6 @@ BaseTimingSegment::~BaseTimingSegment() {} - void BaseTimingSegment::SetRow(const int s) { this->startingRow = s; @@ -26,6 +25,11 @@ float BaseTimingSegment::GetBeat() const return NoteRowToBeat(GetRow()); } +void BaseTimingSegment::Scale( int start, int length, int newLength ) +{ + SetRow( ScalePosition( start, length, newLength, GetRow() ) ); +} + /* ====================================================== Here comes the actual timing segments implementation!! */ @@ -40,6 +44,16 @@ void FakeSegment::SetLength(const float b) this->lengthBeats = b; } +void FakeSegment::Scale( int start, int length, int newLength ) +{ + float startBeat = GetBeat(); + float endBeat = startBeat + GetLength(); + float newStartBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), startBeat ); + float newEndBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), endBeat ); + SetLength( newEndBeat - newStartBeat ); + TimingSegment::Scale( start, length, newLength ); +} + bool FakeSegment::operator<( const FakeSegment &other ) const { LTCOMPARE(GetRow()); @@ -60,8 +74,19 @@ void WarpSegment::SetLength(const float b) this->lengthBeats = b; } +void WarpSegment::Scale( int start, int length, int newLength ) +{ + // XXX: this function is duplicated, there should be a better way + float startBeat = GetBeat(); + float endBeat = startBeat + GetLength(); + float newStartBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), startBeat ); + float newEndBeat = ScalePosition( NoteRowToBeat(start), NoteRowToBeat(length), NoteRowToBeat(newLength), endBeat ); + SetLength( newEndBeat - newStartBeat ); + TimingSegment::Scale( start, length, newLength ); +} + bool WarpSegment::operator<( const WarpSegment &other ) const -{ +{ LTCOMPARE(GetRow()); LTCOMPARE(GetLength()); return false; diff --git a/src/TimingSegments.h b/src/TimingSegments.h index 72e9a267c2..4acbe60350 100644 --- a/src/TimingSegments.h +++ b/src/TimingSegments.h @@ -27,6 +27,14 @@ struct BaseTimingSegment virtual ~BaseTimingSegment(); + /** + * @brief Scales itself. + * @param start Starting row + * @param length Length in rows + * @param newLength The new length in rows + */ + virtual void Scale( int start, int length, int newLength ); + /** * @brief Set the starting row of the BaseTimingSegment. * @@ -177,6 +185,8 @@ struct FakeSegment : public TimingSegment * @param b the length in beats. */ void SetLength(const float b); + void Scale( int start, int length, int newLength ); + /** * @brief Compares two FakeSegments to see if one is less than the other. * @param other the other FakeSegment to compare to. @@ -236,6 +246,8 @@ struct WarpSegment : public TimingSegment * @param b the length in beats. */ void SetLength(const float b); + void Scale( int start, int length, int newLength ); + /* * @brief Compares two WarpSegments to see if one is less than the other. * @param other the other WarpSegment to compare to.