From 0994bd64bc1248739092ec7924c862c10fac1780 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 11:12:47 +0700 Subject: [PATCH 1/7] fix crash in NotesLoaderBMS --- src/NotesLoaderBMS.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/NotesLoaderBMS.cpp b/src/NotesLoaderBMS.cpp index b87a603042..3f0f2fb394 100644 --- a/src/NotesLoaderBMS.cpp +++ b/src/NotesLoaderBMS.cpp @@ -1183,14 +1183,17 @@ bool BMSLoader::LoadFromDir( const RString &sDir, Song &out ) Steps* pNewNotes = apSteps[i]; const bool ok = LoadFromBMSFile( out.GetSongDir() + arrayBMSFileNames[i], aBMSData[i], *pNewNotes, out, mapFilenameToKeysoundIndex ); if( ok ) + { + // set song's timing data to the main file. + if( i == iMainDataIndex ) + out.m_SongTiming = pNewNotes->m_Timing; + out.AddSteps( pNewNotes ); + } else delete pNewNotes; } - // set song's timing data to the main file. - out.m_SongTiming = apSteps[iMainDataIndex]->m_Timing; - SlideDuplicateDifficulties( out ); ConvertString( out.m_sMainTitle, "utf-8,japanese" ); From aa0eb7f5d72fd26e32dee21788cc3506318f212a Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 11:43:08 +0700 Subject: [PATCH 2/7] GetSpeedMultiplier in ArrowEffects becomes TimingData::GetDisplayedSpeedPercent. We might need to use it later in other parts (NoteField). --- src/ArrowEffects.cpp | 46 +------------------------------------------- src/TimingData.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++ src/TimingData.h | 2 ++ 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index e408967789..2e3a1b6144 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -211,50 +211,6 @@ void ArrowEffects::Update() } } -float GetSpeedMultiplier( float fSongBeat, float fMusicSeconds, const TimingData &tim ) -{ - if( tim.m_SpeedSegments.size() == 0 ) - return 1.0; - - const int index = tim.GetSpeedSegmentIndexAtBeat( fSongBeat ); - - const SpeedSegment &seg = tim.m_SpeedSegments[index]; - float fStartBeat = NoteRowToBeat(seg.m_iStartRow); - float fStartTime = tim.GetElapsedTimeFromBeat( fStartBeat ) - tim.GetDelayAtBeat( fStartBeat ); - float fEndTime; - float fCurTime = fMusicSeconds; - - if( seg.m_usMode == 1 ) // seconds - { - fEndTime = fStartTime + seg.m_fWait; - } - else - { - fEndTime = tim.GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ) - tim.GetDelayAtBeat( fStartBeat + seg.m_fWait ); - } - - if( ( index == 0 && tim.m_SpeedSegments[0].m_fWait > 0.0 ) && fCurTime < fStartTime ) - { - return 1.0; - } - else if( fEndTime >= fCurTime && ( index > 0 || tim.m_SpeedSegments[0].m_fWait > 0.0 ) ) - { - const float fPriorSpeed = ( index == 0 ? 1 : tim.m_SpeedSegments[index - 1].m_fPercent ); - float fTimeUsed = fCurTime - fStartTime; - float fDuration = fEndTime - fStartTime; - float fRatioUsed = fDuration == 0.0 ? 1 : fTimeUsed / fDuration; - - float fDistance = fPriorSpeed - seg.m_fPercent; - float fRatioNeed = fRatioUsed * -fDistance; - return (fPriorSpeed + fRatioNeed); - } - else - { - return seg.m_fPercent; - } - -} - /* For visibility testing: if bAbsolute is false, random modifiers must return * the minimum possible scroll speed. */ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, float &fPeakYOffsetOut, bool &bIsPastPeakOut, bool bAbsolute ) @@ -277,7 +233,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float { float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep; - float fSpeedMultiplier = ( GAMESTATE->m_bInStepEditor || !GAMESTATE->m_bIsUsingStepTiming ) ? 1.0 : GetSpeedMultiplier( position.m_fSongBeatVisible, position.m_fMusicSecondsVisible, pCurSteps->m_Timing ); + float fSpeedMultiplier = ( GAMESTATE->m_bInStepEditor || !GAMESTATE->m_bIsUsingStepTiming ) ? 1.0 : pCurSteps->m_Timing.GetDisplayedSpeedPercent( position.m_fSongBeatVisible, position.m_fMusicSecondsVisible ); fYOffset += fSpeedMultiplier * fYOffsetBeatSpacing * (1-pPlayerState->m_PlayerOptions.GetCurrent().m_fTimeSpacing); } diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 9e7f064cf1..cf8e3fb728 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1341,6 +1341,50 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) this->SetBPMAtRow( iStartRow, fNewBPM ); } +float TimingData::GetDisplayedSpeedPercent( float fSongBeat, float fMusicSeconds ) +{ + if( m_SpeedSegments.size() == 0 ) + return 1.0; + + const int index = GetSpeedSegmentIndexAtBeat( fSongBeat ); + + const SpeedSegment &seg = m_SpeedSegments[index]; + float fStartBeat = NoteRowToBeat(seg.m_iStartRow); + float fStartTime = GetElapsedTimeFromBeat( fStartBeat ) - GetDelayAtBeat( fStartBeat ); + float fEndTime; + float fCurTime = fMusicSeconds; + + if( seg.m_usMode == 1 ) // seconds + { + fEndTime = fStartTime + seg.m_fWait; + } + else + { + fEndTime = GetElapsedTimeFromBeat( fStartBeat + seg.m_fWait ) - GetDelayAtBeat( fStartBeat + seg.m_fWait ); + } + + if( ( index == 0 && m_SpeedSegments[0].m_fWait > 0.0 ) && fCurTime < fStartTime ) + { + return 1.0; + } + else if( fEndTime >= fCurTime && ( index > 0 || m_SpeedSegments[0].m_fWait > 0.0 ) ) + { + const float fPriorSpeed = ( index == 0 ? 1 : m_SpeedSegments[index - 1].m_fPercent ); + float fTimeUsed = fCurTime - fStartTime; + float fDuration = fEndTime - fStartTime; + float fRatioUsed = fDuration == 0.0 ? 1 : fTimeUsed / fDuration; + + float fDistance = fPriorSpeed - seg.m_fPercent; + float fRatioNeed = fRatioUsed * -fDistance; + return (fPriorSpeed + fRatioNeed); + } + else + { + return seg.m_fPercent; + } + +} + void TimingData::TidyUpData() { // If there are no BPM segments, provide a default. diff --git a/src/TimingData.h b/src/TimingData.h index 21add1ba39..f64b9054c7 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1594,6 +1594,8 @@ public: */ void AddSpeedSegment( const SpeedSegment &seg ); + float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ); + /** * @brief Determine when the fakes end. * @param iRow The row you start on. From 5cde71754719723bc2af117ef08f14fb9870edc0 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 12:27:03 +0700 Subject: [PATCH 3/7] GetDisplayedSpeedPercent should be const --- src/TimingData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TimingData.h b/src/TimingData.h index f64b9054c7..c44b4da58a 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1594,7 +1594,7 @@ public: */ void AddSpeedSegment( const SpeedSegment &seg ); - float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ); + float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ) const; /** * @brief Determine when the fakes end. From 0533e742c5b6b1175722140eb5d1eb99ddd0e73c Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 12:29:55 +0700 Subject: [PATCH 4/7] a const is need on TimingData.cpp too --- src/TimingData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index cf8e3fb728..ced065bb8e 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1341,7 +1341,7 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) this->SetBPMAtRow( iStartRow, fNewBPM ); } -float TimingData::GetDisplayedSpeedPercent( float fSongBeat, float fMusicSeconds ) +float TimingData::GetDisplayedSpeedPercent( float fSongBeat, float fMusicSeconds ) const { if( m_SpeedSegments.size() == 0 ) return 1.0; From 51229ad086756e61a2bddb1abc0f2dc1c6ca885f Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 12:44:48 +0700 Subject: [PATCH 5/7] limit searching to 16 beats --- src/NoteField.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index b687c88ce6..4266675887 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -708,6 +708,7 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB // Adjust search distance so that notes don't pop onto the screen. float fSearchDistance = 10; float fLastBeatToDraw = GetDisplayedPosition(pPlayerState)->m_fSongBeat+fSearchDistance; + float fSpeedMultiplier = GetDisplayedTiming(pPlayerState)->GetDisplayedSpeedPercent(GetDisplayedPosition(pPlayerState)->m_fSongBeatVisible, GetDisplayedPosition(pPlayerState)->m_fMusicSecondsVisible); const int NUM_ITERATIONS = 20; @@ -733,6 +734,11 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB fSearchDistance /= 2; } + if( fSpeedMultiplier < 0.75 ) + { + fLastBeatToDraw = min(fLastBeatToDraw, GetDisplayedPosition(pPlayerState)->m_fSongBeat + 16); + } + return fLastBeatToDraw; } From ddbecd5de491b5baec142fc959f1146bae13b841 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 13:07:59 +0700 Subject: [PATCH 6/7] add a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warpsadd a comment about behavior of stops and delays in warps --- src/TimingData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index ced065bb8e..24035ab690 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -515,6 +515,7 @@ bool TimingData::IsWarpAtRow( int iNoteRow ) const const WarpSegment& s = m_WarpSegments[i]; if( s.m_iStartRow <= iNoteRow && iNoteRow < (s.m_iStartRow + BeatToNoteRow(s.m_fLengthBeats) ) ) { + // Allow stops inside warps to allow things like stop, warp, stop, warp, stop, and so on. if( m_StopSegments.empty() ) { return true; From ccc66ccaeb8ab69d49ab6c1997971df0546be9eb Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Tue, 24 May 2011 13:30:21 +0700 Subject: [PATCH 7/7] disable editing wait and mode on a row without a speed segment. enabling it is no-op anyway. --- src/ScreenEdit.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 0c9faf76ae..65d41e3c54 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3204,6 +3204,8 @@ void ScreenEdit::DisplayTimingMenu() { float fBeat = GetBeat(); TimingData &pTime = GetAppropriateTiming(); + bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).m_iStartRow == BeatToNoteRow( fBeat ); + g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pTime.m_fBeat0OffsetInSeconds) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetStopAtBeat( fBeat ) ) ) ; @@ -3213,8 +3215,8 @@ void ScreenEdit::DisplayTimingMenu() 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 ) ) ); - g_TimingDataInformation.rows[speed_percent].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetSpeedPercentAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetSpeedWaitAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[speed_percent].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.5f", pTime.GetSpeedPercentAtBeat( fBeat ) ) : "---" ); + g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.5f", pTime.GetSpeedWaitAtBeat( fBeat ) ) : "---" ); RString starting = ( pTime.GetSpeedModeAtBeat( fBeat ) == 1 ? "Seconds" : "Beats" ); g_TimingDataInformation.rows[speed_mode].SetOneUnthemedChoice( starting.c_str() ); @@ -3224,8 +3226,8 @@ void ScreenEdit::DisplayTimingMenu() g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[speed_percent].bEnabled = GAMESTATE->m_bIsUsingStepTiming; - g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsUsingStepTiming; - g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsUsingStepTiming; + g_TimingDataInformation.rows[speed_wait].bEnabled = GAMESTATE->m_bIsUsingStepTiming && bHasSpeedOnThisRow; + g_TimingDataInformation.rows[speed_mode].bEnabled = GAMESTATE->m_bIsUsingStepTiming && bHasSpeedOnThisRow; g_TimingDataInformation.rows[fake].bEnabled = GAMESTATE->m_bIsUsingStepTiming; EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation );