From 8d80ddedf2f7ff3fa6ca94ec553d1f209507bd33 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 19 Mar 2011 19:38:45 +0700 Subject: [PATCH] Compress/Expand shall not break apart hold notes that overlaps the start/end marker. --- src/NoteDataUtil.cpp | 71 ++++++++++++++++++++++---------------------- src/ScreenEdit.cpp | 40 ++++++++----------------- 2 files changed, 49 insertions(+), 62 deletions(-) diff --git a/src/NoteDataUtil.cpp b/src/NoteDataUtil.cpp index a20e846c7b..9b5748ce39 100644 --- a/src/NoteDataUtil.cpp +++ b/src/NoteDataUtil.cpp @@ -2232,25 +2232,34 @@ void NoteDataUtil::AddTapAttacks( NoteData &nd, Song* pSong ) void NoteDataUtil::Scale( NoteData &nd, float fScale ) { ASSERT( fScale > 0 ); - - NoteData temp; - temp.CopyAll( nd ); - nd.ClearAll(); - - for( int r=0; r<=temp.GetLastRow(); r++ ) + + NoteData ndOut; + ndOut.SetNumTracks( nd.GetNumTracks() ); + + for( int t=0; tsecond; + int iNewRow = lrintf( fScale * iter->first ); + int iNewDuration = lrintf( fScale * (iter->first + tn.iDuration) ); + tn.iDuration = iNewDuration; + ndOut.SetTapNote( t, iNewRow, tn ); } } + + nd.swap( ndOut ); +} + +/* XXX: move this to an appropriate place, same place as NoteRowToBeat perhaps? */ +static inline int GetScaledRow( float fScale, int iStartIndex, int iEndIndex, int iRow ) +{ + if( iRow < iStartIndex ) + return iRow; + else if( iRow > iEndIndex ) + return iRow + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + else + return lrintf( (iRow - iStartIndex) * fScale ) + iStartIndex; } void NoteDataUtil::ScaleRegion( NoteData &nd, float fScale, int iStartIndex, int iEndIndex ) @@ -2258,31 +2267,23 @@ void NoteDataUtil::ScaleRegion( NoteData &nd, float fScale, int iStartIndex, int ASSERT( fScale > 0 ); ASSERT( iStartIndex < iEndIndex ); ASSERT( iStartIndex >= 0 ); - - NoteData temp1, temp2; - temp1.SetNumTracks( nd.GetNumTracks() ); - temp2.SetNumTracks( nd.GetNumTracks() ); - - if( iStartIndex != 0 ) - temp1.CopyRange( nd, 0, iStartIndex ); - if( iEndIndex != MAX_NOTE_ROW ) - { - const int iScaledFirstRowAfterRegion = int(iStartIndex + (iEndIndex - iStartIndex) * fScale); - temp1.CopyRange( nd, iEndIndex, MAX_NOTE_ROW, iScaledFirstRowAfterRegion ); - } - temp2.CopyRange( nd, iStartIndex, iEndIndex ); - nd.ClearAll(); - - for( int t=0; tfirst*fScale + iStartIndex ); - temp1.SetTapNote( t, new_row, iter->second ); + TapNote tn = iter->second; + int iNewRow = GetScaledRow( fScale, iStartIndex, iEndIndex, iter->first ); + int iNewDuration = GetScaledRow( fScale, iStartIndex, iEndIndex, iter->first + tn.iDuration ) - iNewRow; + tn.iDuration = iNewDuration; + ndOut.SetTapNote( t, iNewRow, tn ); } } - - nd.swap( temp1 ); + + nd.swap( ndOut ); } void NoteDataUtil::InsertRows( NoteData &nd, int iStartIndex, int iRowsToAdd ) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 49c10825ec..8a17a27059 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3419,11 +3419,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case tempo: { // This affects all steps. - const NoteData OldClipboard( m_Clipboard ); - HandleAreaMenuChoice( cut ); - AlterType at = (AlterType)iAnswers[c]; float fScale = -1; + switch( at ) { DEFAULT_FAIL( at ); @@ -3434,31 +3432,18 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns case expand_3_2: fScale = 1.5f; break; case expand_2x: fScale = 2; break; } - - switch( at ) - { - DEFAULT_FAIL( at ); - case compress_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break; - case compress_3_2: NoteDataUtil::Scale( m_Clipboard, fScale ); break; - case compress_4_3: NoteDataUtil::Scale( m_Clipboard, fScale ); break; - case expand_4_3: NoteDataUtil::Scale( m_Clipboard, fScale ); break; - case expand_3_2: NoteDataUtil::Scale( m_Clipboard, fScale ); break; - case expand_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break; - } - - int iOldClipboardRow = m_NoteFieldEdit.m_iEndMarker - m_NoteFieldEdit.m_iBeginMarker; - int iNewClipboardRow = lrintf( iOldClipboardRow * fScale ); - int iDeltaRows = iNewClipboardRow - iOldClipboardRow; - int iNewClipboardEndRow = m_NoteFieldEdit.m_iBeginMarker + iNewClipboardRow; - if( iDeltaRows > 0 ) - NoteDataUtil::InsertRows( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, iDeltaRows ); - else - NoteDataUtil::DeleteRows( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, -iDeltaRows ); - + + int iStartIndex = m_NoteFieldEdit.m_iBeginMarker; + int iEndIndex = m_NoteFieldEdit.m_iEndMarker; + int iNewEndIndex = iEndIndex + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); + + // scale currently editing notes + NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex ); + + // scale timing data m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); - HandleAreaMenuChoice( paste_at_begin_marker ); - + // scale all other steps. const vector sIter = m_pSong->GetAllSteps(); RString sTempStyle, sTempDiff; for( unsigned i = 0; i < sIter.size(); i++ ) @@ -3478,7 +3463,8 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns sIter[i]->SetNoteData( ndTemp ); } - m_NoteFieldEdit.m_iEndMarker = iNewClipboardEndRow; + m_NoteFieldEdit.m_iEndMarker = iNewEndIndex; + } break; case play: