From ba5bef76b50b9a46317486fad4929f1454c9119f Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 29 Jun 2011 20:26:05 -0400 Subject: [PATCH 01/21] Make holds and rolls use the same timing. Players may have to update their Preferences.ini file manually. --- src/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Player.cpp b/src/Player.cpp index b9f3c82d11..98c19b8d30 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -115,7 +115,7 @@ void TimingWindowSecondsInit( size_t /*TimingWindow*/ i, RString &sNameOut, floa case TW_W5: defaultValueOut = 0.180f; break; case TW_Mine: defaultValueOut = 0.090f; break; // same as great case TW_Hold: defaultValueOut = 0.500f; break; // allow enough time to take foot off and put back on - case TW_Roll: defaultValueOut = 0.350f; break; + case TW_Roll: defaultValueOut = 0.500f; break; case TW_Attack: defaultValueOut = 0.135f; break; } } From 92a304ab8aad879d7702d1ad7fc43bbb2b321917 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 29 Jun 2011 23:25:42 -0400 Subject: [PATCH 02/21] Minor simplification. We should eventually make it not required to scroll horizontally. --- src/ScreenGameplay.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 9936268534..475ca16250 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1696,7 +1696,8 @@ void ScreenGameplay::Update( float fDeltaTime ) // update fGameplaySeconds STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime; - if( GAMESTATE->m_Position.m_fSongBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat && GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) + float curBeat = GAMESTATE->m_Position.m_fSongBeat; + if( curBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat && curBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) { STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime; From a8da45978df27d759e8aab4dcfbc1e7472a85455 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 29 Jun 2011 23:32:14 -0400 Subject: [PATCH 03/21] Prep work for cache tag adjusting. Hopefully this won't take too long. --- src/Song.cpp | 3 +++ src/Song.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Song.cpp b/src/Song.cpp index caf5f08315..750605658e 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -69,6 +69,9 @@ Song::Song() m_fMusicSampleStartSeconds = -1; m_fMusicSampleLengthSeconds = DEFAULT_MUSIC_SAMPLE_LENGTH; m_fMusicLengthSeconds = 0; + firstSecond = -1; + lastSecond = -1; + specifiedLastSecond = -1; m_fFirstBeat = -1; m_fLastBeat = -1; m_fSpecifiedLastBeat = -1; diff --git a/src/Song.h b/src/Song.h index 990e553009..95dd3b1a6e 100644 --- a/src/Song.h +++ b/src/Song.h @@ -232,6 +232,9 @@ public: RString m_sInstrumentTrackFile[NUM_InstrumentTrack]; float m_fMusicLengthSeconds; + float firstSecond; + float lastSecond; + float specifiedLastSecond; float m_fFirstBeat; // beat of first note float m_fLastBeat; // beat of last note float m_fSpecifiedLastBeat; // specified last beat of the song From 4aa404d38ebfd1d02079f6f9db2e62bc77a4284f Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Wed, 29 Jun 2011 23:42:14 -0400 Subject: [PATCH 04/21] We should write 6 for consistency. Not worth a cache reload yet. --- src/NotesWriterSSC.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index dc9c63a5a2..528f438c66 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -367,12 +367,12 @@ bool NotesWriterSSC::Write( RString sPath, const Song &out, const vector if( bSavingCache ) { f.PutLine( ssprintf( "// cache tags:" ) ); - f.PutLine( ssprintf( "#FIRSTBEAT:%.3f;", out.m_fFirstBeat ) ); - f.PutLine( ssprintf( "#LASTBEAT:%.3f;", out.m_fLastBeat ) ); + f.PutLine( ssprintf( "#FIRSTBEAT:%.6f;", out.m_fFirstBeat ) ); + f.PutLine( ssprintf( "#LASTBEAT:%.6f;", out.m_fLastBeat ) ); f.PutLine( ssprintf( "#SONGFILENAME:%s;", out.m_sSongFileName.c_str() ) ); f.PutLine( ssprintf( "#HASMUSIC:%i;", out.m_bHasMusic ) ); f.PutLine( ssprintf( "#HASBANNER:%i;", out.m_bHasBanner ) ); - f.PutLine( ssprintf( "#MUSICLENGTH:%.3f;", out.m_fMusicLengthSeconds ) ); + f.PutLine( ssprintf( "#MUSICLENGTH:%.6f;", out.m_fMusicLengthSeconds ) ); f.PutLine( ssprintf( "// end cache tags" ) ); } From 00c1ce6a79ef75e5ad33079235ac37255484b12a Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 01:09:07 -0400 Subject: [PATCH 05/21] We store 6 decimals, so display 6 decimals. --- Themes/_fallback/metrics.ini | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 127d5862d7..6054b15099 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3650,12 +3650,12 @@ PlayRecordHelpOnCommand=halign,0;valign,0;shadowlength,1 LoopOnChartEnd=true -CurrentBeatFormat="%s:\n %.5f\n" -CurrentSecondFormat="%s:\n %.5f\n" +CurrentBeatFormat="%s:\n %.6f\n" +CurrentSecondFormat="%s:\n %.6f\n" SnapToFormat="%s: %s\n" -SelectionBeatBeginFormat="%s:\n %.5f" +SelectionBeatBeginFormat="%s:\n %.6f" SelectionBeatUnfinishedFormat=" ...\n" -SelectionBeatEndFormat="-%.5f\n" +SelectionBeatEndFormat="-%.6f\n" DifficultyFormat="%s:\n %s\n" RoutinePlayerFormat="%s:\n %d\n" DescriptionFormat="%s:\n %s\n" @@ -3674,9 +3674,9 @@ NumRollsFormat="%s: %d\n" NumLiftsFormat="%s: %d\n" NumFakesFormat="%s: %d\n" TimingModeFormat="%s:\n %s\n" -Beat0OffsetFormat="%s:\n %.5f secs\n" -PreviewStartFormat="%s:\n %.5f secs\n" -PreviewLengthFormat="%s:\n %.5f secs\n" +Beat0OffsetFormat="%s:\n %.6f secs\n" +PreviewStartFormat="%s:\n %.6f secs\n" +PreviewLengthFormat="%s:\n %.6f secs\n" [ScreenPracticeMenu] Fallback="ScreenEditMenu" From 8bc2c381422692e6fada50ed5121c644c1fcaaf3 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 01:11:38 -0400 Subject: [PATCH 06/21] Replace #BEAT tags with #SECOND tags. Split Timing has made this necessary. Yes, this means another recache. --- Docs/Changelog_SSCformat.txt | 5 ++ Docs/Changelog_sm5.txt | 6 +++ Docs/Luadoc/Lua.xml | 2 + Docs/Luadoc/LuaDocumentation.xml | 6 +++ Docs/SimfileFormats/ssc_msd5.txt | 2 +- Themes/_fallback/Languages/en.ini | 4 +- src/Background.cpp | 9 ++-- src/DancingCharacters.cpp | 8 +-- src/GameState.cpp | 3 +- src/Inventory.cpp | 4 +- src/LyricDisplay.cpp | 4 +- src/MeterDisplay.cpp | 4 +- src/NotesLoaderJson.cpp | 2 - src/NotesLoaderSM.cpp | 40 +++++---------- src/NotesLoaderSMA.cpp | 28 +++------- src/NotesLoaderSSC.cpp | 17 +++++-- src/NotesWriterJson.cpp | 4 +- src/NotesWriterSM.cpp | 4 +- src/NotesWriterSSC.cpp | 9 ++-- src/ScreenEdit.cpp | 85 +++++++++++++++++-------------- src/ScreenEdit.h | 2 +- src/ScreenGameplay.cpp | 19 ++++--- src/Song.cpp | 50 +++++++++++++----- src/Song.h | 2 +- 24 files changed, 178 insertions(+), 141 deletions(-) diff --git a/Docs/Changelog_SSCformat.txt b/Docs/Changelog_SSCformat.txt index 12cb56d7b8..20088bb92b 100644 --- a/Docs/Changelog_SSCformat.txt +++ b/Docs/Changelog_SSCformat.txt @@ -9,6 +9,11 @@ change to JSON, but it is unsure if this will be done. Implement .ssc at your own risk. ________________________________________________________________________________ +[v0.73] - Wolfman2000 +* Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the BEAT + equivalents. +* Move #LASTSECONDHINT to after the Timing tags. + [v0.72] - Wolfman2000 * Have #OFFSET come before #ATTACKS in the Step data. diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 3becdfa38c..51ae1cbde6 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,12 @@ ________________________________________________________________________________ StepMania 5.0 Preview 2 | 201106?? -------------------------------------------------------------------------------- +2011/06/30 +---------- +* [NotesAll] Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the + former BEAT equivalents. Split Timing has made this a necessity thanks to + certain files that abuse Stops/Delays more than usual. [Wolfman2000] + 2011/06/28 ---------- * [ScreenEdit] Add a function to copy/paste the TimingData of a player's diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 1785b00b94..ed192118a5 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -1244,9 +1244,11 @@ + + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 2098898a41..40d229921d 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -3084,6 +3084,9 @@ Returns the first beat of the song. + + Returns the first second of the song. + Returns the genre of the song. @@ -3093,6 +3096,9 @@ Returns the last beat of the song. + + Returns the last second of the song. + Gets the path to the lyrics. diff --git a/Docs/SimfileFormats/ssc_msd5.txt b/Docs/SimfileFormats/ssc_msd5.txt index 119f61b297..9c00273a64 100644 --- a/Docs/SimfileFormats/ssc_msd5.txt +++ b/Docs/SimfileFormats/ssc_msd5.txt @@ -21,11 +21,11 @@ #DELAYS:; #LABELS:; #TIMESIGNATURES:; -#LASTBEATHINT:; #SAMPLESTART:; #SAMPLELENGTH:; #DISPLAYBPM:[xxx][xxx:xxx]|[*]; #SELECTABLE:; +#LASTBEATHINT:; #BGCHANGES:; #FGCHANGES:; #KEYSOUNDS:; diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 1c796abc6b..e9f39cb930 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -916,7 +916,7 @@ Insert Entry=Insert Entry Jumps=Jumps Key Joy Mappings=Config Key/Joy Mappings Language=Language -Last beat hint=Last beat hint +Last second hint=Last second hint Layer=Layer LifeDifficulty=Life Difficulty LifeType=Life Type @@ -1256,7 +1256,7 @@ Enter a new chart style.=Enter a new chart style (e.g. "Pad", "Keyboard"). Enter a new meter.=Enter the difficulty rating for this chart. Enter the author who made this step pattern.=Enter the author who made this step pattern. Enter the offset for the song.=Enter the beat 0 offset for the song. -Enter a new last beat hint.=Enter a new last beat hint. +Enter a new last second hint.=Enter a new last second hint. Enter a new main title transliteration.=Enter a new main title transliteration. Enter a new main title.=Enter a new main title. Enter a new sub title transliteration.=Enter a new sub title transliteration. diff --git a/src/Background.cpp b/src/Background.cpp index 19e21abf7a..b86a86027e 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -577,13 +577,16 @@ void BackgroundImpl::LoadFromSong( const Song* pSong ) else // pSong doesn't have an animation plan { Layer &layer = m_Layer[0]; + const TimingData &t = pSong->m_SongTiming; + float firstBeat = t.GetBeatFromElapsedTime(pSong->firstSecond); + float lastBeat = t.GetBeatFromElapsedTime(pSong->lastSecond); - LoadFromRandom( pSong->m_fFirstBeat, pSong->m_fLastBeat, BackgroundChange() ); + LoadFromRandom( firstBeat, lastBeat, BackgroundChange() ); // end showing the static song background BackgroundChange change; change.m_def = m_StaticBackgroundDef; - change.m_fStartBeat = pSong->m_fLastBeat; + change.m_fStartBeat = lastBeat; layer.m_aBGChanges.push_back( change ); } @@ -642,7 +645,7 @@ void BackgroundImpl::LoadFromSong( const Song* pSong ) continue; float fStartBeat = change.m_fStartBeat; - float fEndBeat = pSong->m_fLastBeat; + float fEndBeat = pSong->m_SongTiming.GetBeatFromElapsedTime(pSong->lastSecond); if( i+1 < mainlayer.m_aBGChanges.size() ) fEndBeat = mainlayer.m_aBGChanges[i+1].m_fStartBeat; diff --git a/src/DancingCharacters.cpp b/src/DancingCharacters.cpp index 08088290eb..d9382c42d1 100644 --- a/src/DancingCharacters.cpp +++ b/src/DancingCharacters.cpp @@ -166,7 +166,8 @@ void DancingCharacters::LoadNextSong() m_fThisCameraEndBeat = 0; ASSERT( GAMESTATE->m_pCurSong ); - m_fThisCameraEndBeat = GAMESTATE->m_pCurSong->m_fFirstBeat; + Song &s = *GAMESTATE->m_pCurSong; + m_fThisCameraEndBeat = s.m_SongTiming.GetBeatFromElapsedTime(s.firstSecond); FOREACH_PlayerNumber( p ) if( GAMESTATE->IsPlayerEnabled(p) ) @@ -212,9 +213,10 @@ void DancingCharacters::Update( float fDelta ) bWasGameplayStarting = bGameplayStarting; static float fLastBeat = GAMESTATE->m_Position.m_fSongBeat; + Song &s = *GAMESTATE->m_pCurSong; + float firstBeat = s.m_SongTiming.GetBeatFromElapsedTime(s.firstSecond); float fThisBeat = GAMESTATE->m_Position.m_fSongBeat; - if( fLastBeat < GAMESTATE->m_pCurSong->m_fFirstBeat && - fThisBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat ) + if( fLastBeat < firstBeat && fThisBeat >= firstBeat ) { FOREACH_PlayerNumber( p ) m_pCharacter[p]->PlayAnimation( "dance" ); diff --git a/src/GameState.cpp b/src/GameState.cpp index fe0d7099de..1ba34d53f9 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -991,7 +991,8 @@ update player position code goes here float GameState::GetSongPercent( float beat ) const { // 0 = first step; 1 = last step - return (beat - m_pCurSong->m_fFirstBeat) / m_pCurSong->m_fLastBeat; + float curTime = this->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat(beat); + return (curTime - m_pCurSong->firstSecond) / m_pCurSong->lastSecond; } int GameState::GetNumStagesLeft( PlayerNumber pn ) const diff --git a/src/Inventory.cpp b/src/Inventory.cpp index d3f563c30a..71a30a9ba9 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -119,10 +119,10 @@ void Inventory::Update( float fDelta ) } } - + Song &song = *GAMESTATE->m_pCurSong; // use items if this player is CPU-controlled if( m_pPlayerState->m_PlayerController != PC_HUMAN && - GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) + GAMESTATE->m_Position.m_fSongBeat < song.m_SongTiming.GetBeatFromElapsedTime(song.lastSecond) ) { // every 1 seconds, try to use an item int iLastSecond = (int)(RageTimer::GetTimeSinceStartFast() - fDelta); diff --git a/src/LyricDisplay.cpp b/src/LyricDisplay.cpp index 7284d2dc17..a6bdfea918 100644 --- a/src/LyricDisplay.cpp +++ b/src/LyricDisplay.cpp @@ -59,8 +59,8 @@ void LyricDisplay::Update( float fDeltaTime ) if( m_iCurLyricNumber+1 < GAMESTATE->m_pCurSong->m_LyricSegments.size() ) fEndTime = pSong->m_LyricSegments[m_iCurLyricNumber+1].m_fStartTime; else - fEndTime = pSong->m_SongTiming.GetElapsedTimeFromBeat( pSong->m_fLastBeat ); - + fEndTime = pSong->lastSecond; + const float fDistance = fEndTime - pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime; const float fTweenBufferTime = IN_LENGTH.GetValue() + OUT_LENGTH.GetValue(); diff --git a/src/MeterDisplay.cpp b/src/MeterDisplay.cpp index 641b50d73c..5bc9da2e6a 100644 --- a/src/MeterDisplay.cpp +++ b/src/MeterDisplay.cpp @@ -73,8 +73,8 @@ void SongMeterDisplay::Update( float fDeltaTime ) { if( GAMESTATE->m_pCurSong ) { - float fSongStartSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fFirstBeat ); - float fSongEndSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); + float fSongStartSeconds = GAMESTATE->m_pCurSong->firstSecond; + float fSongEndSeconds = GAMESTATE->m_pCurSong->lastSecond; float fPercentPositionSong = SCALE( GAMESTATE->m_Position.m_fMusicSeconds, fSongStartSeconds, fSongEndSeconds, 0.0f, 1.0f ); CLAMP( fPercentPositionSong, 0, 1 ); diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp index 9d422d5177..dab70f29ee 100644 --- a/src/NotesLoaderJson.cpp +++ b/src/NotesLoaderJson.cpp @@ -150,8 +150,6 @@ static void Deserialize( Song &out, const Json::Value &root ) else if( sSelectable.EqualsNoCase("NO") ) out.m_SelectionDisplay = out.SHOW_NEVER; - out.m_fFirstBeat = (float)root["FirstBeat"].asDouble(); - out.m_fLastBeat = (float)root["LastBeat"].asDouble(); out.m_sSongFileName = root["SongFileName"].asString(); out.m_bHasMusic = root["HasMusic"].asBool(); out.m_bHasBanner = root["HasBanner"].asBool(); diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index fc5a59273e..82da1ffbbc 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -812,37 +812,19 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache } else if( sValueName=="LASTBEATHINT" ) - out.m_fSpecifiedLastBeat = StringToFloat( sParams[1] ); + { + // unable to identify at this point: ignore + } else if( sValueName=="MUSICBYTES" ) ; /* ignore */ - /* We calculate these. Some SMs in circulation have bogus values for - * these, so make sure we always calculate it ourself. */ - else if( sValueName=="FIRSTBEAT" ) + // cache tags from older SM files: ignore. + else if(sValueName=="FIRSTBEAT" || sValueName=="LASTBEAT" || + sValueName=="SONGFILENAME" || sValueName=="HASMUSIC" || + sValueName=="HASBANNER") { - if( bFromCache ) - out.m_fFirstBeat = StringToFloat( sParams[1] ); - } - else if( sValueName=="LASTBEAT" ) - { - if( bFromCache ) - out.m_fLastBeat = StringToFloat( sParams[1] ); - } - else if( sValueName=="SONGFILENAME" ) - { - if( bFromCache ) - out.m_sSongFileName = sParams[1]; - } - else if( sValueName=="HASMUSIC" ) - { - if( bFromCache ) - out.m_bHasMusic = StringToInt( sParams[1] ) != 0; - } - else if( sValueName=="HASBANNER" ) - { - if( bFromCache ) - out.m_bHasBanner = StringToInt( sParams[1] ) != 0; + ; } else if( sValueName=="SAMPLESTART" ) @@ -1108,9 +1090,10 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache ) if( bFromCache ) break; + float lastBeat = song.m_SongTiming.GetBeatFromElapsedTime(song.lastSecond); /* If BGChanges already exist after the last beat, don't add the * background in the middle. */ - if( !bg.empty() && bg.back().m_fStartBeat-0.0001f >= song.m_fLastBeat ) + if( !bg.empty() && bg.back().m_fStartBeat-0.0001f >= lastBeat ) break; // If the last BGA is already the song BGA, don't add a duplicate. @@ -1120,7 +1103,8 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache ) if( !IsAFile( song.GetBackgroundPath() ) ) break; - bg.push_back( BackgroundChange(song.m_fLastBeat,song.m_sBackgroundFile) ); + + bg.push_back( BackgroundChange(lastBeat,song.m_sBackgroundFile) ); } while(0); } song.TidyUpData( bFromCache ); diff --git a/src/NotesLoaderSMA.cpp b/src/NotesLoaderSMA.cpp index 648d54dcca..05db8d42b0 100644 --- a/src/NotesLoaderSMA.cpp +++ b/src/NotesLoaderSMA.cpp @@ -225,30 +225,16 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach } else if( sValueName=="LASTBEATHINT" ) - out.m_fSpecifiedLastBeat = StringToFloat( sParams[1] ); - + { + // can't identify at this position: ignore. + } else if( sValueName=="MUSICBYTES" ) ; /* ignore */ - /* We calculate these. Some SMs in circulation have bogus values for - * these, so make sure we always calculate it ourself. */ - else if( sValueName=="FIRSTBEAT" ) - { - ; - } - else if( sValueName=="LASTBEAT" ) - { - ; - } - else if( sValueName=="SONGFILENAME" ) - { - ; - } - else if( sValueName=="HASMUSIC" ) - { - ; - } - else if( sValueName=="HASBANNER" ) + // Cache tags: ignore. + else if (sValueName=="FIRSTBEAT" || sValueName=="LASTBEAT" || + sValueName=="SONGFILENAME" || sValueName=="HASMUSIC" || + sValueName=="HASBANNER" ) { ; } diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index fe02b9181b..d2d92daf51 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -265,7 +265,12 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach else if( sValueName=="LASTBEATHINT" ) { - out.m_fSpecifiedLastBeat = StringToFloat( sParams[1] ); + // unable to parse due to tag position. Ignore. + } + + else if (sValueName == "LASTSECONDHINT") + { + out.specifiedLastSecond = StringToFloat(sParams[1]); } else if( sValueName=="MUSICBYTES" ) @@ -395,16 +400,20 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach /* The following are cache tags. Never fill their values * directly: only from the cached version. */ - else if( sValueName=="FIRSTBEAT" ) + else if( sValueName=="FIRSTBEAT" || sValueName=="LASTBEAT" ) + { + // no longer used. + } + else if (sValueName=="FIRSTSECOND") { if( bFromCache ) - out.m_fFirstBeat = StringToFloat( sParams[1] ); + out.firstSecond = StringToFloat( sParams[1] ); } else if( sValueName=="LASTBEAT" ) { if( bFromCache ) - out.m_fLastBeat = StringToFloat( sParams[1] ); + out.lastSecond = StringToFloat( sParams[1] ); } else if( sValueName=="SONGFILENAME" ) diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index e5ad6338d9..f0df061323 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -147,8 +147,8 @@ bool NotesWriterJson::WriteSong( const RString &sFile, const Song &out, bool bWr else root["Selectable"] = "YES"; - root["FirstBeat"] = out.m_fFirstBeat; - root["LastBeat"] = out.m_fLastBeat; + root["FirstBeat"] = out.m_SongTiming.GetBeatFromElapsedTime(out.firstSecond); + root["LastBeat"] = out.m_SongTiming.GetBeatFromElapsedTime(out.lastSecond); root["SongFileName"] = out.m_sSongFileName; root["HasMusic"] = out.m_bHasMusic; root["HasBanner"] = out.m_bHasBanner; diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index 6b9f89c1fe..06934bb06e 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -66,8 +66,8 @@ static void WriteGlobalTags( RageFile &f, Song &out ) f.PutLine( ssprintf( "#OFFSET:%.3f;", out.m_SongTiming.m_fBeat0OffsetInSeconds ) ); f.PutLine( ssprintf( "#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds ) ); f.PutLine( ssprintf( "#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds ) ); - if( out.m_fSpecifiedLastBeat > 0 ) - f.PutLine( ssprintf("#LASTBEATHINT:%.3f;", out.m_fSpecifiedLastBeat) ); + if( out.specifiedLastSecond > 0 ) + f.PutLine( ssprintf("#LASTBEATHINT:%.3f;", out.m_SongTiming.GetBeatFromElapsedTime(out.specifiedLastSecond)) ); f.Write( "#SELECTABLE:" ); switch(out.m_SelectionDisplay) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 528f438c66..261cf73c05 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -203,8 +203,6 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) f.PutLine( ssprintf( "#OFFSET:%.6f;", out.m_SongTiming.m_fBeat0OffsetInSeconds ) ); f.PutLine( ssprintf( "#SAMPLESTART:%.6f;", out.m_fMusicSampleStartSeconds ) ); f.PutLine( ssprintf( "#SAMPLELENGTH:%.6f;", out.m_fMusicSampleLengthSeconds ) ); - if( out.m_fSpecifiedLastBeat > 0 ) - f.PutLine( ssprintf("#LASTBEATHINT:%.6f;", out.m_fSpecifiedLastBeat) ); f.Write( "#SELECTABLE:" ); switch(out.m_SelectionDisplay) @@ -234,6 +232,9 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) WriteTimingTags( f, out.m_SongTiming, true ); + if( out.specifiedLastSecond > 0 ) + f.PutLine( ssprintf("#LASTSECONDHINT:%.6f;", out.specifiedLastSecond) ); + FOREACH_BackgroundLayer( b ) { if( b==0 ) @@ -367,8 +368,8 @@ bool NotesWriterSSC::Write( RString sPath, const Song &out, const vector if( bSavingCache ) { f.PutLine( ssprintf( "// cache tags:" ) ); - f.PutLine( ssprintf( "#FIRSTBEAT:%.6f;", out.m_fFirstBeat ) ); - f.PutLine( ssprintf( "#LASTBEAT:%.6f;", out.m_fLastBeat ) ); + f.PutLine( ssprintf( "#FIRSTSECOND:%.6f;", out.firstSecond ) ); + f.PutLine( ssprintf( "#LASTSECOND:%.6f;", out.lastSecond ) ); f.PutLine( ssprintf( "#SONGFILENAME:%s;", out.m_sSongFileName.c_str() ) ); f.PutLine( ssprintf( "#HASMUSIC:%i;", out.m_bHasMusic ) ); f.PutLine( ssprintf( "#HASBANNER:%i;", out.m_bHasBanner ) ); diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 55660d2c05..c14cb5c3b9 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -618,7 +618,7 @@ static MenuDef g_SongInformation( MenuRowDef( ScreenEdit::main_title_transliteration, "Main title transliteration", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::sub_title_transliteration, "Sub title transliteration", true, EditMode_Practice, true, true, 0, NULL ), MenuRowDef( ScreenEdit::artist_transliteration, "Artist transliteration", true, EditMode_Practice, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::last_beat_hint, "Last beat hint", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::last_second_hint, "Last second hint", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::preview_start, "Preview Start", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::preview_length, "Preview Length", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::display_bpm, "Display BPM", true, EditMode_Full, true, true, 0, "Actual", "Specified", "Random" ), @@ -2127,7 +2127,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if (index >= 0) { - const RString sDuration = ssprintf( "%.5f", attacks[index].fSecsRemaining ); + const RString sDuration = ssprintf( "%.6f", attacks[index].fSecsRemaining ); g_InsertCourseAttack.rows[remove].bEnabled = true; if( g_InsertCourseAttack.rows[duration].choices.size() == 9 ) @@ -2158,7 +2158,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) if( iAttack >= 0 ) { - const RString sDuration = ssprintf( "%.5f", ce.attacks[iAttack].fSecsRemaining ); + const RString sDuration = ssprintf( "%.6f", ce.attacks[iAttack].fSecsRemaining ); g_InsertCourseAttack.rows[remove].bEnabled = true; if( g_InsertCourseAttack.rows[duration].choices.size() == 9 ) @@ -3426,13 +3426,19 @@ static void ChangeArtistTranslit( const RString &sNew ) static void ChangeBeat0Offset( const RString &sNew ) { - TimingData &timing = GAMESTATE->m_bIsUsingStepTiming ? GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : GAMESTATE->m_pCurSong->m_SongTiming; + TimingData &timing = (GAMESTATE->m_bIsUsingStepTiming ? + GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : + GAMESTATE->m_pCurSong->m_SongTiming); timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); } -static void ChangeLastBeatHint( const RString &sNew ) +static void ChangeLastSecondHint( const RString &sNew ) { - GAMESTATE->m_pCurSong->m_fSpecifiedLastBeat = StringToFloat( sNew ); + Song &s = *GAMESTATE->m_pCurSong; + TimingData &timing = (GAMESTATE->m_bIsUsingStepTiming ? + GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : + s.m_SongTiming); + s.specifiedLastSecond = StringToFloat(sNew); } static void ChangePreviewStart( const RString &sNew ) @@ -3507,23 +3513,23 @@ void ScreenEdit::DisplayTimingMenu() TimingData &pTime = GetAppropriateTiming(); bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat ).GetBeat() == 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 ) ) ) ; - g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetDelayAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.6f", pTime.m_fBeat0OffsetInSeconds) ); + g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetBPMAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetStopAtBeat( fBeat ) ) ) ; + g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetDelayAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature].SetOneUnthemedChoice( ssprintf("%d / %d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ), pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); 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( bHasSpeedOnThisRow ? ssprintf("%.5f", pTime.GetSpeedPercentAtBeat( fBeat ) ) : "---" ); - g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.5f", pTime.GetSpeedWaitAtBeat( fBeat ) ) : "---" ); + g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetWarpAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[speed_percent].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.6f", pTime.GetSpeedPercentAtBeat( fBeat ) ) : "---" ); + g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.6f", pTime.GetSpeedWaitAtBeat( fBeat ) ) : "---" ); RString starting = ( pTime.GetSpeedModeAtBeat( fBeat ) == 1 ? "Seconds" : "Beats" ); g_TimingDataInformation.rows[speed_mode].SetOneUnthemedChoice( starting.c_str() ); - g_TimingDataInformation.rows[scroll].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetScrollAtBeat( fBeat ) ) ); - g_TimingDataInformation.rows[fake].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetFakeAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[scroll].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetScrollAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[fake].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetFakeAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[tickcount].bEnabled = GAMESTATE->m_bIsUsingStepTiming; g_TimingDataInformation.rows[combo].bEnabled = GAMESTATE->m_bIsUsingStepTiming; @@ -3733,12 +3739,12 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_SongInformation.rows[main_title_transliteration].SetOneUnthemedChoice( pSong->m_sMainTitleTranslit ); g_SongInformation.rows[sub_title_transliteration].SetOneUnthemedChoice( pSong->m_sSubTitleTranslit ); g_SongInformation.rows[artist_transliteration].SetOneUnthemedChoice( pSong->m_sArtistTranslit ); - g_SongInformation.rows[last_beat_hint].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedLastBeat) ); - g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds) ); - g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds) ); + g_SongInformation.rows[last_second_hint].SetOneUnthemedChoice( ssprintf("%.6f", pSong->specifiedLastSecond) ); + g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.6f", pSong->m_fMusicSampleStartSeconds) ); + g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.6f", pSong->m_fMusicSampleLengthSeconds) ); g_SongInformation.rows[display_bpm].iDefaultChoice = pSong->m_DisplayBPMType; - g_SongInformation.rows[min_bpm].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedBPMMin) ); - g_SongInformation.rows[max_bpm].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedBPMMax) ); + g_SongInformation.rows[min_bpm].SetOneUnthemedChoice( ssprintf("%.6f", pSong->m_fSpecifiedBPMMin) ); + g_SongInformation.rows[max_bpm].SetOneUnthemedChoice( ssprintf("%.6f", pSong->m_fSpecifiedBPMMax) ); EditMiniMenu( &g_SongInformation, SM_BackFromSongInformation ); } @@ -4206,7 +4212,7 @@ static LocalizedString ENTER_CREDIT ("ScreenEdit","Enter a new credit."); static LocalizedString ENTER_MAIN_TITLE_TRANSLIT ("ScreenEdit","Enter a new main title transliteration."); static LocalizedString ENTER_SUB_TITLE_TRANSLIT ("ScreenEdit","Enter a new sub title transliteration."); static LocalizedString ENTER_ARTIST_TRANSLIT ("ScreenEdit","Enter a new artist transliteration."); -static LocalizedString ENTER_LAST_BEAT_HINT ("ScreenEdit","Enter a new last beat hint."); +static LocalizedString ENTER_LAST_SECOND_HINT ("ScreenEdit","Enter a new last second hint."); static LocalizedString ENTER_PREVIEW_START ("ScreenEdit","Enter a new preview start."); static LocalizedString ENTER_PREVIEW_LENGTH ("ScreenEdit","Enter a new preview length."); static LocalizedString ENTER_MIN_BPM ("ScreenEdit","Enter a new min BPM."); @@ -4242,29 +4248,29 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec case artist_transliteration: ScreenTextEntry::TextEntry( SM_None, ENTER_ARTIST_TRANSLIT, pSong->m_sArtistTranslit, 100, NULL, ChangeArtistTranslit, NULL ); break; - case last_beat_hint: - ScreenTextEntry::TextEntry( SM_None, ENTER_LAST_BEAT_HINT, - ssprintf("%.5f", pSong->m_fSpecifiedLastBeat), 20, - ScreenTextEntry::FloatValidate, ChangeLastBeatHint, NULL ); + case last_second_hint: + ScreenTextEntry::TextEntry( SM_None, ENTER_LAST_SECOND_HINT, + ssprintf("%.6f", pSong->specifiedLastSecond), 20, + ScreenTextEntry::FloatValidate, ChangeLastSecondHint, NULL ); break; case preview_start: ScreenTextEntry::TextEntry( SM_None, ENTER_PREVIEW_START, - ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds), 20, + ssprintf("%.6f", pSong->m_fMusicSampleStartSeconds), 20, ScreenTextEntry::FloatValidate, ChangePreviewStart, NULL ); break; case preview_length: ScreenTextEntry::TextEntry( SM_None, ENTER_PREVIEW_LENGTH, - ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds), 20, + ssprintf("%.6f", pSong->m_fMusicSampleLengthSeconds), 20, ScreenTextEntry::FloatValidate, ChangePreviewLength, NULL ); break; case min_bpm: ScreenTextEntry::TextEntry( SM_None, ENTER_MIN_BPM, - ssprintf("%.5f", pSong->m_fSpecifiedBPMMin), 20, + ssprintf("%.6f", pSong->m_fSpecifiedBPMMin), 20, ScreenTextEntry::FloatValidate, ChangeMinBPM, NULL ); break; case max_bpm: ScreenTextEntry::TextEntry( SM_None, ENTER_MAX_BPM, - ssprintf("%.5f", pSong->m_fSpecifiedBPMMax), 20, + ssprintf("%.6f", pSong->m_fSpecifiedBPMMax), 20, ScreenTextEntry::FloatValidate, ChangeMaxBPM, NULL ); break; }; @@ -4293,7 +4299,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice DEFAULT_FAIL( c ); case beat_0_offset: ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET, - ssprintf("%.5f", GetAppropriateTiming().m_fBeat0OffsetInSeconds), 20, + ssprintf("%.6f", GetAppropriateTiming().m_fBeat0OffsetInSeconds), 20, ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL ); break; case bpm: @@ -4359,7 +4365,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromWarpChange, ENTER_WARP_VALUE, - ssprintf( "%.4f", GetAppropriateTiming().GetWarpAtBeat( GetBeat() ) ), + ssprintf( "%.6f", GetAppropriateTiming().GetWarpAtBeat( GetBeat() ) ), 10 ); break; @@ -4367,7 +4373,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromSpeedPercentChange, ENTER_SPEED_PERCENT_VALUE, - ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetRatio() ), + ssprintf( "%.6f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetRatio() ), 10 ); break; @@ -4375,7 +4381,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromScrollChange, ENTER_SCROLL_VALUE, - ssprintf( "%.5f", GetAppropriateTiming().GetScrollSegmentAtBeat( GetBeat() ).GetRatio() ), + ssprintf( "%.6f", GetAppropriateTiming().GetScrollSegmentAtBeat( GetBeat() ).GetRatio() ), 10 ); break; @@ -4383,7 +4389,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromSpeedWaitChange, ENTER_SPEED_WAIT_VALUE, - ssprintf( "%.5f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetLength() ), + ssprintf( "%.6f", GetAppropriateTiming().GetSpeedSegmentAtBeat( GetBeat() ).GetLength() ), 10 ); break; @@ -4403,7 +4409,7 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice ScreenTextEntry::TextEntry( SM_BackFromFakeChange, ENTER_FAKE_VALUE, - ssprintf("%.5f", GetAppropriateTiming().GetFakeAtBeat( GetBeat() ) ), + ssprintf("%.6f", GetAppropriateTiming().GetFakeAtBeat( GetBeat() ) ), 10 ); break; @@ -4701,14 +4707,15 @@ float ScreenEdit::GetMaximumBeatForNewNote() const case EditMode_CourseMods: case EditMode_Home: { - float fEndBeat = GAMESTATE->m_pCurSong->m_fLastBeat; + Song &s = *GAMESTATE->m_pCurSong; + TimingData &timing = s.m_SongTiming; + float fEndBeat = timing.GetBeatFromElapsedTime(s.lastSecond); /* Round up to the next measure end. Some songs end on weird beats * mid-measure, and it's odd to have movement capped to these weird * beats. */ - TimingData &songTiming = GAMESTATE->m_pCurSong->m_SongTiming; float playerBeat = GetAppropriatePosition().m_fSongBeat; - int beatsPerMeasure = songTiming.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum(); + int beatsPerMeasure = timing.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum(); fEndBeat += beatsPerMeasure; fEndBeat = ftruncf( fEndBeat, (float)beatsPerMeasure ); @@ -4723,7 +4730,7 @@ float ScreenEdit::GetMaximumBeatForMoving() const { float fEndBeat = GetMaximumBeatForNewNote(); - /* Jump to GetLastBeat even if it's past m_pCurSong->m_fLastBeat + /* Jump to GetLastBeat even if it's past the song's last beat * so that users can delete garbage steps past then end that they have * have inserted in a text editor. Once they delete all steps on * GetLastBeat() and move off of that beat, they won't be able to return. */ diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 255cf2b425..e75a4a854f 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -529,7 +529,7 @@ public: main_title_transliteration, sub_title_transliteration, artist_transliteration, - last_beat_hint, + last_second_hint, preview_start, preview_length, display_bpm, diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 475ca16250..5379530502 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1329,8 +1329,7 @@ void ScreenGameplay::StartPlayingSong( float fMinTimeToNotes, float fMinTimeToMu p.StopMode = RageSoundParams::M_CONTINUE; { - const float fFirstBeat = GAMESTATE->m_pCurSong->m_fFirstBeat; - const float fFirstSecond = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( fFirstBeat ); + const float fFirstSecond = GAMESTATE->m_pCurSong->firstSecond; float fStartDelay = fMinTimeToNotes - fFirstSecond; fStartDelay = max( fStartDelay, fMinTimeToMusic ); p.m_StartSecond = -fStartDelay; @@ -1412,8 +1411,9 @@ void ScreenGameplay::PlayAnnouncer( RString type, float fSeconds ) /* Don't play before the first beat, or after we're finished. */ if( m_DancingState != STATE_DANCING ) return; - if( GAMESTATE->m_pCurSong == NULL || // this will be true on ScreenDemonstration sometimes - GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fFirstBeat ) + if(GAMESTATE->m_pCurSong == NULL || // this will be true on ScreenDemonstration sometimes + GAMESTATE->m_Position.m_fSongBeat < + GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime(GAMESTATE->m_pCurSong->firstSecond) ) return; if( m_fTimeSinceLastDancingComment < fSeconds ) @@ -1488,7 +1488,7 @@ bool ScreenGameplay::AllAreFailing() void ScreenGameplay::GetMusicEndTiming( float &fSecondsToStartFadingOutMusic, float &fSecondsToStartTransitioningOut ) { - float fLastStepSeconds = GAMESTATE->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); + float fLastStepSeconds = GAMESTATE->m_pCurSong->lastSecond; fLastStepSeconds += Player::GetMaxStepDistanceSeconds(); float fTransitionLength; @@ -1697,7 +1697,11 @@ void ScreenGameplay::Update( float fDeltaTime ) // update fGameplaySeconds STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime; float curBeat = GAMESTATE->m_Position.m_fSongBeat; - if( curBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat && curBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) + Song &s = *GAMESTATE->m_pCurSong; + TimingData &timing = s.m_SongTiming; + + + if( curBeat >= timing.GetBeatFromElapsedTime(s.firstSecond) && curBeat < timing.GetBeatFromElapsedTime(s.lastSecond) ) { STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime; @@ -1978,7 +1982,8 @@ void ScreenGameplay::UpdateLights() } // Before the first beat of the song, all cabinet lights solid on (except for menu buttons). - bool bOverrideCabinetBlink = (GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->m_fFirstBeat); + Song &s = *GAMESTATE->m_pCurSong; + bool bOverrideCabinetBlink = (GAMESTATE->m_Position.m_fSongBeat < s.m_SongTiming.GetBeatFromElapsedTime(s.firstSecond)); FOREACH_CabinetLight( cl ) bBlinkCabinetLight[cl] |= bOverrideCabinetBlink; diff --git a/src/Song.cpp b/src/Song.cpp index 750605658e..5ac5a64554 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 185; +const int FILE_CACHE_VERSION = 186; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; @@ -511,7 +511,8 @@ void Song::TidyUpData( bool bFromCache ) if( m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds ) { - int iBeat = lrintf( m_fLastBeat/2 ); + // Attempt to get a reasonable default. + int iBeat = lrintf(this->m_SongTiming.GetBeatFromElapsedTime(this->lastSecond)/2); iBeat -= iBeat%4; m_fMusicSampleStartSeconds = timing.GetElapsedTimeFromBeat( (float)iBeat ); } @@ -800,7 +801,7 @@ void Song::TranslateTitles() void Song::ReCalculateRadarValuesAndLastBeat( bool bFromCache ) { - if( bFromCache && m_fFirstBeat >= 0 && m_fLastBeat > 0 ) + if( bFromCache && this->firstSecond >= 0 && this->lastSecond > 0 ) { // this is loaded from cache, then we just have to calculate the radar values. for( unsigned i=0; ispecifiedLastSecond; // Make sure we're at least as long as the specified amount. for( unsigned i=0; iCalculateRadarValues( m_fMusicLengthSeconds ); - // calculate lastBeat + // calculate lastSecond // If it's autogen, then first/last beat will come from the parent. if( pSteps->IsAutogen() ) @@ -842,12 +843,14 @@ void Song::ReCalculateRadarValuesAndLastBeat( bool bFromCache ) if( tempNoteData.GetLastRow() == 0 ) continue; - fFirstBeat = min( fFirstBeat, m_SongTiming.GetBeatFromElapsedTime(pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetFirstBeat())) ); - fLastBeat = max( fLastBeat, m_SongTiming.GetBeatFromElapsedTime(pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetLastBeat())) ); + localFirst = min(localFirst, + pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetFirstBeat())); + localLast = max(localLast, + pSteps->m_Timing.GetElapsedTimeFromBeat(tempNoteData.GetLastBeat())); } - m_fFirstBeat = fFirstBeat; - m_fLastBeat = fLastBeat; + this->firstSecond = localFirst; + this->lastSecond = localLast; } // Return whether the song is playable in the given style. @@ -1461,8 +1464,7 @@ bool Song::HasSignificantBpmChangesOrStops() const float Song::GetStepsSeconds() const { - const TimingData &timing = this->m_SongTiming; - return timing.GetElapsedTimeFromBeat( m_fLastBeat ) - timing.GetElapsedTimeFromBeat( m_fFirstBeat ); + return this->lastSecond - this->firstSecond; } bool Song::IsLong() const @@ -1579,8 +1581,26 @@ public: } static int GetStepsSeconds( T* p, lua_State *L ) { lua_pushnumber(L, p->GetStepsSeconds()); return 1; } static int NormallyDisplayed( T* p, lua_State *L ){ lua_pushboolean(L, p->NormallyDisplayed()); return 1; } - static int GetFirstBeat( T* p, lua_State *L ) { lua_pushnumber(L, p->m_fFirstBeat); return 1; } - static int GetLastBeat( T* p, lua_State *L ) { lua_pushnumber(L, p->m_fLastBeat); return 1; } + static int GetFirstSecond(T* p, lua_State *L) + { + lua_pushnumber(L, p->firstSecond); + return 1; + } + static int GetLastSecond(T* p, lua_State *L) + { + lua_pushnumber(L, p->lastSecond); + return 1; + } + static int GetFirstBeat( T* p, lua_State *L ) + { + lua_pushnumber(L, p->m_SongTiming.GetBeatFromElapsedTime(p->firstSecond)); + return 1; + } + static int GetLastBeat( T* p, lua_State *L ) + { + lua_pushnumber(L, p->m_SongTiming.GetBeatFromElapsedTime(p->lastSecond)); + return 1; + } static int HasAttacks( T* p, lua_State *L ) { lua_pushboolean(L, p->HasAttacks()); return 1; } static int GetDisplayBpms( T* p, lua_State *L ) { @@ -1657,7 +1677,9 @@ public: ADD_METHOD( GetStepsSeconds ); ADD_METHOD( NormallyDisplayed ); ADD_METHOD( GetFirstBeat ); + ADD_METHOD( GetFirstSecond ); ADD_METHOD( GetLastBeat ); + ADD_METHOD( GetLastSecond ); ADD_METHOD( HasAttacks ); ADD_METHOD( GetDisplayBpms ); ADD_METHOD( IsDisplayBpmSecret ); diff --git a/src/Song.h b/src/Song.h index 95dd3b1a6e..d661347db1 100644 --- a/src/Song.h +++ b/src/Song.h @@ -20,7 +20,7 @@ void FixupPath( RString &path, const RString &sSongPath ); RString GetSongAssetPath( RString sPath, const RString &sSongPath ); /** @brief The version of the .ssc file format. */ -const static float STEPFILE_VERSION_NUMBER = 0.72f; +const static float STEPFILE_VERSION_NUMBER = 0.73f; /** @brief How many edits for this song can each profile have? */ const int MAX_EDITS_PER_SONG_PER_PROFILE = 15; From 6fc669127bc4cd8f052d67c005d932b30944e374 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 01:16:08 -0400 Subject: [PATCH 07/21] No longer used. --- src/ScreenEdit.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index c14cb5c3b9..6d6b21f4e5 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3435,9 +3435,6 @@ static void ChangeBeat0Offset( const RString &sNew ) static void ChangeLastSecondHint( const RString &sNew ) { Song &s = *GAMESTATE->m_pCurSong; - TimingData &timing = (GAMESTATE->m_bIsUsingStepTiming ? - GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : - s.m_SongTiming); s.specifiedLastSecond = StringToFloat(sNew); } From 11923a80ba62d232be8d80a68a5b3cb43c0f5388 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 01:23:59 -0400 Subject: [PATCH 08/21] Allow setting last second at the current beat. Use the Area Menu for this one. --- Docs/Changelog_sm5.txt | 5 ++++- Themes/_fallback/Languages/en.ini | 1 + src/ScreenEdit.cpp | 10 +++++++++- src/ScreenEdit.h | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 51ae1cbde6..d2e2b127ef 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -5,7 +5,7 @@ from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ ================================================================================ -StepMania 5.0 Preview 2 | 201106?? +StepMania 5.0 Preview 2 | 201107?? -------------------------------------------------------------------------------- 2011/06/30 @@ -13,6 +13,9 @@ StepMania 5.0 Preview 2 | 201106?? * [NotesAll] Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the former BEAT equivalents. Split Timing has made this a necessity thanks to certain files that abuse Stops/Delays more than usual. [Wolfman2000] +* [ScreenEdit] Add a function in the Area Menu to designate the current beat + as the last second of the song. Please try to be smart and not use this too + early. [Wolfman2000] 2011/06/28 ---------- diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index e9f39cb930..adbb6deadc 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -838,6 +838,7 @@ Delete=Delete Delete beat and shift up=Delete beat and shift up Description=Description Designate as Music Preview=Designate as Music Preview +Designate last second at current beat=Designate last second at current beat Difficulty=Difficulty Display BPM=Display BPM DisplayAspectRatio=Aspect Ratio diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 6d6b21f4e5..4de9d3ede2 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -581,8 +581,9 @@ static MenuDef g_AreaMenu( EditMode_Full, true, true, 0, NULL ), MenuRowDef(ScreenEdit::convert_delay_to_beat, "Convert delay to beats", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef(ScreenEdit::last_second_at_beat, "Designate last second at current beat", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::undo, "Undo", true, EditMode_Practice, true, true, 0, NULL ), - MenuRowDef(ScreenEdit::clear_clipboard, "Clear clipboard", true, + MenuRowDef(ScreenEdit::clear_clipboard, "Clear clipboard", true, EditMode_Practice, true, true, 0, NULL ) ); @@ -4129,6 +4130,13 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns timing.InsertRows(GetRow(), BeatToNoteRow(pauseBeats)); break; } + case last_second_at_beat: + { + TimingData &timing = GetAppropriateTiming(); + Song &s = *GAMESTATE->m_pCurSong; + s.specifiedLastSecond = timing.GetElapsedTimeFromBeat(GetBeat()); + break; + } case undo: Undo(); break; diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index e75a4a854f..a2392a83e6 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -421,6 +421,7 @@ public: shift_pauses_backward, convert_pause_to_beat, convert_delay_to_beat, + last_second_at_beat, undo, clear_clipboard, NUM_AREA_MENU_CHOICES From 7627cbe5ac3f866cdd7de231bdd718d439735f01 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 01:30:14 -0400 Subject: [PATCH 09/21] Unused. --- src/Song.cpp | 3 --- src/Song.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/Song.cpp b/src/Song.cpp index 5ac5a64554..6c68a53f20 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -72,9 +72,6 @@ Song::Song() firstSecond = -1; lastSecond = -1; specifiedLastSecond = -1; - m_fFirstBeat = -1; - m_fLastBeat = -1; - m_fSpecifiedLastBeat = -1; m_SelectionDisplay = SHOW_ALWAYS; m_bEnabled = true; m_DisplayBPMType = DISPLAY_BPM_ACTUAL; diff --git a/src/Song.h b/src/Song.h index d661347db1..ff5e2196a2 100644 --- a/src/Song.h +++ b/src/Song.h @@ -235,9 +235,6 @@ public: float firstSecond; float lastSecond; float specifiedLastSecond; - float m_fFirstBeat; // beat of first note - float m_fLastBeat; // beat of last note - float m_fSpecifiedLastBeat; // specified last beat of the song float m_fMusicSampleStartSeconds; float m_fMusicSampleLengthSeconds; DisplayBPM m_DisplayBPMType; From 80d3618b8e733b1177373c3188f7f00c43d945c7 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 01:56:50 -0400 Subject: [PATCH 10/21] Prepare for function abstraction. --- src/Song.cpp | 28 ++++++++++++++++++++++++---- src/Song.h | 9 +++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Song.cpp b/src/Song.cpp index 6c68a53f20..992410adbe 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -100,6 +100,26 @@ void Song::DetachSteps() m_vpStepsByType[st].clear(); } +float Song::GetFirstSecond() const +{ + return this->firstSecond; +} + +float Song::GetFirstBeat() const +{ + return this->m_SongTiming.GetBeatFromElapsedTime(this->firstSecond); +} + +float Song::GetLastSecond() const +{ + return this->lastSecond; +} + +float Song::GetLastBeat() const +{ + return this->m_SongTiming.GetBeatFromElapsedTime(this->lastSecond); +} + // Reset to an empty song. void Song::Reset() { @@ -1580,22 +1600,22 @@ public: static int NormallyDisplayed( T* p, lua_State *L ){ lua_pushboolean(L, p->NormallyDisplayed()); return 1; } static int GetFirstSecond(T* p, lua_State *L) { - lua_pushnumber(L, p->firstSecond); + lua_pushnumber(L, p->GetFirstSecond()); return 1; } static int GetLastSecond(T* p, lua_State *L) { - lua_pushnumber(L, p->lastSecond); + lua_pushnumber(L, p->GetLastSecond()); return 1; } static int GetFirstBeat( T* p, lua_State *L ) { - lua_pushnumber(L, p->m_SongTiming.GetBeatFromElapsedTime(p->firstSecond)); + lua_pushnumber(L, p->GetFirstBeat()); return 1; } static int GetLastBeat( T* p, lua_State *L ) { - lua_pushnumber(L, p->m_SongTiming.GetBeatFromElapsedTime(p->lastSecond)); + lua_pushnumber(L, p->GetLastBeat()); return 1; } static int HasAttacks( T* p, lua_State *L ) { lua_pushboolean(L, p->HasAttacks()); return 1; } diff --git a/src/Song.h b/src/Song.h index ff5e2196a2..b64d9daf9c 100644 --- a/src/Song.h +++ b/src/Song.h @@ -231,9 +231,13 @@ public: RString m_sMusicFile; RString m_sInstrumentTrackFile[NUM_InstrumentTrack]; + /** @brief The length of the music file. */ float m_fMusicLengthSeconds; + /** @brief The first second that a note is hit. */ float firstSecond; + /** @brief The last second that a note is hit. */ float lastSecond; + /** @brief The last second of the song for playing purposes. */ float specifiedLastSecond; float m_fMusicSampleStartSeconds; float m_fMusicSampleLengthSeconds; @@ -289,6 +293,11 @@ public: /** @brief The Song's TimingData. */ TimingData m_SongTiming; + + float GetFirstBeat() const; + float GetFirstSecond() const; + float GetLastBeat() const; + float GetLastSecond() const; typedef vector VBackgroundChange; private: From 5940bdeddb7e5853981be77b8c7b46623dafc600 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 02:10:58 -0400 Subject: [PATCH 11/21] More abstraction. --- src/Background.cpp | 7 +++---- src/DancingCharacters.cpp | 6 ++---- src/GameState.cpp | 2 +- src/Inventory.cpp | 2 +- src/LyricDisplay.cpp | 2 +- src/MeterDisplay.cpp | 4 ++-- src/NotesLoaderSM.cpp | 2 +- src/NotesLoaderSSC.cpp | 2 +- src/NotesWriterJson.cpp | 4 ++-- src/NotesWriterSSC.cpp | 4 ++-- src/ScreenEdit.cpp | 4 ++-- src/ScreenGameplay.cpp | 13 +++++-------- src/Song.cpp | 6 +++--- 13 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/Background.cpp b/src/Background.cpp index b86a86027e..d5b14b308b 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -577,9 +577,8 @@ void BackgroundImpl::LoadFromSong( const Song* pSong ) else // pSong doesn't have an animation plan { Layer &layer = m_Layer[0]; - const TimingData &t = pSong->m_SongTiming; - float firstBeat = t.GetBeatFromElapsedTime(pSong->firstSecond); - float lastBeat = t.GetBeatFromElapsedTime(pSong->lastSecond); + float firstBeat = pSong->GetFirstBeat(); + float lastBeat = pSong->GetLastBeat(); LoadFromRandom( firstBeat, lastBeat, BackgroundChange() ); @@ -645,7 +644,7 @@ void BackgroundImpl::LoadFromSong( const Song* pSong ) continue; float fStartBeat = change.m_fStartBeat; - float fEndBeat = pSong->m_SongTiming.GetBeatFromElapsedTime(pSong->lastSecond); + float fEndBeat = pSong->GetLastBeat(); if( i+1 < mainlayer.m_aBGChanges.size() ) fEndBeat = mainlayer.m_aBGChanges[i+1].m_fStartBeat; diff --git a/src/DancingCharacters.cpp b/src/DancingCharacters.cpp index d9382c42d1..403277580c 100644 --- a/src/DancingCharacters.cpp +++ b/src/DancingCharacters.cpp @@ -166,8 +166,7 @@ void DancingCharacters::LoadNextSong() m_fThisCameraEndBeat = 0; ASSERT( GAMESTATE->m_pCurSong ); - Song &s = *GAMESTATE->m_pCurSong; - m_fThisCameraEndBeat = s.m_SongTiming.GetBeatFromElapsedTime(s.firstSecond); + m_fThisCameraEndBeat = GAMESTATE->m_pCurSong->GetFirstBeat(); FOREACH_PlayerNumber( p ) if( GAMESTATE->IsPlayerEnabled(p) ) @@ -213,8 +212,7 @@ void DancingCharacters::Update( float fDelta ) bWasGameplayStarting = bGameplayStarting; static float fLastBeat = GAMESTATE->m_Position.m_fSongBeat; - Song &s = *GAMESTATE->m_pCurSong; - float firstBeat = s.m_SongTiming.GetBeatFromElapsedTime(s.firstSecond); + float firstBeat = GAMESTATE->m_pCurSong->GetFirstBeat(); float fThisBeat = GAMESTATE->m_Position.m_fSongBeat; if( fLastBeat < firstBeat && fThisBeat >= firstBeat ) { diff --git a/src/GameState.cpp b/src/GameState.cpp index 1ba34d53f9..bf9a841bd8 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -992,7 +992,7 @@ float GameState::GetSongPercent( float beat ) const { // 0 = first step; 1 = last step float curTime = this->m_pCurSong->m_SongTiming.GetElapsedTimeFromBeat(beat); - return (curTime - m_pCurSong->firstSecond) / m_pCurSong->lastSecond; + return (curTime - m_pCurSong->GetFirstSecond()) / m_pCurSong->GetLastSecond(); } int GameState::GetNumStagesLeft( PlayerNumber pn ) const diff --git a/src/Inventory.cpp b/src/Inventory.cpp index 71a30a9ba9..b45b779449 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -122,7 +122,7 @@ void Inventory::Update( float fDelta ) Song &song = *GAMESTATE->m_pCurSong; // use items if this player is CPU-controlled if( m_pPlayerState->m_PlayerController != PC_HUMAN && - GAMESTATE->m_Position.m_fSongBeat < song.m_SongTiming.GetBeatFromElapsedTime(song.lastSecond) ) + GAMESTATE->m_Position.m_fSongBeat < song.GetLastBeat() ) { // every 1 seconds, try to use an item int iLastSecond = (int)(RageTimer::GetTimeSinceStartFast() - fDelta); diff --git a/src/LyricDisplay.cpp b/src/LyricDisplay.cpp index a6bdfea918..b896814e1d 100644 --- a/src/LyricDisplay.cpp +++ b/src/LyricDisplay.cpp @@ -59,7 +59,7 @@ void LyricDisplay::Update( float fDeltaTime ) if( m_iCurLyricNumber+1 < GAMESTATE->m_pCurSong->m_LyricSegments.size() ) fEndTime = pSong->m_LyricSegments[m_iCurLyricNumber+1].m_fStartTime; else - fEndTime = pSong->lastSecond; + fEndTime = pSong->GetLastSecond(); const float fDistance = fEndTime - pSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime; const float fTweenBufferTime = IN_LENGTH.GetValue() + OUT_LENGTH.GetValue(); diff --git a/src/MeterDisplay.cpp b/src/MeterDisplay.cpp index 5bc9da2e6a..cd8c2faebb 100644 --- a/src/MeterDisplay.cpp +++ b/src/MeterDisplay.cpp @@ -73,8 +73,8 @@ void SongMeterDisplay::Update( float fDeltaTime ) { if( GAMESTATE->m_pCurSong ) { - float fSongStartSeconds = GAMESTATE->m_pCurSong->firstSecond; - float fSongEndSeconds = GAMESTATE->m_pCurSong->lastSecond; + float fSongStartSeconds = GAMESTATE->m_pCurSong->GetFirstSecond(); + float fSongEndSeconds = GAMESTATE->m_pCurSong->GetLastSecond(); float fPercentPositionSong = SCALE( GAMESTATE->m_Position.m_fMusicSeconds, fSongStartSeconds, fSongEndSeconds, 0.0f, 1.0f ); CLAMP( fPercentPositionSong, 0, 1 ); diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 82da1ffbbc..ffe564269c 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -1090,7 +1090,7 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache ) if( bFromCache ) break; - float lastBeat = song.m_SongTiming.GetBeatFromElapsedTime(song.lastSecond); + float lastBeat = song.GetLastBeat(); /* If BGChanges already exist after the last beat, don't add the * background in the middle. */ if( !bg.empty() && bg.back().m_fStartBeat-0.0001f >= lastBeat ) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index d2d92daf51..1f4314a31a 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -410,7 +410,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach out.firstSecond = StringToFloat( sParams[1] ); } - else if( sValueName=="LASTBEAT" ) + else if( sValueName=="LASTSECOND" ) { if( bFromCache ) out.lastSecond = StringToFloat( sParams[1] ); diff --git a/src/NotesWriterJson.cpp b/src/NotesWriterJson.cpp index f0df061323..8320c3d4b9 100644 --- a/src/NotesWriterJson.cpp +++ b/src/NotesWriterJson.cpp @@ -147,8 +147,8 @@ bool NotesWriterJson::WriteSong( const RString &sFile, const Song &out, bool bWr else root["Selectable"] = "YES"; - root["FirstBeat"] = out.m_SongTiming.GetBeatFromElapsedTime(out.firstSecond); - root["LastBeat"] = out.m_SongTiming.GetBeatFromElapsedTime(out.lastSecond); + root["FirstBeat"] = out.GetFirstBeat(); + root["LastBeat"] = out.GetLastBeat(); root["SongFileName"] = out.m_sSongFileName; root["HasMusic"] = out.m_bHasMusic; root["HasBanner"] = out.m_bHasBanner; diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 261cf73c05..364361dd74 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -368,8 +368,8 @@ bool NotesWriterSSC::Write( RString sPath, const Song &out, const vector if( bSavingCache ) { f.PutLine( ssprintf( "// cache tags:" ) ); - f.PutLine( ssprintf( "#FIRSTSECOND:%.6f;", out.firstSecond ) ); - f.PutLine( ssprintf( "#LASTSECOND:%.6f;", out.lastSecond ) ); + f.PutLine( ssprintf( "#FIRSTSECOND:%.6f;", out.GetFirstSecond() ) ); + f.PutLine( ssprintf( "#LASTSECOND:%.6f;", out.GetLastSecond() ) ); f.PutLine( ssprintf( "#SONGFILENAME:%s;", out.m_sSongFileName.c_str() ) ); f.PutLine( ssprintf( "#HASMUSIC:%i;", out.m_bHasMusic ) ); f.PutLine( ssprintf( "#HASBANNER:%i;", out.m_bHasBanner ) ); diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 4de9d3ede2..1ac2c39f78 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -4713,12 +4713,12 @@ float ScreenEdit::GetMaximumBeatForNewNote() const case EditMode_Home: { Song &s = *GAMESTATE->m_pCurSong; - TimingData &timing = s.m_SongTiming; - float fEndBeat = timing.GetBeatFromElapsedTime(s.lastSecond); + float fEndBeat = s.GetLastBeat(); /* Round up to the next measure end. Some songs end on weird beats * mid-measure, and it's odd to have movement capped to these weird * beats. */ + TimingData &timing = s.m_SongTiming; float playerBeat = GetAppropriatePosition().m_fSongBeat; int beatsPerMeasure = timing.GetTimeSignatureSegmentAtBeat( playerBeat ).GetNum(); fEndBeat += beatsPerMeasure; diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 5379530502..7cb93d1113 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1329,7 +1329,7 @@ void ScreenGameplay::StartPlayingSong( float fMinTimeToNotes, float fMinTimeToMu p.StopMode = RageSoundParams::M_CONTINUE; { - const float fFirstSecond = GAMESTATE->m_pCurSong->firstSecond; + const float fFirstSecond = GAMESTATE->m_pCurSong->GetFirstSecond(); float fStartDelay = fMinTimeToNotes - fFirstSecond; fStartDelay = max( fStartDelay, fMinTimeToMusic ); p.m_StartSecond = -fStartDelay; @@ -1412,8 +1412,7 @@ void ScreenGameplay::PlayAnnouncer( RString type, float fSeconds ) if( m_DancingState != STATE_DANCING ) return; if(GAMESTATE->m_pCurSong == NULL || // this will be true on ScreenDemonstration sometimes - GAMESTATE->m_Position.m_fSongBeat < - GAMESTATE->m_pCurSong->m_SongTiming.GetBeatFromElapsedTime(GAMESTATE->m_pCurSong->firstSecond) ) + GAMESTATE->m_Position.m_fSongBeat < GAMESTATE->m_pCurSong->GetFirstBeat()) return; if( m_fTimeSinceLastDancingComment < fSeconds ) @@ -1488,7 +1487,7 @@ bool ScreenGameplay::AllAreFailing() void ScreenGameplay::GetMusicEndTiming( float &fSecondsToStartFadingOutMusic, float &fSecondsToStartTransitioningOut ) { - float fLastStepSeconds = GAMESTATE->m_pCurSong->lastSecond; + float fLastStepSeconds = GAMESTATE->m_pCurSong->GetLastSecond(); fLastStepSeconds += Player::GetMaxStepDistanceSeconds(); float fTransitionLength; @@ -1698,10 +1697,8 @@ void ScreenGameplay::Update( float fDeltaTime ) STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime; float curBeat = GAMESTATE->m_Position.m_fSongBeat; Song &s = *GAMESTATE->m_pCurSong; - TimingData &timing = s.m_SongTiming; - - if( curBeat >= timing.GetBeatFromElapsedTime(s.firstSecond) && curBeat < timing.GetBeatFromElapsedTime(s.lastSecond) ) + if( curBeat >= s.GetFirstBeat() && curBeat < s.GetLastBeat() ) { STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime; @@ -1983,7 +1980,7 @@ void ScreenGameplay::UpdateLights() // Before the first beat of the song, all cabinet lights solid on (except for menu buttons). Song &s = *GAMESTATE->m_pCurSong; - bool bOverrideCabinetBlink = (GAMESTATE->m_Position.m_fSongBeat < s.m_SongTiming.GetBeatFromElapsedTime(s.firstSecond)); + bool bOverrideCabinetBlink = (GAMESTATE->m_Position.m_fSongBeat < s.GetFirstBeat()); FOREACH_CabinetLight( cl ) bBlinkCabinetLight[cl] |= bOverrideCabinetBlink; diff --git a/src/Song.cpp b/src/Song.cpp index 992410adbe..fefc77f0fa 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -529,7 +529,7 @@ void Song::TidyUpData( bool bFromCache ) if( m_fMusicSampleStartSeconds+m_fMusicSampleLengthSeconds > this->m_fMusicLengthSeconds ) { // Attempt to get a reasonable default. - int iBeat = lrintf(this->m_SongTiming.GetBeatFromElapsedTime(this->lastSecond)/2); + int iBeat = lrintf(this->m_SongTiming.GetBeatFromElapsedTime(this->GetLastSecond())/2); iBeat -= iBeat%4; m_fMusicSampleStartSeconds = timing.GetElapsedTimeFromBeat( (float)iBeat ); } @@ -818,7 +818,7 @@ void Song::TranslateTitles() void Song::ReCalculateRadarValuesAndLastBeat( bool bFromCache ) { - if( bFromCache && this->firstSecond >= 0 && this->lastSecond > 0 ) + if( bFromCache && this->GetFirstSecond() >= 0 && this->GetLastSecond() > 0 ) { // this is loaded from cache, then we just have to calculate the radar values. for( unsigned i=0; ilastSecond - this->firstSecond; + return this->GetLastSecond() - this->GetFirstSecond(); } bool Song::IsLong() const From df14721d0fcfae1e29c5398ba91cd89a81eef20e Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 02:11:32 -0400 Subject: [PATCH 12/21] Last update requires recache fix. Accidentally wasn't reading the right tag. --- src/Song.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Song.cpp b/src/Song.cpp index fefc77f0fa..f39b853b48 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 186; +const int FILE_CACHE_VERSION = 187; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; From 57e3c2fc80e9a1245a3a38b7972a43665d99acad Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 02:19:37 -0400 Subject: [PATCH 13/21] Use accessor functions instead of direct calls. --- src/NotesLoaderSSC.cpp | 6 +++--- src/NotesWriterSM.cpp | 5 +++-- src/NotesWriterSSC.cpp | 4 ++-- src/ScreenEdit.cpp | 8 ++++---- src/Song.cpp | 25 +++++++++++++++++++++++++ src/Song.h | 18 ++++++++++++------ 6 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 1f4314a31a..258d1ae5d7 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -270,7 +270,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach else if (sValueName == "LASTSECONDHINT") { - out.specifiedLastSecond = StringToFloat(sParams[1]); + out.SetSpecifiedLastSecond(StringToFloat(sParams[1])); } else if( sValueName=="MUSICBYTES" ) @@ -407,13 +407,13 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach else if (sValueName=="FIRSTSECOND") { if( bFromCache ) - out.firstSecond = StringToFloat( sParams[1] ); + out.SetFirstSecond(StringToFloat(sParams[1])); } else if( sValueName=="LASTSECOND" ) { if( bFromCache ) - out.lastSecond = StringToFloat( sParams[1] ); + out.SetLastSecond(StringToFloat(sParams[1])); } else if( sValueName=="SONGFILENAME" ) diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index 06934bb06e..48db17d8ff 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -66,8 +66,9 @@ static void WriteGlobalTags( RageFile &f, Song &out ) f.PutLine( ssprintf( "#OFFSET:%.3f;", out.m_SongTiming.m_fBeat0OffsetInSeconds ) ); f.PutLine( ssprintf( "#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds ) ); f.PutLine( ssprintf( "#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds ) ); - if( out.specifiedLastSecond > 0 ) - f.PutLine( ssprintf("#LASTBEATHINT:%.3f;", out.m_SongTiming.GetBeatFromElapsedTime(out.specifiedLastSecond)) ); + float specBeat = out.GetSpecifiedLastBeat(); + if( specBeat > 0 ) + f.PutLine( ssprintf("#LASTBEATHINT:%.3f;", specBeat) ); f.Write( "#SELECTABLE:" ); switch(out.m_SelectionDisplay) diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 364361dd74..bad8a1690e 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -232,8 +232,8 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) WriteTimingTags( f, out.m_SongTiming, true ); - if( out.specifiedLastSecond > 0 ) - f.PutLine( ssprintf("#LASTSECONDHINT:%.6f;", out.specifiedLastSecond) ); + if( out.GetSpecifiedLastSecond() > 0 ) + f.PutLine( ssprintf("#LASTSECONDHINT:%.6f;", out.GetSpecifiedLastSecond()) ); FOREACH_BackgroundLayer( b ) { diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 1ac2c39f78..08e53a6aea 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3436,7 +3436,7 @@ static void ChangeBeat0Offset( const RString &sNew ) static void ChangeLastSecondHint( const RString &sNew ) { Song &s = *GAMESTATE->m_pCurSong; - s.specifiedLastSecond = StringToFloat(sNew); + s.SetSpecifiedLastSecond(StringToFloat(sNew)); } static void ChangePreviewStart( const RString &sNew ) @@ -3737,7 +3737,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_SongInformation.rows[main_title_transliteration].SetOneUnthemedChoice( pSong->m_sMainTitleTranslit ); g_SongInformation.rows[sub_title_transliteration].SetOneUnthemedChoice( pSong->m_sSubTitleTranslit ); g_SongInformation.rows[artist_transliteration].SetOneUnthemedChoice( pSong->m_sArtistTranslit ); - g_SongInformation.rows[last_second_hint].SetOneUnthemedChoice( ssprintf("%.6f", pSong->specifiedLastSecond) ); + g_SongInformation.rows[last_second_hint].SetOneUnthemedChoice( ssprintf("%.6f", pSong->GetSpecifiedLastSecond()) ); g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.6f", pSong->m_fMusicSampleStartSeconds) ); g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.6f", pSong->m_fMusicSampleLengthSeconds) ); g_SongInformation.rows[display_bpm].iDefaultChoice = pSong->m_DisplayBPMType; @@ -4134,7 +4134,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns { TimingData &timing = GetAppropriateTiming(); Song &s = *GAMESTATE->m_pCurSong; - s.specifiedLastSecond = timing.GetElapsedTimeFromBeat(GetBeat()); + s.SetSpecifiedLastSecond(timing.GetElapsedTimeFromBeat(GetBeat())); break; } case undo: @@ -4255,7 +4255,7 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec break; case last_second_hint: ScreenTextEntry::TextEntry( SM_None, ENTER_LAST_SECOND_HINT, - ssprintf("%.6f", pSong->specifiedLastSecond), 20, + ssprintf("%.6f", pSong->GetSpecifiedLastSecond()), 20, ScreenTextEntry::FloatValidate, ChangeLastSecondHint, NULL ); break; case preview_start: diff --git a/src/Song.cpp b/src/Song.cpp index f39b853b48..87eaf91058 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -120,6 +120,31 @@ float Song::GetLastBeat() const return this->m_SongTiming.GetBeatFromElapsedTime(this->lastSecond); } +float Song::GetSpecifiedLastSecond() const +{ + return this->specifiedLastSecond; +} + +float Song::GetSpecifiedLastBeat() const +{ + return this->m_SongTiming.GetBeatFromElapsedTime(this->specifiedLastSecond); +} + +void Song::SetFirstSecond(const float f) +{ + this->firstSecond = f; +} + +void Song::SetLastSecond(const float f) +{ + this->lastSecond = f; +} + +void Song::SetSpecifiedLastSecond(const float f) +{ + this->specifiedLastSecond = f; +} + // Reset to an empty song. void Song::Reset() { diff --git a/src/Song.h b/src/Song.h index b64d9daf9c..279cb8e5b9 100644 --- a/src/Song.h +++ b/src/Song.h @@ -233,12 +233,6 @@ public: /** @brief The length of the music file. */ float m_fMusicLengthSeconds; - /** @brief The first second that a note is hit. */ - float firstSecond; - /** @brief The last second that a note is hit. */ - float lastSecond; - /** @brief The last second of the song for playing purposes. */ - float specifiedLastSecond; float m_fMusicSampleStartSeconds; float m_fMusicSampleLengthSeconds; DisplayBPM m_DisplayBPMType; @@ -298,9 +292,21 @@ public: float GetFirstSecond() const; float GetLastBeat() const; float GetLastSecond() const; + float GetSpecifiedLastBeat() const; + float GetSpecifiedLastSecond() const; + + void SetFirstSecond(const float f); + void SetLastSecond(const float f); + void SetSpecifiedLastSecond(const float f); typedef vector VBackgroundChange; private: + /** @brief The first second that a note is hit. */ + float firstSecond; + /** @brief The last second that a note is hit. */ + float lastSecond; + /** @brief The last second of the song for playing purposes. */ + float specifiedLastSecond; /** * @brief The background changes (sorted by layer) that are for this Song. * From 5c41a3990373311b8471e1c6aa2231d6f401be6b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 11:43:40 -0400 Subject: [PATCH 14/21] Simplify, fix timing bars. --- .../BGAnimations/ScreenGameplay decorations/default.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index 6fa5c4a506..4b548bafa8 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -19,8 +19,8 @@ local function CreateStops(Player) if song then local songLen = song:MusicLengthSeconds(); - local firstBeatSecs = timingData:GetElapsedTimeFromBeat(song:GetFirstBeat()); - local lastBeatSecs = timingData:GetElapsedTimeFromBeat(song:GetLastBeat()); + local firstBeatSecs = song:GetFirstSecond(); + local lastBeatSecs = song:GetLastSecond(); local bpms = timingData:GetBPMs(); From 08884a7321b1a67877dda44d354386799265bd2b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 12:30:54 -0400 Subject: [PATCH 15/21] Start showing Delays in the progress bar. I think this needs abstracting more before I continue with other segments. --- .../ScreenGameplay decorations/default.lua | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index 4b548bafa8..9eacd2a56c 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -3,6 +3,7 @@ local function CreateStops(Player) local bars = Def.ActorFrame{ }; local bpmFrame = Def.ActorFrame{ Name="BPMFrame"; }; local stopFrame = Def.ActorFrame{ Name="StopFrame"; }; + local delayFrame = Def.ActorFrame{ Name="DelayFrame"; }; local fFrameWidth = 380; local fFrameHeight = 8; @@ -25,6 +26,61 @@ local function CreateStops(Player) local bpms = timingData:GetBPMs(); local stops = timingData:GetStops(); + local delays = timingData:GetDelays(); + + for i=1,#delays do + local data = split("=",delays[i]); + local beat = data[1]; + local secs = data[2]; + local beatTime = timingData:GetElapsedTimeFromBeat(beat); + if beatTime < 0 then beatTime = 0; end; + + delayFrame[#delayFrame+1] = Def.ActorFrame { + Def.Quad { + InitCommand=function(self) + --self:diffuse(HSVA(192,1,0.8,0.8)); + self:shadowlength(0); + self:shadowcolor( color("#FFFF0077") ); + -- set width + self:zoomto( math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight ); + -- find location + self:x( ( scale(beatTime, firstBeatSecs,lastBeatSecs, -fFrameWidth/2,fFrameWidth/2) ) ); + end; + OnCommand=function(self) + self:diffuse(Color("Yellow")); + self:sleep(beatTime+1); + self:linear(2); + self:diffusealpha(0); + end; + }; + Def.Quad { + InitCommand=function(self) + --self:diffuse(HSVA(192,1,0.8,0.8)); + self:shadowlength(0); + self:shadowcolor( color("#FFFF0077") ); + -- set width + self:zoomto( math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight ); + -- find location + self:x( ( scale(beatTime, firstBeatSecs,lastBeatSecs, -fFrameWidth/2,fFrameWidth/2) ) ); + end; + OnCommand=function(self) + self:diffusealpha(1); + self:diffuseshift(); + self:effectcolor1(Color("Green")); + self:effectcolor2(Color("Red")); + self:effectclock('beat'); + self:effectperiod(1/8); + -- + self:diffusealpha(0); + self:sleep(beatTime+1); + self:diffusealpha(1); + self:linear(4); + self:diffusealpha(0); + end; + }; + }; + end; + for i=1,#stops do local data = split("=",stops[i]); local beat = data[1]; @@ -70,18 +126,16 @@ local function CreateStops(Player) -- self:diffusealpha(0); self:sleep(beatTime+1); - -- self:linear(1); self:diffusealpha(1); self:linear(4); self:diffusealpha(0); end; }; - --OnCommand=cmd(diffuse,Color("White");sleep,math.min(0.00001+(secs-5),0.00001);linear,1;diffuse,Color("Orange");sleep,4;linear,2;diffusealpha,0); - --OnCommand=cmd(diffuse,Color("White");linear,1;diffuse,Color("Orange");); }; end; end; bars[#bars+1] = stopFrame; + bars[#bars+1] = delayFrame; t[#t+1] = bars; end return t From 67039e8998fa8ea1b35bc1aaf9bc3ca9033f4de9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 12:51:03 -0400 Subject: [PATCH 16/21] Hooray lua! Functions in functions = yay. :D --- .../ScreenGameplay decorations/default.lua | 82 ++++--------------- 1 file changed, 17 insertions(+), 65 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index 9eacd2a56c..0e6d28e1f9 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -28,26 +28,21 @@ local function CreateStops(Player) local stops = timingData:GetStops(); local delays = timingData:GetDelays(); - for i=1,#delays do - local data = split("=",delays[i]); - local beat = data[1]; - local secs = data[2]; + local function CreateLine(beat, secs, firstShadow, firstDiffuse, secondShadow, firstEffect, secondEffect) local beatTime = timingData:GetElapsedTimeFromBeat(beat); if beatTime < 0 then beatTime = 0; end; - - delayFrame[#delayFrame+1] = Def.ActorFrame { + return Def.ActorFrame { Def.Quad { InitCommand=function(self) - --self:diffuse(HSVA(192,1,0.8,0.8)); self:shadowlength(0); - self:shadowcolor( color("#FFFF0077") ); + self:shadowcolor(color(firstShadow)); -- set width - self:zoomto( math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight ); + self:zoomto(math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight); -- find location - self:x( ( scale(beatTime, firstBeatSecs,lastBeatSecs, -fFrameWidth/2,fFrameWidth/2) ) ); + self:x((scale(beatTime,firstBeatSecs,lastBeatSecs,-fFrameWidth/2,fFrameWidth/2))); end; OnCommand=function(self) - self:diffuse(Color("Yellow")); + self:diffuse(Color(firstDiffuse)); self:sleep(beatTime+1); self:linear(2); self:diffusealpha(0); @@ -57,17 +52,17 @@ local function CreateStops(Player) InitCommand=function(self) --self:diffuse(HSVA(192,1,0.8,0.8)); self:shadowlength(0); - self:shadowcolor( color("#FFFF0077") ); + self:shadowcolor(color(secondShadow)); -- set width - self:zoomto( math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight ); + self:zoomto(math.max((secs/songLen)*fFrameWidth, 1),fFrameHeight); -- find location - self:x( ( scale(beatTime, firstBeatSecs,lastBeatSecs, -fFrameWidth/2,fFrameWidth/2) ) ); + self:x((scale(beatTime,firstBeatSecs,lastBeatSecs,-fFrameWidth/2,fFrameWidth/2))); end; OnCommand=function(self) self:diffusealpha(1); self:diffuseshift(); - self:effectcolor1(Color("Green")); - self:effectcolor2(Color("Red")); + self:effectcolor1(Color(firstEffect)); + self:effectcolor2(Color(secondEffect)); self:effectclock('beat'); self:effectperiod(1/8); -- @@ -81,57 +76,14 @@ local function CreateStops(Player) }; end; + for i=1,#delays do + local data = split("=",delays[i]); + delayFrame[#delayFrame+1] = CreateLine(data[1], data[2], "#FFFF0077", "Yellow", "#FFFF0077", "Green", "Red"); + end; + for i=1,#stops do local data = split("=",stops[i]); - local beat = data[1]; - local secs = data[2]; - local beatTime = timingData:GetElapsedTimeFromBeat(beat); - if beatTime < 0 then beatTime = 0; end; - - stopFrame[#stopFrame+1] = Def.ActorFrame { - Def.Quad { - InitCommand=function(self) - --self:diffuse(HSVA(192,1,0.8,0.8)); - self:shadowlength(0); - self:shadowcolor( color("#FFFFFF77") ); - -- set width - self:zoomto( math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight ); - -- find location - self:x( ( scale(beatTime, firstBeatSecs,lastBeatSecs, -fFrameWidth/2,fFrameWidth/2) ) ); - end; - OnCommand=function(self) - self:diffuse(Color("White")); - self:sleep(beatTime+1); - self:linear(2); - self:diffusealpha(0); - end; - }; - Def.Quad { - InitCommand=function(self) - --self:diffuse(HSVA(192,1,0.8,0.8)); - self:shadowlength(0); - self:shadowcolor( color("#FFFFFF77") ); - -- set width - self:zoomto( math.max((secs/songLen)*fFrameWidth, 1), fFrameHeight ); - -- find location - self:x( ( scale(beatTime, firstBeatSecs,lastBeatSecs, -fFrameWidth/2,fFrameWidth/2) ) ); - end; - OnCommand=function(self) - self:diffusealpha(1); - self:diffuseshift(); - self:effectcolor1(Color("Orange")); - self:effectcolor2(Color("Red")); - self:effectclock('beat'); - self:effectperiod(1/8); - -- - self:diffusealpha(0); - self:sleep(beatTime+1); - self:diffusealpha(1); - self:linear(4); - self:diffusealpha(0); - end; - }; - }; + stopFrame[#stopFrame+1] = CreateLine(data[1], data[2], "#FFFFFF77", "White", "#FFFFFF77", "Orange", "Red"); end; end; bars[#bars+1] = stopFrame; From 347a4f1d5c75c72db19d617fdefd328a641113fe Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 13:13:31 -0400 Subject: [PATCH 17/21] Add warps to the bar. Hmm...purple is not the best color. Also, the order we add the frames is important. Best to keep that in mind for future segments. --- .../ScreenGameplay decorations/default.lua | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index 0e6d28e1f9..ddd7db0144 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -4,6 +4,7 @@ local function CreateStops(Player) local bpmFrame = Def.ActorFrame{ Name="BPMFrame"; }; local stopFrame = Def.ActorFrame{ Name="StopFrame"; }; local delayFrame = Def.ActorFrame{ Name="DelayFrame"; }; + local warpFrame = Def.ActorFrame{ Name="WarpFrame"; }; local fFrameWidth = 380; local fFrameHeight = 8; @@ -27,6 +28,7 @@ local function CreateStops(Player) local stops = timingData:GetStops(); local delays = timingData:GetDelays(); + local warps = timingData:GetWarps(); local function CreateLine(beat, secs, firstShadow, firstDiffuse, secondShadow, firstEffect, secondEffect) local beatTime = timingData:GetElapsedTimeFromBeat(beat); @@ -42,7 +44,7 @@ local function CreateStops(Player) self:x((scale(beatTime,firstBeatSecs,lastBeatSecs,-fFrameWidth/2,fFrameWidth/2))); end; OnCommand=function(self) - self:diffuse(Color(firstDiffuse)); + self:diffuse(color(firstDiffuse)); self:sleep(beatTime+1); self:linear(2); self:diffusealpha(0); @@ -61,8 +63,8 @@ local function CreateStops(Player) OnCommand=function(self) self:diffusealpha(1); self:diffuseshift(); - self:effectcolor1(Color(firstEffect)); - self:effectcolor2(Color(secondEffect)); + self:effectcolor1(color(firstEffect)); + self:effectcolor2(color(secondEffect)); self:effectclock('beat'); self:effectperiod(1/8); -- @@ -78,16 +80,25 @@ local function CreateStops(Player) for i=1,#delays do local data = split("=",delays[i]); - delayFrame[#delayFrame+1] = CreateLine(data[1], data[2], "#FFFF0077", "Yellow", "#FFFF0077", "Green", "Red"); + delayFrame[#delayFrame+1] = CreateLine(data[1], data[2], + "#FFFF0077", "#FFFF0077", "#FFFF0077", "#00FF0077", "#FF000077"); end; for i=1,#stops do local data = split("=",stops[i]); - stopFrame[#stopFrame+1] = CreateLine(data[1], data[2], "#FFFFFF77", "White", "#FFFFFF77", "Orange", "Red"); + stopFrame[#stopFrame+1] = CreateLine(data[1], data[2], + "#FFFFFF77", "#FFFFFF77", "#FFFFFF77", "#FFA50077", "#FF000077"); + end; + + for i=1,#warps do + local data = split("=",warps[i]); + warpFrame[#warpFrame+1] = CreateLine(data[1], 0, + "#CC00CC77", "#CC00CC77", "#CC00CC77", "#FF33CC77", "#FF000077"); end; end; bars[#bars+1] = stopFrame; bars[#bars+1] = delayFrame; + bars[#bars+1] = warpFrame; t[#t+1] = bars; end return t From 0f6d4cd813646e4844e4d4cc2e04b085c354dfb9 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 13:35:25 -0400 Subject: [PATCH 18/21] Adjust attacks on offset change. Should we ever store the other timing segments in seconds and not beats in the future, we may want to use this. --- src/Attack.cpp | 8 ++++++++ src/Attack.h | 5 +++++ src/ScreenEdit.cpp | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/src/Attack.cpp b/src/Attack.cpp index 568b83ec4c..25a19415c9 100644 --- a/src/Attack.cpp +++ b/src/Attack.cpp @@ -104,6 +104,14 @@ vector AttackArray::ToVectorString() const return ret; } +void AttackArray::UpdateStartTimes(float delta) +{ + FOREACH(Attack, *this, a) + { + a->fStartSecond += delta; + } +} + /* * (c) 2003-2004 Chris Danford * All rights reserved. diff --git a/src/Attack.h b/src/Attack.h index 9e3ae45310..fe61a48723 100644 --- a/src/Attack.h +++ b/src/Attack.h @@ -76,6 +76,11 @@ struct AttackArray : public vector * @brief Return a string representation used for simfiles. * @return the string representation. */ vector ToVectorString() const; + + /** + * @brief Adjust the starting time of all attacks. + * @param delta the amount to change. */ + void UpdateStartTimes(float delta); }; #endif diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 08e53a6aea..ed8bebe2d4 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -1936,6 +1936,14 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB ) } GetAppropriateTiming().m_fBeat0OffsetInSeconds += fDelta; (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); + if (GAMESTATE->m_bIsUsingStepTiming) + { + GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks.UpdateStartTimes(fDelta); + } + else + { + GAMESTATE->m_pCurSong->m_Attacks.UpdateStartTimes(fDelta); + } SetDirty( true ); } break; @@ -3430,7 +3438,17 @@ static void ChangeBeat0Offset( const RString &sNew ) TimingData &timing = (GAMESTATE->m_bIsUsingStepTiming ? GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : GAMESTATE->m_pCurSong->m_SongTiming); + float old = timing.m_fBeat0OffsetInSeconds; timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); + float delta = timing.m_fBeat0OffsetInSeconds - old; + if (GAMESTATE->m_bIsUsingStepTiming) + { + GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks.UpdateStartTimes(delta); + } + else + { + GAMESTATE->m_pCurSong->m_Attacks.UpdateStartTimes(delta); + } } static void ChangeLastSecondHint( const RString &sNew ) From 6f5d7073518cb94fbbb5d822f5c11bf842bf4397 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 14:14:50 -0400 Subject: [PATCH 19/21] Activate the other segments on the bar. Anyone up to improving my poor taste in colors? --- .../ScreenGameplay decorations/default.lua | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index ddd7db0144..52a449d45e 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -5,6 +5,9 @@ local function CreateStops(Player) local stopFrame = Def.ActorFrame{ Name="StopFrame"; }; local delayFrame = Def.ActorFrame{ Name="DelayFrame"; }; local warpFrame = Def.ActorFrame{ Name="WarpFrame"; }; + local fakeFrame = Def.ActorFrame{ Name="FakeFrame"; }; + local scrollFrame = Def.ActorFrame{ Name="ScrollFrame"; }; + local speedFrame = Def.ActorFrame{ Name="SpeedFrame"; }; local fFrameWidth = 380; local fFrameHeight = 8; @@ -24,11 +27,13 @@ local function CreateStops(Player) local firstBeatSecs = song:GetFirstSecond(); local lastBeatSecs = song:GetLastSecond(); - local bpms = timingData:GetBPMs(); - + local bpms = timingData:GetBPMsAndTimes(); local stops = timingData:GetStops(); local delays = timingData:GetDelays(); local warps = timingData:GetWarps(); + local fakes = timingData:GetFakes(); + local scrolls = timingData:GetScrolls(); + local speeds = timingData:GetSpeeds(); local function CreateLine(beat, secs, firstShadow, firstDiffuse, secondShadow, firstEffect, secondEffect) local beatTime = timingData:GetElapsedTimeFromBeat(beat); @@ -78,6 +83,12 @@ local function CreateStops(Player) }; end; + for i=1,#bpms do + local data = split("=",bpms[i]); + bpmFrame[#bpmFrame+1] = CreateLine(data[1], 0, + "#00808077", "#00808077", "#00808077", "#FF634777", "#FF000077"); + end; + for i=1,#delays do local data = split("=",delays[i]); delayFrame[#delayFrame+1] = CreateLine(data[1], data[2], @@ -90,15 +101,38 @@ local function CreateStops(Player) "#FFFFFF77", "#FFFFFF77", "#FFFFFF77", "#FFA50077", "#FF000077"); end; + for i=1,#scrolls do + local data = split("=",scrolls[i]); + scrollFrame[#scrollFrame+1] = CreateLine(data[1], 0, + "#4169E177", "#4169E177", "#4169E177", "#0000FF77", "#FF000077"); + end; + + for i=1,#speeds do + local data = split("=",speeds[i]); + -- TODO: Turn beats into seconds for this calculation? + speedFrame[#speedFrame+1] = CreateLine(data[1], 0, + "#ADFF2F77", "#ADFF2F77", "#ADFF2F77", "#7CFC0077", "#FF000077"); + end; + for i=1,#warps do local data = split("=",warps[i]); warpFrame[#warpFrame+1] = CreateLine(data[1], 0, "#CC00CC77", "#CC00CC77", "#CC00CC77", "#FF33CC77", "#FF000077"); end; + + for i=1,#fakes do + local data = split("=",fakes[i]); + fakeFrame[#fakeFrame+1] = CreateLine(data[1], 0, + "#BC8F8F77", "#BC8F8F77", "#BC8F8F77", "#F4A46077", "#FF000077"); + end; end; + bars[#bars+1] = bpmFrame; + bars[#bars+1] = scrollFrame; + bars[#bars+1] = speedFrame; bars[#bars+1] = stopFrame; bars[#bars+1] = delayFrame; bars[#bars+1] = warpFrame; + bars[#bars+1] = fakeFrame; t[#t+1] = bars; end return t From 688e27f143bf240d8bb26e22124134bb102ec601 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 14:16:28 -0400 Subject: [PATCH 20/21] Better name. --- .../BGAnimations/ScreenGameplay decorations/default.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index 52a449d45e..c1b82ed972 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -1,4 +1,4 @@ -local function CreateStops(Player) +local function CreateSegments(Player) local t = Def.ActorFrame { }; local bars = Def.ActorFrame{ }; local bpmFrame = Def.ActorFrame{ Name="BPMFrame"; }; @@ -172,7 +172,7 @@ for pn in ivalues(PlayerNumber) do }; Tip=LoadActor( THEME:GetPathG( 'SongMeterDisplay', 'tip ' .. PlayerNumberToString(pn) ) ) .. { InitCommand=cmd(visible,false); }; }; - CreateStops(pn) .. { + CreateSegments(pn) .. { -- InitCommand=cmd(draworder,10); }; }; @@ -223,7 +223,7 @@ t[#t+1] = StandardDecorationFromFileOptional("SongTitle","SongTitle"); }; Tip=LoadActor( THEME:GetPathG( 'SongMeterDisplay', 'tip ' .. PlayerNumberToString(PLAYER_1) ) ) .. { InitCommand=cmd(visible,false); }; }; - CreateStops(); + CreateSegments(); }; --]] if( not GAMESTATE:IsCourseMode() ) then t[#t+1] = Def.Actor{ From 906c36137cc9425e1707135196d55bcc010dece8 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 30 Jun 2011 14:39:57 -0400 Subject: [PATCH 21/21] Simplify. --- .../ScreenGameplay decorations/default.lua | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua index c1b82ed972..815b30b141 100644 --- a/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenGameplay decorations/default.lua @@ -193,38 +193,6 @@ t[#t+1] = StandardDecorationFromFileOptional("BPMDisplay","BPMDisplay"); t[#t+1] = StandardDecorationFromFileOptional("StageDisplay","StageDisplay"); t[#t+1] = StandardDecorationFromFileOptional("SongTitle","SongTitle"); ---[[ t[#t+1] = Def.ActorFrame { - InitCommand=function(self) - self:name("SongMeterDisplay"); - ActorUtil.LoadAllCommandsAndSetXY(self,Var "LoadingScreen"); - end; - LoadActor( THEME:GetPathG( 'SongMeterDisplay', 'frame ' .. PlayerNumberToString(PLAYER_1) ) ) .. { - InitCommand=function(self) - self:name('Frame'); - ActorUtil.LoadAllCommandsAndSetXY(self,"SongMeterDisplay"); - end; - }; - Def.Quad { - InitCommand=cmd(zoomto,2,8); - OnCommand=cmd(x,scale(0.25,0,1,-380/2,380/2);diffuse,Color("Orange");diffusealpha,0.5); - }; - Def.Quad { - InitCommand=cmd(zoomto,2,8); - OnCommand=cmd(x,scale(0.5,0,1,-380/2,380/2);diffuse,Color("Orange");diffusealpha,0.5); - }; - Def.Quad { - InitCommand=cmd(zoomto,2,8); - OnCommand=cmd(x,scale(0.75,0,1,-380/2,380/2);diffuse,Color("Orange");diffusealpha,0.5); - }; - Def.SongMeterDisplay { - InitCommand=cmd(SetStreamWidth,THEME:GetMetric( "SongMeterDisplay", 'StreamWidth' )); - Stream=LoadActor( THEME:GetPathG( 'SongMeterDisplay', 'stream ' .. PlayerNumberToString(PLAYER_1) ) )..{ - InitCommand=cmd(diffuse,Color("Orange");diffusealpha,0.5;blend,Blend.Add;); - }; - Tip=LoadActor( THEME:GetPathG( 'SongMeterDisplay', 'tip ' .. PlayerNumberToString(PLAYER_1) ) ) .. { InitCommand=cmd(visible,false); }; - }; - CreateSegments(); -}; --]] if( not GAMESTATE:IsCourseMode() ) then t[#t+1] = Def.Actor{ JudgmentMessageCommand = function(self, params)