diff --git a/stepmania/Themes/default/Fonts/ScreenMusicScroll titles.redir b/stepmania/Themes/default/Fonts/ScreenMusicScroll titles.redir new file mode 100644 index 0000000000..219504d9e6 --- /dev/null +++ b/stepmania/Themes/default/Fonts/ScreenMusicScroll titles.redir @@ -0,0 +1 @@ +MusicList titles diff --git a/stepmania/src/Background.cpp b/stepmania/src/Background.cpp index 9a4ab6c412..205ba8a6b3 100644 --- a/stepmania/src/Background.cpp +++ b/stepmania/src/Background.cpp @@ -19,7 +19,8 @@ #include "GameState.h" #include "ThemeManager.h" #include "PrefsManager.h" - +#include "NoteTypes.h" +#include // for fmodf const float FADE_SECONDS = 1.0f; @@ -31,20 +32,22 @@ const float FADE_SECONDS = 1.0f; #define RECT_BACKGROUND RectI(LEFT_EDGE,TOP_EDGE,RIGHT_EDGE,BOTTOM_EDGE) -int CompareBGSegments(const BGSegment &seg1, const BGSegment &seg2) -{ - return seg1.m_fStartBeat < seg2.m_fStartBeat; -} -void SortBGSegmentArray( vector &arrayBGSegments ) +const CString STATIC_BACKGROUND = "static background"; +const int MAX_RANDOM_BACKGROUNDS = 5; +const CString RANDOM_BACKGROUND[MAX_RANDOM_BACKGROUNDS] = { - sort( arrayBGSegments.begin(), arrayBGSegments.end(), CompareBGSegments ); -} + "__random1", + "__random2", + "__random3", + "__random4", + "__random5" +}; Background::Background() { - m_iCurBGSegment = 0; + m_iCurBGChange = 0; m_bInDanger = false; m_pFadingBGA = NULL; @@ -72,12 +75,14 @@ Background::~Background() void Background::Unload() { - for( unsigned i=0; i::iterator iter = m_BGAnimations.begin(); + iter != m_BGAnimations.end(); + iter++ ) + delete iter->second; m_BGAnimations.clear(); - m_aBGSegments.clear(); - m_iCurBGSegment = 0; + m_aBGChanges.clear(); + m_iCurBGChange = 0; } void Background::LoadFromAniDir( CString sAniDir ) @@ -87,10 +92,10 @@ void Background::LoadFromAniDir( CString sAniDir ) BGAnimation* pTempBGA; pTempBGA = new BGAnimation; pTempBGA->LoadFromAniDir( sAniDir ); - m_BGAnimations.push_back( pTempBGA ); + m_BGAnimations[STATIC_BACKGROUND] = pTempBGA; } -BGAnimation *Background::GetBGA(const Song *pSong, const BackgroundChange &aniseg) const +BGAnimation *Background::CreateSongBGA(const Song *pSong, CString sBGName) const { BGAnimation *pTempBGA; @@ -100,7 +105,7 @@ BGAnimation *Background::GetBGA(const Song *pSong, const BackgroundChange &anise CStringArray asFiles; // Look for BGAnims in the song dir - GetDirListing( pSong->GetSongDir()+aniseg.m_sBGName, asFiles, true, true ); + GetDirListing( pSong->GetSongDir()+sBGName, asFiles, true, true ); if( !asFiles.empty() ) { pTempBGA = new BGAnimation; @@ -108,7 +113,7 @@ BGAnimation *Background::GetBGA(const Song *pSong, const BackgroundChange &anise return pTempBGA; } // Look for BG movies in the song dir - GetDirListing( pSong->GetSongDir()+aniseg.m_sBGName, asFiles, false, true ); + GetDirListing( pSong->GetSongDir()+sBGName, asFiles, false, true ); if( !asFiles.empty() ) { pTempBGA = new BGAnimation; @@ -116,7 +121,7 @@ BGAnimation *Background::GetBGA(const Song *pSong, const BackgroundChange &anise return pTempBGA; } // Look for movies in the RandomMovies dir - GetDirListing( RANDOMMOVIES_DIR+aniseg.m_sBGName, asFiles, false, true ); + GetDirListing( RANDOMMOVIES_DIR+sBGName, asFiles, false, true ); if( !asFiles.empty() ) { pTempBGA = new BGAnimation; @@ -125,7 +130,7 @@ BGAnimation *Background::GetBGA(const Song *pSong, const BackgroundChange &anise } // Look for BGAnims in the BGAnims dir - GetDirListing( BG_ANIMS_DIR+aniseg.m_sBGName, asFiles, true, true ); + GetDirListing( BG_ANIMS_DIR+sBGName, asFiles, true, true ); if( !asFiles.empty() ) { pTempBGA = new BGAnimation; @@ -134,16 +139,78 @@ BGAnimation *Background::GetBGA(const Song *pSong, const BackgroundChange &anise } // Look for BGAnims in the BGAnims dir - GetDirListing( VISUALIZATIONS_DIR+aniseg.m_sBGName, asFiles, false, true ); + GetDirListing( VISUALIZATIONS_DIR+sBGName, asFiles, false, true ); if( !asFiles.empty() ) { pTempBGA = new BGAnimation; pTempBGA->LoadFromVisualization( asFiles[0] ); return pTempBGA; } + + // There is no background by this name. return NULL; } +BGAnimation* Background::CreateRandomBGA() const +{ + switch( PREFSMAN->m_BackgroundMode ) + { + default: + ASSERT(0); + // fall through + case PrefsManager::BGMODE_OFF: + return NULL; + case PrefsManager::BGMODE_ANIMATIONS: + { + CStringArray arrayPossibleAnims; + GetDirListing( BG_ANIMS_DIR+"*", arrayPossibleAnims, true, true ); + // strip out "cvs" and "danger + int i; + for( i=arrayPossibleAnims.size()-1; i>=0; i-- ) + if( 0==stricmp(arrayPossibleAnims[i].Right(3),"cvs") || 0==stricmp(arrayPossibleAnims[i].Right(3),"danger") ) + arrayPossibleAnims.erase(arrayPossibleAnims.begin()+i, + arrayPossibleAnims.begin()+i+1); + + if( arrayPossibleAnims.empty() ) + return NULL; + unsigned index = rand() % arrayPossibleAnims.size(); + BGAnimation *pTempBGA = new BGAnimation; + pTempBGA->LoadFromAniDir( arrayPossibleAnims[index] ); + return pTempBGA; + } + case PrefsManager::BGMODE_MOVIEVIS: + { + CStringArray arrayPossibleMovies; + GetDirListing( VISUALIZATIONS_DIR + "*.avi", arrayPossibleMovies, false, true ); + GetDirListing( VISUALIZATIONS_DIR + "*.mpg", arrayPossibleMovies, false, true ); + GetDirListing( VISUALIZATIONS_DIR + "*.mpeg", arrayPossibleMovies, false, true ); + + if( arrayPossibleMovies.empty() ) + return NULL; + unsigned index = rand() % arrayPossibleMovies.size(); + BGAnimation* pTempBGA = new BGAnimation; + pTempBGA->LoadFromVisualization( arrayPossibleMovies[index] ); + return pTempBGA; + } + break; + case PrefsManager::BGMODE_RANDOMMOVIES: + { + CStringArray arrayPossibleMovies; + GetDirListing( RANDOMMOVIES_DIR + "*.avi", arrayPossibleMovies, false, true ); + GetDirListing( RANDOMMOVIES_DIR + "*.mpg", arrayPossibleMovies, false, true ); + GetDirListing( RANDOMMOVIES_DIR + "*.mpeg", arrayPossibleMovies, false, true ); + + if( arrayPossibleMovies.empty() ) + return NULL; + unsigned index = rand() % arrayPossibleMovies.size(); + BGAnimation *pTempBGA = new BGAnimation; + pTempBGA->LoadFromMovie( arrayPossibleMovies[index], true, false ); + return pTempBGA; + } + break; + } +} + void Background::LoadFromSong( Song* pSong ) { Unload(); @@ -153,201 +220,94 @@ void Background::LoadFromSong( Song* pSong ) CString sSongBGPath = pSong && pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathTo("Graphics","Common fallback background"); - // // Load the static background that will before notes start and after notes end - // - { BGAnimation *pTempBGA = new BGAnimation; pTempBGA->LoadFromStaticGraphic( sSongBGPath ); - m_BGAnimations.push_back( pTempBGA ); + m_BGAnimations[STATIC_BACKGROUND] = pTempBGA; } + + // Load random backgrounds + { + for( int i=0; iHasBGChanges() ) { - // start off showing the static song background - m_aBGSegments.push_back( BGSegment(-10000,0,false) ); - - // Load the animations used by the song's pre-defined animation plan. - // the song has a plan. Use it. + // Load all song-specified backgrounds for( unsigned i=0; im_BackgroundChanges.size(); i++ ) { - const BackgroundChange& aniseg = pSong->m_BackgroundChanges[i]; - bool bFade = i==0; + float fStartBeat = pSong->m_BackgroundChanges[i].m_fStartBeat; + CString sBGName = pSong->m_BackgroundChanges[i].m_sBGName; + + bool bIsAlreadyLoaded = m_BGAnimations.find(sBGName) != m_BGAnimations.end(); - BGAnimation *pTempBGA = GetBGA(pSong, aniseg); - - if(pTempBGA != NULL) + if( !bIsAlreadyLoaded ) { - m_BGAnimations.push_back( pTempBGA ); - // add to the plan - m_aBGSegments.push_back( BGSegment(aniseg.m_fStartBeat, m_BGAnimations.size()-1, bFade) ); + BGAnimation *pTempBGA = CreateSongBGA(pSong, sBGName); + if( pTempBGA ) + m_BGAnimations[sBGName] = pTempBGA; + else // the background was not found. Use a random one instead + sBGName = RANDOM_BACKGROUND[ rand()%MAX_RANDOM_BACKGROUNDS ]; } + + m_aBGChanges.push_back( BackgroundChange(fStartBeat, sBGName) ); } - - // end showing the static song background - m_aBGSegments.push_back( BGSegment(pSong->m_fLastBeat,0,false) ); - - SortBGSegmentArray( m_aBGSegments ); // Need to sort in case there is a background change after the last beat (not likely) } else // pSong doesn't have an animation plan { - - enum BackgroundMode { MODE_STATIC_BG, MODE_ANIMATIONS, MODE_MOVIE_VIS, MODE_RANDOMMOVIES } backgroundMode; - - // - // figure out what BackgroundMode to use - // - if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_OFF ) - backgroundMode = MODE_STATIC_BG; - else if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_MOVIEVIS ) - backgroundMode = MODE_MOVIE_VIS; - else if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_RANDOMMOVIES ) - backgroundMode = MODE_RANDOMMOVIES; - else - backgroundMode = MODE_ANIMATIONS; - - bool bFade = backgroundMode==MODE_RANDOMMOVIES; - - // - // Load animations that will play while notes are active - // - switch( backgroundMode ) - { - case MODE_STATIC_BG: - break; - case MODE_MOVIE_VIS: - { - CStringArray arrayPossibleMovies; - GetDirListing( VISUALIZATIONS_DIR + "*.avi", arrayPossibleMovies, false, true ); - GetDirListing( VISUALIZATIONS_DIR + "*.mpg", arrayPossibleMovies, false, true ); - GetDirListing( VISUALIZATIONS_DIR + "*.mpeg", arrayPossibleMovies, false, true ); - - BGAnimation *pTempBGA = NULL; - if( !arrayPossibleMovies.empty() ) - { - unsigned index = rand() % arrayPossibleMovies.size(); - pTempBGA = new BGAnimation; - pTempBGA->LoadFromVisualization( arrayPossibleMovies[index] ); - } - else - { - pTempBGA = new BGAnimation; - pTempBGA->LoadFromStaticGraphic( sSongBGPath ); - } - m_BGAnimations.push_back( pTempBGA ); - } - break; - case MODE_ANIMATIONS: - { - CStringArray arrayPossibleAnims; - GetDirListing( BG_ANIMS_DIR+"*", arrayPossibleAnims, true, true ); - // strip out "cvs" and "danger - int i; - for( i=arrayPossibleAnims.size()-1; i>=0; i-- ) - if( 0==stricmp(arrayPossibleAnims[i].Right(3),"cvs") || 0==stricmp(arrayPossibleAnims[i].Right(3),"danger") ) - arrayPossibleAnims.erase(arrayPossibleAnims.begin()+i, - arrayPossibleAnims.begin()+i+1); - for( i=0; i<4 && !arrayPossibleAnims.empty(); i++ ) - { - unsigned index = rand() % arrayPossibleAnims.size(); - BGAnimation *pTempBGA = new BGAnimation; - pTempBGA->LoadFromAniDir( arrayPossibleAnims[index] ); - m_BGAnimations.push_back( pTempBGA ); - arrayPossibleAnims.erase( arrayPossibleAnims.begin()+index, - arrayPossibleAnims.begin()+index+1 ); - } - } - break; - case MODE_RANDOMMOVIES: - { - CStringArray arrayPossibleMovies; - GetDirListing( RANDOMMOVIES_DIR + "*.avi", arrayPossibleMovies, false, true ); - GetDirListing( RANDOMMOVIES_DIR + "*.mpg", arrayPossibleMovies, false, true ); - GetDirListing( RANDOMMOVIES_DIR + "*.mpeg", arrayPossibleMovies, false, true ); - for( int i=0; i<4 && !arrayPossibleMovies.empty(); i++ ) - { - unsigned index = rand() % arrayPossibleMovies.size(); - BGAnimation *pTempBGA = new BGAnimation; - pTempBGA->LoadFromMovie( arrayPossibleMovies[index], true, false ); - m_BGAnimations.push_back( pTempBGA ); - arrayPossibleMovies.erase( arrayPossibleMovies.begin()+index, - arrayPossibleMovies.begin()+index+1 ); - } - } - break; - default: - ASSERT(0); - } - - - // At this point, m_BGAnimations[0] is the song background, and everything else - // in m_BGAnimations should be cycled through randomly while notes are playing. - // - // Generate an animation plan - // - if( backgroundMode == MODE_MOVIE_VIS ) - { - m_aBGSegments.push_back( BGSegment(-10000,1,false) ); - return; - } - else - { - // start off showing the static song background - m_aBGSegments.push_back( BGSegment(-10000,0,false) ); - } - const float fFirstBeat = pSong->m_fFirstBeat; const float fLastBeat = pSong->m_fLastBeat; - /* If we have only 2, only generate a single animation segment for for the - * whole song. Otherwise, if it's a movie, it'll loop every four measures; we - * want it to play continuously. */ - if( m_BGAnimations.size() == 2) { - m_aBGSegments.push_back( BGSegment(fFirstBeat,1,bFade) ); - } else { - // change BG every 4 bars - for( float f=fFirstBeat; fm_BPMSegments.size(); i++ ) - { - const BPMSegment& bpmseg = pSong->m_BPMSegments[i]; - - if( bpmseg.m_fStartBeat < fFirstBeat || bpmseg.m_fStartBeat > fLastBeat ) - continue; // skip] - - int index; - if( m_BGAnimations.size()==1 ) - index = 0; - else - index = 1 + int(bpmseg.m_fBPM)%(m_BGAnimations.size()-1); - m_aBGSegments.push_back( BGSegment(bpmseg.m_fStartBeat,index,bFade) ); - } + // change BG every 4 bars + for( float f=fFirstBeat; fm_fLastBeat,0,bFade) ); - - // sort segments - SortBGSegmentArray( m_aBGSegments ); + // change BG every BPM change that is at the beginning of a measure + for( unsigned i=0; im_BPMSegments.size(); i++ ) + { + const BPMSegment& bpmseg = pSong->m_BPMSegments[i]; + + if( fmodf(bpmseg.m_fStartBeat, BEATS_PER_MEASURE) != 0 ) + continue; // skip + + if( bpmseg.m_fStartBeat < fFirstBeat || bpmseg.m_fStartBeat > fLastBeat ) + continue; // skip + + CString sBGName = RANDOM_BACKGROUND[ rand()%MAX_RANDOM_BACKGROUNDS ]; + m_aBGChanges.push_back( BackgroundChange(bpmseg.m_fStartBeat,sBGName) ); + } } - for( unsigned i=0; im_fLastBeat,STATIC_BACKGROUND) ); + + + // sort segments + SortBackgroundChangesArray( m_aBGChanges ); + + + + for( map::iterator iter = m_BGAnimations.begin(); + iter != m_BGAnimations.end(); + iter++ ) { - m_BGAnimations[i]->SetXY( (float)LEFT_EDGE, (float)TOP_EDGE ); - m_BGAnimations[i]->SetZoomX( fXZoom ); - m_BGAnimations[i]->SetZoomY( fYZoom ); + iter->second->SetXY( (float)LEFT_EDGE, (float)TOP_EDGE ); + iter->second->SetZoomX( fXZoom ); + iter->second->SetZoomY( fYZoom ); } m_BGADanger.SetXY( (float)LEFT_EDGE, (float)TOP_EDGE ); @@ -360,7 +320,7 @@ void Background::Update( float fDeltaTime ) { ActorFrame::Update( fDeltaTime ); - if( DangerVisible() ) + if( IsDangerVisible() ) { m_BGADanger.Update( fDeltaTime ); } @@ -375,17 +335,17 @@ void Background::Update( float fDeltaTime ) // Find the BGSegment we're in unsigned i; - for( i=0; im_fSongBeat < m_aBGSegments[i+1].m_fStartBeat ) + for( i=0; im_fSongBeat < m_aBGChanges[i+1].m_fStartBeat ) break; - ASSERT( i >= 0 && i= 0 && i m_iCurBGSegment ) + if( int(i) > m_iCurBGChange ) { // LOG->Trace( "%d, %d, %f, %f\n", m_iCurBGSegment, i, m_aBGSegments[i].m_fStartBeat, GAMESTATE->m_fSongBeat ); - BGAnimation* pOld = GetCurBGA(); - m_iCurBGSegment = i; - BGAnimation* pNew = GetCurBGA(); + BGAnimation* pOld = GetCurrentBGA(); + m_iCurBGChange = i; + BGAnimation* pNew = GetCurrentBGA(); if( pOld != pNew ) { @@ -393,11 +353,12 @@ void Background::Update( float fDeltaTime ) pNew->GainingFocus(); m_pFadingBGA = pOld; - m_fSecsLeftInFade = m_aBGSegments[m_iCurBGSegment].m_bFade ? FADE_SECONDS : 0; + bool bBGAnimsMode = PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_ANIMATIONS; + m_fSecsLeftInFade = bBGAnimsMode ? 0 : FADE_SECONDS; } } - GetCurBGA()->Update( fDeltaTime ); + GetCurrentBGA()->Update( fDeltaTime ); if( m_pFadingBGA ) { m_pFadingBGA->Update( fDeltaTime ); @@ -416,13 +377,13 @@ void Background::DrawPrimitives() { ActorFrame::DrawPrimitives(); - if( DangerVisible() ) + if( IsDangerVisible() ) { m_BGADanger.Draw(); } else { - GetCurBGA()->Draw(); + GetCurrentBGA()->Draw(); if( m_pFadingBGA ) m_pFadingBGA->Draw(); } @@ -432,7 +393,7 @@ void Background::DrawPrimitives() m_quadBorder[i].Draw(); } -bool Background::DangerVisible() +bool Background::IsDangerVisible() { return m_bInDanger && PREFSMAN->m_bShowDanger && (RageTimer::GetTimeSinceStart() - (int)RageTimer::GetTimeSinceStart()) < 0.5f; } diff --git a/stepmania/src/Background.h b/stepmania/src/Background.h index c05bdd2c69..60a9737203 100644 --- a/stepmania/src/Background.h +++ b/stepmania/src/Background.h @@ -12,22 +12,11 @@ ----------------------------------------------------------------------------- */ - #include "Sprite.h" #include "Quad.h" #include "ActorFrame.h" -#include "song.h" #include "BGAnimation.h" - - -struct BGSegment // like a BGChange, but holds index of a background instead of name -{ - BGSegment() {}; - BGSegment( float b, int i, bool f ) { m_fStartBeat = b; m_iBGIndex = i; m_bFade = f; }; - float m_fStartBeat; - int m_iBGIndex; - bool m_bFade; -}; +#include "Song.h" class Background : public ActorFrame @@ -53,17 +42,21 @@ public: virtual bool IsInDanger() { return m_bInDanger; }; protected: - bool DangerVisible(); - BGAnimation *GetBGA(const Song *pSong, const BackgroundChange &aniseg) const; + bool IsDangerVisible(); BGAnimation m_BGADanger; - // used in all BackgroundModes except OFF - vector m_BGAnimations; - vector m_aBGSegments; - int m_iCurBGSegment; // this increases as we move into new segments - BGAnimation* GetCurBGA() { int index = m_aBGSegments[m_iCurBGSegment].m_iBGIndex; return m_BGAnimations[index]; }; - BGAnimation* m_pCurrentBGA; + + BGAnimation* CreateSongBGA(const Song *pSong, CString sBGName) const; + BGAnimation* CreateRandomBGA() const; + + map m_BGAnimations; + vector m_aBGChanges; + int m_iCurBGChange; // starts at 0 and increases to m_aBGSegments.size()-1 + BGAnimation* GetCurrentBGA() + { + return m_BGAnimations[ m_aBGChanges[m_iCurBGChange].m_sBGName ]; + } BGAnimation* m_pFadingBGA; float m_fSecsLeftInFade; diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 05b615deb3..f50ab99769 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -174,6 +174,7 @@ void NoteField::DrawBPMText( const float fBeat, const float fBPM ) const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat ); const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); + m_textMeasureNumber.SetHorizAlign( Actor::align_right ); m_textMeasureNumber.SetDiffuse( RageColor(1,0,0,1) ); m_textMeasureNumber.SetGlow( RageColor(1,1,1,cosf(RageTimer::GetTimeSinceStart()*2)/2+0.5f) ); m_textMeasureNumber.SetText( ssprintf("%.2f", fBPM) ); @@ -186,6 +187,7 @@ void NoteField::DrawFreezeText( const float fBeat, const float fSecs ) const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat ); const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); + m_textMeasureNumber.SetHorizAlign( Actor::align_right ); m_textMeasureNumber.SetDiffuse( RageColor(0.8f,0.8f,0,1) ); m_textMeasureNumber.SetGlow( RageColor(1,1,1,cosf(RageTimer::GetTimeSinceStart()*2)/2+0.5f) ); m_textMeasureNumber.SetText( ssprintf("%.2f", fSecs) ); @@ -198,10 +200,11 @@ void NoteField::DrawBGChangeText( const float fBeat, const CString sNewBGName ) const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fBeat ); const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); + m_textMeasureNumber.SetHorizAlign( Actor::align_left ); m_textMeasureNumber.SetDiffuse( RageColor(0,1,0,1) ); m_textMeasureNumber.SetGlow( RageColor(1,1,1,cosf(RageTimer::GetTimeSinceStart()*2)/2+0.5f) ); m_textMeasureNumber.SetText( sNewBGName ); - m_textMeasureNumber.SetXY( +GetWidth()/2.f + 10, fYPos ); + m_textMeasureNumber.SetXY( +GetWidth()/2.f, fYPos ); m_textMeasureNumber.Draw(); } diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 5a2bb18ca9..48e0990c72 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -111,6 +111,7 @@ Menu g_KeyboardShortcuts MenuRow( "Shift + Up/Down: Drag area marker", false ), MenuRow( "P: Play selection", false ), MenuRow( "Ctrl + P: Play whole song", false ), + MenuRow( "Shift + P: Play current beat to end", false ), MenuRow( "F7/F8: Decrease/increase BPM at cur beat", false ), MenuRow( "F9/F10: Decrease/increase stop at cur beat", false ), MenuRow( "F11/F12: Decrease/increase music offset", false ), @@ -119,23 +120,25 @@ Menu g_KeyboardShortcuts * menu each time), so it doesn't use a whole bunch of hotkeys. */ MenuRow( "[ and ]: Decrease/increase sample music start", false ), MenuRow( "{ and }: Decrease/increase sample music length", false ), - MenuRow( "M: Play sample music", false ) + MenuRow( "M: Play sample music", false ), + MenuRow( "B: Add/Edit Background Change", false ) ); Menu g_MainMenu ( "Main Menu", - MenuRow( "Edit Notes Statistics", true ), - MenuRow( "Play Whole Song", true ), - MenuRow( "Save", true ), - MenuRow( "Player Options", true ), - MenuRow( "Song Options", true ), - MenuRow( "Edit Song Info", true ), - MenuRow( "Add/Edit BPM Change", true ), - MenuRow( "Add/Edit Stop", true ), - MenuRow( "Add/Edit BG Change", true ), - MenuRow( "Play preview music", true ), - MenuRow( "Exit", true ) + MenuRow( "Edit Notes Statistics", true ), + MenuRow( "Play Whole Song", true ), + MenuRow( "Play Current Beat To End", true ), + MenuRow( "Save", true ), + MenuRow( "Player Options", true ), + MenuRow( "Song Options", true ), + MenuRow( "Edit Song Info", true ), + MenuRow( "Add/Edit BPM Change", true ), + MenuRow( "Add/Edit Stop", true ), + MenuRow( "Add/Edit BG Change", true ), + MenuRow( "Play preview music", true ), + MenuRow( "Exit", true ) ); Menu g_AreaMenu @@ -913,11 +916,17 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ case SDLK_m: PlayPreviewMusic(); break; + case SDLK_b: + HandleMainMenuChoice( edit_bg_change, NULL ); + break; case SDLK_p: { if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,SDLK_LCTRL)) || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,SDLK_RCTRL)) ) HandleMainMenuChoice( play_whole_song, NULL ); + else if( INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,SDLK_LSHIFT)) || + INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD,SDLK_RSHIFT)) ) + HandleMainMenuChoice( play_current_beat_to_end, NULL ); else if( m_NoteFieldEdit.m_fBeginMarker!=-1 && m_NoteFieldEdit.m_fEndMarker!=-1 ) HandleAreaMenuChoice( play, NULL ); @@ -1088,24 +1097,6 @@ void ScreenEdit::OnSnapModeChange() // Begin helper functions for InputEdit -void AddBGChange( CString sBGName ) -{ - Song* pSong = GAMESTATE->m_pCurSong; - unsigned i; - for( i=0; im_BackgroundChanges.size(); i++ ) - { - if( pSong->m_BackgroundChanges[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) - break; - } - - if( i != pSong->m_BackgroundChanges.size() ) // there is already a BGChange here - pSong->m_BackgroundChanges.erase( pSong->m_BackgroundChanges.begin()+i, - pSong->m_BackgroundChanges.begin()+i+1); - - // create a new BGChange - if( sBGName != "" ) - pSong->AddBackgroundChange( BackgroundChange(GAMESTATE->m_fSongBeat, sBGName) ); -} void ChangeDescription( CString sNew ) { @@ -1183,6 +1174,13 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers ) HandleAreaMenuChoice( play, NULL ); } break; + case play_current_beat_to_end: + { + m_NoteFieldEdit.m_fBeginMarker = GAMESTATE->m_fSongBeat; + m_NoteFieldEdit.m_fEndMarker = m_NoteFieldEdit.GetLastBeat(); + HandleAreaMenuChoice( play, NULL ); + } + break; case save: { // copy edit into current Notes @@ -1193,7 +1191,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers ) GAMESTATE->m_pCurSong->Save(); SCREENMAN->SystemMessage( "Saved as SM and DWI." ); - SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","edit save") ); + SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","ScreenEdit save") ); } break; case player_options: @@ -1224,26 +1222,28 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers ) // // Fill in option names // + + // m_pSong->GetSongDir() has trailing slash g_BGChange.rows[add_song_bganimation].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"/*.*", g_BGChange.rows[add_song_bganimation].choices, true ); + GetDirListing( m_pSong->GetSongDir()+"*.*", g_BGChange.rows[add_song_bganimation].choices, true ); g_BGChange.rows[add_song_movie].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"/*.avi", g_BGChange.rows[add_song_movie].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"/*.mpg", g_BGChange.rows[add_song_movie].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"/*.mpeg", g_BGChange.rows[add_song_movie].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.avi", g_BGChange.rows[add_song_movie].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.mpg", g_BGChange.rows[add_song_movie].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.mpeg", g_BGChange.rows[add_song_movie].choices, false ); g_BGChange.rows[add_global_random_movie].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"/*.avi", g_BGChange.rows[add_global_random_movie].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"/*.mpg", g_BGChange.rows[add_global_random_movie].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"/*.mpeg", g_BGChange.rows[add_global_random_movie].choices, false ); + GetDirListing( RANDOMMOVIES_DIR+"*.avi", g_BGChange.rows[add_global_random_movie].choices, false ); + GetDirListing( RANDOMMOVIES_DIR+"*.mpg", g_BGChange.rows[add_global_random_movie].choices, false ); + GetDirListing( RANDOMMOVIES_DIR+"*.mpeg", g_BGChange.rows[add_global_random_movie].choices, false ); g_BGChange.rows[add_global_bganimation].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"/*.*", g_BGChange.rows[add_global_bganimation].choices, true ); + GetDirListing( BG_ANIMS_DIR+"*.*", g_BGChange.rows[add_global_bganimation].choices, true ); g_BGChange.rows[add_global_visualization].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"/*.avi", g_BGChange.rows[add_global_visualization].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"/*.mpg", g_BGChange.rows[add_global_visualization].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"/*.mpeg", g_BGChange.rows[add_global_visualization].choices, false ); + GetDirListing( VISUALIZATIONS_DIR+"*.avi", g_BGChange.rows[add_global_visualization].choices, false ); + GetDirListing( VISUALIZATIONS_DIR+"*.mpg", g_BGChange.rows[add_global_visualization].choices, false ); + GetDirListing( VISUALIZATIONS_DIR+"*.mpeg", g_BGChange.rows[add_global_visualization].choices, false ); // @@ -1256,7 +1256,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers ) g_BGChange.rows[add_random].enabled = true; g_BGChange.rows[add_song_bganimation].enabled = g_BGChange.rows[add_song_bganimation].choices.size() > 0; - g_BGChange.rows[add_song_movie].enabled = g_BGChange.rows[add_global_random_movie].choices.size() > 0; + g_BGChange.rows[add_song_movie].enabled = g_BGChange.rows[add_song_movie].choices.size() > 0; g_BGChange.rows[add_global_random_movie].enabled = g_BGChange.rows[add_global_random_movie].choices.size() > 0; g_BGChange.rows[add_global_bganimation].enabled = g_BGChange.rows[add_global_bganimation].choices.size() > 0; g_BGChange.rows[add_global_visualization].enabled = g_BGChange.rows[add_global_visualization].choices.size() > 0; @@ -1515,30 +1515,37 @@ void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, int* iAnswers ) { Song* pSong = GAMESTATE->m_pCurSong; + CString sBGName; + switch( c ) { case add_random: - SCREENMAN->TextEntry( SM_None, "Edit main title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitle, ChangeMainTitle, NULL ); + sBGName = "-random-"; break; case add_song_bganimation: - SCREENMAN->TextEntry( SM_None, "Edit sub title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitle, ChangeSubTitle, NULL ); - break; case add_song_movie: - SCREENMAN->TextEntry( SM_None, "Edit artist.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtist, ChangeArtist, NULL ); - break; case add_global_random_movie: - SCREENMAN->TextEntry( SM_None, "Edit main title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitleTranslit, ChangeMainTitleTranslit, NULL ); - break; case add_global_bganimation: - SCREENMAN->TextEntry( SM_None, "Edit sub title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitleTranslit, ChangeSubTitleTranslit, NULL ); - break; case add_global_visualization: - SCREENMAN->TextEntry( SM_None, "Edit artist transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtistTranslit, ChangeArtistTranslit, NULL ); + sBGName = g_BGChange.rows[c].choices[iAnswers[c]]; break; case delete_change: - SCREENMAN->TextEntry( SM_None, "Edit artist transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtistTranslit, ChangeArtistTranslit, NULL ); + sBGName = ""; break; default: ASSERT(0); }; + + unsigned i; + for( i=0; im_BackgroundChanges.size(); i++ ) + if( m_pSong->m_BackgroundChanges[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) + break; + + if( i != m_pSong->m_BackgroundChanges.size() ) // there is already a BGChange here + m_pSong->m_BackgroundChanges.erase( m_pSong->m_BackgroundChanges.begin()+i, + m_pSong->m_BackgroundChanges.begin()+i+1); + + // create a new BGChange + if( sBGName != "" ) + m_pSong->AddBackgroundChange( BackgroundChange(GAMESTATE->m_fSongBeat, sBGName) ); } diff --git a/stepmania/src/ScreenEdit.h b/stepmania/src/ScreenEdit.h index b470f4f4a1..d85e7e4d79 100644 --- a/stepmania/src/ScreenEdit.h +++ b/stepmania/src/ScreenEdit.h @@ -104,6 +104,7 @@ public: enum MainMenuChoice { edit_notes_statistics, play_whole_song, + play_current_beat_to_end, save, player_options, song_options, diff --git a/stepmania/src/ScreenMiniMenu.cpp b/stepmania/src/ScreenMiniMenu.cpp index 968f66ec6b..aaa578fc86 100644 --- a/stepmania/src/ScreenMiniMenu.cpp +++ b/stepmania/src/ScreenMiniMenu.cpp @@ -124,7 +124,7 @@ ScreenMiniMenu::ScreenMiniMenu( Menu* pDef, ScreenMessage SM_SendOnOK, ScreenMes m_textAnswer[k].SetX( fAnswerX ); } - SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","ScreenMiniMenu music") ); + SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","Common prompt") ); } void ScreenMiniMenu::Update( float fDeltaTime ) @@ -277,11 +277,18 @@ int ScreenMiniMenu::GetGoDownSpot() bool ScreenMiniMenu::CanGoLeft() { - return m_iCurAnswers[m_iCurLine] != 0; + int iNumInCurRow = m_Def.rows[m_iCurLine].choices.size(); + if( iNumInCurRow==0 ) + return false; + else + return m_iCurAnswers[m_iCurLine] != 0; } bool ScreenMiniMenu::CanGoRight() { int iNumInCurRow = m_Def.rows[m_iCurLine].choices.size(); - return m_iCurAnswers[m_iCurLine] != iNumInCurRow-1; + if( iNumInCurRow==0 ) + return false; + else + return m_iCurAnswers[m_iCurLine] != iNumInCurRow-1; } diff --git a/stepmania/src/ScreenMusicScroll.cpp b/stepmania/src/ScreenMusicScroll.cpp index 0c005f1f2a..6841448155 100644 --- a/stepmania/src/ScreenMusicScroll.cpp +++ b/stepmania/src/ScreenMusicScroll.cpp @@ -160,7 +160,7 @@ ScreenMusicScroll::ScreenMusicScroll() for( i=0; iGetPathTo("Fonts","music scroll") ); + m_textLines[m_iNumLines].LoadFromFont( THEME->GetPathTo("Fonts","Screen MusicScroll titles") ); m_textLines[m_iNumLines].SetText( pSong->GetFullDisplayTitle(), pSong->GetFullTranslitTitle() ); m_textLines[m_iNumLines].SetDiffuse( SONGMAN->GetSongColor(pSong) ); m_textLines[m_iNumLines].SetZoom( TEXT_ZOOM ); diff --git a/stepmania/src/ScreenPrompt.cpp b/stepmania/src/ScreenPrompt.cpp index ed6d4139eb..2689db1487 100644 --- a/stepmania/src/ScreenPrompt.cpp +++ b/stepmania/src/ScreenPrompt.cpp @@ -79,7 +79,7 @@ ScreenPrompt::ScreenPrompt( ScreenMessage SM_SendWhenDone, CString sText, bool b m_textAnswer[m_bAnswer].SetEffectGlowShift(); - SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","ScreenMenuPrompt music.mp3") ); + SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","Common prompt") ); } void ScreenPrompt::Update( float fDeltaTime ) diff --git a/stepmania/src/ScreenTextEntry.cpp b/stepmania/src/ScreenTextEntry.cpp index d7c6900b71..1a831cb055 100644 --- a/stepmania/src/ScreenTextEntry.cpp +++ b/stepmania/src/ScreenTextEntry.cpp @@ -70,7 +70,7 @@ ScreenTextEntry::ScreenTextEntry( ScreenMessage SM_SendWhenDone, CString sQuesti UpdateText(); this->AddChild( &m_textAnswer ); - SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","menu prompt") ); + SOUNDMAN->PlayOnce( THEME->GetPathTo("Sounds","Common prompt") ); } void ScreenTextEntry::UpdateText() diff --git a/stepmania/src/ThemeManager.cpp b/stepmania/src/ThemeManager.cpp index 46fb1cb6af..459559e269 100644 --- a/stepmania/src/ThemeManager.cpp +++ b/stepmania/src/ThemeManager.cpp @@ -213,7 +213,9 @@ try_element_again: * the default theme point to "_shared background", and themes override * just "_shared background"; the redirs in the default theme should end * up resolving to the overridden background. */ - CString sPath = GetPathTo(sAssetCategory, sNewFileName); + /* Use GetPathToOptional because we don't want report that there's an element + * missing. Instead we want to report that the redirect is invalid. */ + CString sPath = GetPathToOptional(sAssetCategory, sNewFileName); if( !sPath.empty() ) return sPath; diff --git a/stepmania/src/song.h b/stepmania/src/song.h index fe6b12baa5..1a23304260 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -47,6 +47,8 @@ struct BackgroundChange CString m_sBGName; }; +void SortBackgroundChangesArray( vector &arrayBackgroundChanges ); + struct LyricSegment { LyricSegment() { m_fStartTime = -1; };