From 324e07d383c988772f7306f9c2454cc2fe389239 Mon Sep 17 00:00:00 2001 From: Matt Denham Date: Thu, 26 Feb 2004 05:38:46 +0000 Subject: [PATCH] Implemented a quick pair of move/scale functions for TimingData fixed NoteDataUtil::ScaleRegion (and dealt with conflicts - whee) fixed assorted editor inconsistencies and bugs --- stepmania/src/NoteDataUtil.cpp | 15 ++++++--- stepmania/src/ScreenEdit.cpp | 47 +++++++++++++++++++++++++++- stepmania/src/TimingData.cpp | 56 +++++++++++++++++++++++++++++++++- stepmania/src/TimingData.h | 15 ++++++++- 4 files changed, 125 insertions(+), 8 deletions(-) diff --git a/stepmania/src/NoteDataUtil.cpp b/stepmania/src/NoteDataUtil.cpp index 9dfe537c1e..d4c11d84c0 100644 --- a/stepmania/src/NoteDataUtil.cpp +++ b/stepmania/src/NoteDataUtil.cpp @@ -1433,21 +1433,26 @@ void NoteDataUtil::Scale( NoteData &nd, float fScale ) } #endif -// added to fix things in the editor +// added to fix things in the editor - make sure that you're working off data that is +// either in 4s or in 2s and 3s. void NoteDataUtil::ScaleRegion( NoteData &nd, float fScale, float fStartBeat, float fEndBeat) { ASSERT( fScale > 0 ); + ASSERT( fStartBeat < fEndBeat ); + ASSERT( fStartBeat >= 0 ); NoteData temp1, temp2; temp1.Config( nd ); temp2.Config( nd ); - /* XXX: should these be BeatToNoteRow or BeatToNoteRowNotRounded? */ const int iFirstRowAtEndOfRegion = min( nd.GetLastRow(), BeatToNoteRowNotRounded(fEndBeat) ); + const int iScaledFirstRowAfterRegion = (int)((fStartBeat + (fEndBeat - fStartBeat) * fScale) * ROWS_PER_BEAT); - temp1.CopyRange( &nd, 0, BeatToNoteRowNotRounded(fStartBeat) ); - temp1.CopyRange( &nd, BeatToNoteRowNotRounded((fEndBeat - fStartBeat) * fScale), nd.GetLastRow(), iFirstRowAtEndOfRegion); - temp2.CopyRange( &nd, BeatToNoteRowNotRounded(fStartBeat), BeatToNoteRowNotRounded(fEndBeat) ); + if (fStartBeat != 0) + temp1.CopyRange( &nd, 0, fStartBeat * ROWS_PER_BEAT ); + if (nd.GetLastRow() > iFirstRowAtEndOfRegion) + temp1.CopyRange( &nd, iFirstRowAtEndOfRegion, nd.GetLastRow(), iScaledFirstRowAfterRegion); + temp2.CopyRange( &nd, fStartBeat * ROWS_PER_BEAT, iFirstRowAtEndOfRegion ); nd.ClearAll(); for( int r=0; r<=temp2.GetLastRow(); r++ ) diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index f67aa0c5fd..06450c5c24 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -1570,7 +1570,13 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers ) pNotes->SetNoteData( &m_NoteFieldEdit ); GAMESTATE->m_pCurSong->Save(); - SCREENMAN->SystemMessage( "Saved as SM and DWI." ); + // we shouldn't say we're saving a DWI if we're on any game besides + // dance, it just looks tacky and people may be wondering where the + // DWI file is :-) + if ((int)pNotes->m_StepsType <= (int)STEPS_TYPE_DANCE_SOLO) + SCREENMAN->SystemMessage( "Saved as SM and DWI." ); + else + SCREENMAN->SystemMessage( "Saved as SM." ); SOUND->PlayOnce( THEME->GetPathToS("ScreenEdit save") ); } break; @@ -1803,6 +1809,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) break; case tempo: { + // This affects ALL SETS OF STEPS; fun. HandleAreaMenuChoice( cut, NULL ); AlterType at = (AlterType)iAnswers[c]; @@ -1818,6 +1825,8 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) default: ASSERT(0); } + m_Clipboard.ConvertHoldNotesTo2sAnd3s(); + switch( at ) { case compress_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break; @@ -1829,12 +1838,36 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) default: ASSERT(0); } + m_Clipboard.Convert2sAnd3sToHoldNotes(); + // float fOldClipboardEndBeat = m_NoteFieldEdit.m_fEndMarker; float fOldClipboardBeats = m_NoteFieldEdit.m_fEndMarker - m_NoteFieldEdit.m_fBeginMarker; float fNewClipboardBeats = fOldClipboardBeats * fScale; float fDeltaBeats = fNewClipboardBeats - fOldClipboardBeats; float fNewClipboardEndBeat = m_NoteFieldEdit.m_fBeginMarker + fNewClipboardBeats; NoteDataUtil::ShiftRows( m_NoteFieldEdit, m_NoteFieldEdit.m_fBeginMarker, fDeltaBeats ); + m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker ); + + HandleAreaMenuChoice( paste_at_begin_marker, NULL ); + + const vector sIter = m_pSong->GetAllSteps(); + NoteData ndTemp; + CString sTempStyle, sTempDiff; + for (int i = 0; i < sIter.size(); i++) { + if (sIter[i]->IsAutogen()) { + continue; + } + if ((sIter[i]->m_StepsType == GAMESTATE->m_pCurNotes[PLAYER_1]->m_StepsType) && + (sIter[i]->GetDifficulty() == GAMESTATE->m_pCurNotes[PLAYER_1]->GetDifficulty())) { + continue; + } + + sIter[i]->GetNoteData( &ndTemp ); + ndTemp.ConvertHoldNotesTo2sAnd3s(); + NoteDataUtil::ScaleRegion( ndTemp, fScale, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker ); + ndTemp.Convert2sAnd3sToHoldNotes(); + sIter[i]->SetNoteData( &ndTemp ); + } HandleAreaMenuChoice( paste_at_begin_marker, NULL ); @@ -1926,9 +1959,11 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) break; case insert_and_shift: NoteDataUtil::ShiftRows( m_NoteFieldEdit, GAMESTATE->m_fSongBeat, 1 ); + m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat, 1 ); break; case delete_and_shift: NoteDataUtil::ShiftRows( m_NoteFieldEdit, GAMESTATE->m_fSongBeat, -1 ); + m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat, -1 ); break; // MD 11/02/03 - Converting selected region to a pause of the same length. case convert_beat_to_pause: @@ -1944,6 +1979,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) m_NoteFieldEdit.m_fBeginMarker + 0.003f, (-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker) ); + m_pSong->m_Timing.ShiftRows( m_NoteFieldEdit.m_fBeginMarker + 0.003f, + (-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker) + ); unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { @@ -1969,6 +2007,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) // wants to rewrite this to fix that behavior is welcome to - I'm // not sure how exactly to do it without making this a lot longer // than it is. + // NOTE: Fixed this so that holds aren't broken by it. Working in 2s and + // 3s makes this work better, too. :-) It sorta makes you wonder WHY we + // don't bring it into 2s and 3s when we bring up the editor. case convert_pause_to_beat: { float fBPMatPause = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat ); @@ -1989,7 +2030,11 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) fStopLength *= fBPMatPause; fStopLength /= 60; // don't move the step from where it is, just move everything later + m_NoteFieldEdit.ConvertHoldNotesTo2sAnd3s(); NoteDataUtil::ShiftRows( m_NoteFieldEdit, GAMESTATE->m_fSongBeat + 0.003f, fStopLength ); + m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat + 0.003f, fStopLength ); + m_NoteFieldEdit.Convert2sAnd3sToHoldNotes(); + } // Hello and welcome to I FEEL STUPID :-) break; diff --git a/stepmania/src/TimingData.cpp b/stepmania/src/TimingData.cpp index c227b669da..3afcb7c32e 100644 --- a/stepmania/src/TimingData.cpp +++ b/stepmania/src/TimingData.cpp @@ -197,8 +197,62 @@ float TimingData::GetElapsedTimeFromBeat( float fBeat ) const return fElapsedTime; } +void TimingData::ScaleRegion( float fScale, float fStartBeat, float fEndBeat ) { + ASSERT( fScale > 0 ); + ASSERT( fStartBeat >= 0 ); + ASSERT( fStartBeat < fEndBeat ); + + int ix = 0; + + for (ix = 0; ix < m_BPMSegments.size(); ix++) { + const float fSegStart = m_BPMSegments[ix].m_fStartBeat; + if (fSegStart < fStartBeat) + continue; + else if (fSegStart > fEndBeat) + m_BPMSegments[ix].m_fStartBeat += (fEndBeat - fStartBeat) * (fScale - 1); + else + m_BPMSegments[ix].m_fStartBeat = (fSegStart - fStartBeat) * fScale + fStartBeat; + } + + for (ix = 0; ix < m_StopSegments.size(); ix++) { + const float fSegStart = m_StopSegments[ix].m_fStartBeat; + if (fSegStart < fStartBeat) + continue; + else if (fSegStart > fEndBeat) + m_StopSegments[ix].m_fStartBeat += (fEndBeat - fStartBeat) * (fScale - 1); + else + m_StopSegments[ix].m_fStartBeat = (fSegStart - fStartBeat) * fScale + fStartBeat; + } +} + +void TimingData::ShiftRows( float fStartBeat, float fBeatsToShift ) { + int ix = 0; + + for (ix = 0; ix < m_BPMSegments.size(); ix++) { + const float fSegStart = m_BPMSegments[ix].m_fStartBeat; + if (fSegStart < fStartBeat) + continue; + else { + m_BPMSegments[ix].m_fStartBeat += fBeatsToShift; + if (m_BPMSegments[ix].m_fStartBeat < fStartBeat) + m_BPMSegments[ix].m_fStartBeat = fStartBeat; + } + } + + for (ix = 0; ix < m_StopSegments.size(); ix++) { + const float fSegStart = m_StopSegments[ix].m_fStartBeat; + if (fSegStart < fStartBeat) + continue; + else { + m_StopSegments[ix].m_fStartBeat += fBeatsToShift; + if (m_StopSegments[ix].m_fStartBeat < fStartBeat) + m_StopSegments[ix].m_fStartBeat = fStartBeat; + } + } +} + /* - * Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + * Copyright (c) 2001-2004 by the person(s) listed below. All rights reserved. * Chris Danford * Glenn Maynard */ diff --git a/stepmania/src/TimingData.h b/stepmania/src/TimingData.h index c9b93ebcb2..8570975602 100644 --- a/stepmania/src/TimingData.h +++ b/stepmania/src/TimingData.h @@ -39,6 +39,19 @@ public: } float GetElapsedTimeFromBeat( float fBeat ) const; + // used for editor fix - expand/contract needs to move BPMSegments + // and StopSegments that land during/after the edited range. + // in addition, we need to be able to shift them otherwise as well + // (for example, adding/removing rows should move all following + // segments as necessary) + // NOTE: How do we want to handle deleting rows that have a BPM change + // or a stop? I'd like to think we should move them to the first row + // of the range that was deleted (say if rows 1680-1728 are deleted, and + // a BPM change or a stop occurs at row 1704, we'll move it to row + // 1680). + void ScaleRegion( float fScale = 1, float fStartBeat = 0, float fEndBeat = 99999 ); + void ShiftRows( float fStartBeat, float fBeatsToShift ); + CString m_sFile; // informational only vector m_BPMSegments; // this must be sorted before gameplay vector m_StopSegments; // this must be sorted before gameplay @@ -48,7 +61,7 @@ public: #endif /* - * Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved. + * Copyright (c) 2001-2004 by the person(s) listed below. All rights reserved. * Chris Danford * Glenn Maynard */