diff --git a/stepmania/BackgroundEffects/Centered.xml b/stepmania/BackgroundEffects/Centered.xml new file mode 100644 index 0000000000..b305546a66 --- /dev/null +++ b/stepmania/BackgroundEffects/Centered.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/stepmania/BackgroundEffects/Checkerboard2x2.xml b/stepmania/BackgroundEffects/Checkerboard2x2.xml new file mode 100644 index 0000000000..e199e9ebf4 --- /dev/null +++ b/stepmania/BackgroundEffects/Checkerboard2x2.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/stepmania/BackgroundEffects/Stretch.xml b/stepmania/BackgroundEffects/Stretch.xml new file mode 100644 index 0000000000..c5197a642b --- /dev/null +++ b/stepmania/BackgroundEffects/Stretch.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/stepmania/BackgroundTransitions/CrossFade.xml b/stepmania/BackgroundTransitions/CrossFade.xml new file mode 100644 index 0000000000..9816a0e129 --- /dev/null +++ b/stepmania/BackgroundTransitions/CrossFade.xml @@ -0,0 +1,4 @@ + diff --git a/stepmania/BackgroundTransitions/SlideRight.xml b/stepmania/BackgroundTransitions/SlideRight.xml new file mode 100644 index 0000000000..d79870378c --- /dev/null +++ b/stepmania/BackgroundTransitions/SlideRight.xml @@ -0,0 +1,4 @@ + diff --git a/stepmania/src/Background.cpp b/stepmania/src/Background.cpp index 4d1c04fc90..0d1bf1899e 100644 --- a/stepmania/src/Background.cpp +++ b/stepmania/src/Background.cpp @@ -20,21 +20,22 @@ #include "ActorUtil.h" #include #include +#include "XmlFile.h" -const float FADE_SECONDS = 1.0f; +const CString BACKGROUND_EFFECTS_DIR = "BackgroundEffects/"; +const CString BACKGROUND_TRANSITIONS_DIR = "BackgroundTransitions/"; -ThemeMetric LEFT_EDGE ("Background","LeftEdge"); -ThemeMetric TOP_EDGE ("Background","TopEdge"); -ThemeMetric RIGHT_EDGE ("Background","RightEdge"); -ThemeMetric BOTTOM_EDGE ("Background","BottomEdge"); -#define RECT_BACKGROUND RectF (LEFT_EDGE,TOP_EDGE,RIGHT_EDGE,BOTTOM_EDGE) -ThemeMetric BLINK_DANGER_ALL ("Background","BlinkDangerAll"); -ThemeMetric DANGER_ALL_IS_OPAQUE ("Background","DangerAllIsOpaque"); +ThemeMetric LEFT_EDGE ("Background","LeftEdge"); +ThemeMetric TOP_EDGE ("Background","TopEdge"); +ThemeMetric RIGHT_EDGE ("Background","RightEdge"); +ThemeMetric BOTTOM_EDGE ("Background","BottomEdge"); +#define RECT_BACKGROUND RectF (LEFT_EDGE,TOP_EDGE,RIGHT_EDGE,BOTTOM_EDGE) +ThemeMetric BLINK_DANGER_ALL ("Background","BlinkDangerAll"); +ThemeMetric DANGER_ALL_IS_OPAQUE ("Background","DangerAllIsOpaque"); ThemeMetric BRIGHTNESS_FADE_COMMAND ("Background","BrightnessFadeCommand"); -ThemeMetric CLAMP_OUTPUT_PERCENT ("Background","ClampOutputPercent"); +ThemeMetric CLAMP_OUTPUT_PERCENT ("Background","ClampOutputPercent"); -static float g_fBackgroundCenterWidth = 40; -const CString STATIC_BACKGROUND = "static background"; +static float g_fBackgroundCenterWidth = 40; // What is this for? -Chris static RageColor GetBrightnessColor( float fBrightnessPercent ) { @@ -54,8 +55,9 @@ static RageColor GetBrightnessColor( float fBrightnessPercent ) Background::Background() { - m_pDancingCharacters = NULL; m_bInitted = false; + m_pDancingCharacters = NULL; + m_pSong = NULL; } Background::Layer::Layer() @@ -71,6 +73,33 @@ void Background::Init() if( m_bInitted ) return; m_bInitted = true; + STATIC_BACKGROUND_DEF = BackgroundDef(); + + // load transitions + { + ASSERT( m_mapNameToTransition.empty() ); + vector v; + GetDirListing( BACKGROUND_TRANSITIONS_DIR+"*.xml", v, false, true ); + FOREACH( CString, v, sPath ) + { + CString sThrowAway, sFilename; + splitpath( *sPath, sThrowAway, sFilename, sThrowAway ); + XNode xml; + xml.LoadFromFile( *sPath ); + ASSERT( xml.m_sName == "BackgroundTransition" ); + BackgroundTransition &bgt = m_mapNameToTransition[sFilename]; + + CString sCmdLeaves; + bool bSuccess = xml.GetAttrValue( "LeavesCommand", sCmdLeaves ); + ASSERT( bSuccess ); + bgt.cmdLeaves = apActorCommands(new ActorCommands(sCmdLeaves) ); + + CString sCmdRoot; + bSuccess = xml.GetAttrValue( "RootCommand", sCmdRoot ); + ASSERT( bSuccess ); + bgt.cmdRoot = apActorCommands(new ActorCommands(sCmdRoot) ); + } + } m_DangerAll.LoadFromAniDir( THEME->GetPathB("ScreenGameplay","danger all") ); FOREACH_PlayerNumber( p ) @@ -127,7 +156,7 @@ void Background::Unload() void Background::Layer::Unload() { - for( map::iterator iter = m_BGAnimations.begin(); + for( map::iterator iter = m_BGAnimations.begin(); iter != m_BGAnimations.end(); iter++ ) delete iter->second; @@ -173,85 +202,108 @@ Actor *MakeMovie( const CString &sMoviePath ) return pSprite; } -Actor *Background::Layer::CreateSongBGA( const Song *pSong, CString sBGName ) const +bool Background::Layer::CreateBackground( const Song *pSong, const BackgroundDef &bd ) { - BGAnimation *pTempBGA; + // Resolve the background names + vector vsResolvedFile; + vsResolvedFile.push_back( bd.m_sFile1 ); + vsResolvedFile.push_back( bd.m_sFile2 ); - // Using aniseg.m_sBGName, search for the corresponding animation. - // Look in this order: movies in song dir, BGAnims in song dir - // movies in RandomMovies dir, BGAnims in BGAnimsDir. - CStringArray asFiles; - - // Look for BGAnims in the song dir - GetDirListing( pSong->GetSongDir()+sBGName, asFiles, true, true ); - if( !asFiles.empty() ) + for( unsigned i=0; iSetGlobal( ssprintf("File%d",i+1), CString() ); - pTempBGA = new BGAnimation; - pTempBGA->LoadFromAniDir( asFiles[0], false ); - return pTempBGA; - } - // Look for BG movies or static graphics in the song dir - GetDirListing( pSong->GetSongDir()+sBGName, asFiles, false, true ); - if( !asFiles.empty() ) - { - const CString sExt = GetExtension( asFiles[0]) ; - if( sExt.CompareNoCase("avi")==0 || - sExt.CompareNoCase("mpg")==0 || - sExt.CompareNoCase("mpeg")==0 ) + CString &sResolvedFile = vsResolvedFile[0]; + if( sResolvedFile.empty() ) { - return MakeMovie( asFiles[0] ); + if( i == 0 ) + return false; + else + continue; + } + + // Look for vsFileToResolve[i] in: + // - song's dir + // - RandomMovies dir + // - BGAnimations dir. + CStringArray asMatches; + + // Look for BGAnims in the song dir + GetDirListing( sResolvedFile+"*", asMatches, false, true ); + if( asMatches.empty() ) GetDirListing( pSong->GetSongDir()+sResolvedFile+"*", asMatches, false, true ); + if( asMatches.empty() ) GetDirListing( RANDOMMOVIES_DIR+sResolvedFile+"*", asMatches, false, true ); + if( asMatches.empty() ) GetDirListing( BG_ANIMS_DIR+sResolvedFile+"*", asMatches, false, true ); + + if( !asMatches.empty() ) + { + sResolvedFile = asMatches[0]; } else { - Sprite *pSprite = new Sprite; - pSprite->LoadBG( asFiles[0] ); - pSprite->StretchTo( FullScreenRectF ); - return pSprite; + // If the main background file is missing. We failed. + if( i == 0 ) + return false; + else + sResolvedFile = ThemeManager::GetBlankGraphicPath(); + } + + LUA->SetGlobal( ssprintf("File%d",i+1), sResolvedFile ); + } + + CString sEffect = bd.m_sEffect; + if( sEffect.empty() ) + { + FileType ft = ActorUtil::GetFileType(vsResolvedFile[0]); + switch( ft ) + { + case FT_Bitmap: + case FT_Sprite: + case FT_Movie: + sEffect = StandardBackgroundEffectToString( SBE_Stretch ); + break; + case FT_Actor: + case FT_Directory: + case FT_Xml: + case FT_Model: + sEffect = StandardBackgroundEffectToString( SBE_Centered ); + break; + default: + ASSERT(0); } } - // Look for movies in the RandomMovies dir - GetDirListing( RANDOMMOVIES_DIR+sBGName, asFiles, false, true ); - if( !asFiles.empty() ) - return MakeMovie( asFiles[0] ); + ASSERT( !sEffect.empty() ); - // Look for BGAnims in the BGAnims dir - GetDirListing( BG_ANIMS_DIR+sBGName, asFiles, true, true ); - if( !asFiles.empty() ) - { - Actor *pActor = ActorUtil::MakeActor( asFiles[0] ); - ASSERT( pActor ); - return pActor; - } + vector v; + GetDirListing( BACKGROUND_EFFECTS_DIR + sEffect+"*", v, false, true ); + ASSERT( v.size()==1 ); + CString sEffectFile = v[0]; - // Look for BGAnims in the BGAnims dir - GetDirListing( VISUALIZATIONS_DIR+sBGName, asFiles, false, true ); - if( !asFiles.empty() ) - return MakeVisualization( asFiles[0] ); + Actor *pActor = ActorUtil::MakeActor( sEffectFile ); + ASSERT( pActor ); + m_BGAnimations[bd] = pActor; - // There is no background by this name. - return NULL; + for( unsigned i=0; iSetGlobal( ssprintf("File%d",i+1), CString() ); + + return true; } -CString Background::Layer::CreateRandomBGA( const Song *pSong, CString sPreferredSubDir ) +BackgroundDef Background::Layer::CreateRandomBGA( const Song *pSong, CString sPreferredSubDir ) { if( sPreferredSubDir.Right(1) != "/" ) sPreferredSubDir += '/'; if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_OFF ) - return ""; + { + return BackgroundDef(); + } /* If we already have enough random BGAs loaded, use them round-robin. */ if( (int)m_RandomBGAnimations.size() >= PREFSMAN->m_iNumBackgrounds ) { /* XXX: every time we fully loop, shuffle, so we don't play the same sequence * over and over; and nudge the shuffle so the next one won't be a repeat */ - const CString first = m_RandomBGAnimations.front(); + BackgroundDef first = m_RandomBGAnimations.front(); m_RandomBGAnimations.push_back( m_RandomBGAnimations.front() ); m_RandomBGAnimations.pop_front(); return first; @@ -270,12 +322,6 @@ CString Background::Layer::CreateRandomBGA( const Song *pSong, CString sPreferre GetDirListing( BG_ANIMS_DIR + sPreferredSubDir + "*", arrayPaths, true, true ); break; - case PrefsManager::BGMODE_MOVIEVIS: - GetDirListing( VISUALIZATIONS_DIR + sPreferredSubDir + "*.avi", arrayPaths, false, true ); - GetDirListing( VISUALIZATIONS_DIR + sPreferredSubDir + "*.mpg", arrayPaths, false, true ); - GetDirListing( VISUALIZATIONS_DIR + sPreferredSubDir + "*.mpeg", arrayPaths, false, true ); - break; - case PrefsManager::BGMODE_RANDOMMOVIES: GetDirListing( RANDOMMOVIES_DIR + sPreferredSubDir + "*.avi", arrayPaths, false, true ); GetDirListing( RANDOMMOVIES_DIR + sPreferredSubDir + "*.mpg", arrayPaths, false, true ); @@ -296,61 +342,61 @@ CString Background::Layer::CreateRandomBGA( const Song *pSong, CString sPreferre } if( arrayPaths.empty() ) - return ""; + return BackgroundDef(); random_shuffle( arrayPaths.begin(), arrayPaths.end() ); - /* Find the first file in arrayPaths we havn't already loaded. */ - CString file; + /* Find the first BackgroundDef in arrayPaths we havn't already loaded. */ + BackgroundDef bd; { - set loaded; - unsigned i; - for( i = 0; i < m_RandomBGAnimations.size(); ++i ) + // copy into set for easy lookup + set loaded; + for( unsigned i = 0; i < m_RandomBGAnimations.size(); ++i ) loaded.insert( m_RandomBGAnimations[i] ); - i = 0; - while( i < arrayPaths.size() && loaded.find( arrayPaths[i] ) != loaded.end() ) - ++i; - if( i == arrayPaths.size() ) - return ""; + bool bFound = false; + FOREACH_CONST( CString, arrayPaths, p ) + { + FOREACHD_CONST( BackgroundDef, m_RandomBGAnimations, b ) + { + if( b->m_sFile1 == *p ) + { + bd.m_sFile1 = *p; + bFound = true; + break; + } + } + if( bFound ) + break; + } - file = arrayPaths[i]; + if( !bFound ) + return BackgroundDef(); } - Actor *ret; - switch( PREFSMAN->m_BackgroundMode ) - { - case PrefsManager::BGMODE_ANIMATIONS: - { - BGAnimation *p = new BGAnimation; - p->LoadFromAniDir( file ); - ret = p; - break; - } - case PrefsManager::BGMODE_MOVIEVIS: ret = MakeVisualization( file ); break; - case PrefsManager::BGMODE_RANDOMMOVIES: ret = MakeMovie( file ); break; - default: FAIL_M( ssprintf("%i", (int) PREFSMAN->m_BackgroundMode) ); - } - - m_BGAnimations[file] = ret; - m_RandomBGAnimations.push_back( file ); - return file; + bool bSuccess = CreateBackground( pSong, bd ); + ASSERT( bSuccess ); // we fed it valid files, so this shouldn't fail + m_RandomBGAnimations.push_back( bd ); + return bd; } -void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const TimingData &timing, CString sPreferredSubDir ) +void Background::LoadFromRandom( float fFirstBeat, float fLastBeat ) { + const TimingData &timing = m_pSong->m_Timing; + const CString &sPreferredSubDir = m_pSong->m_sGroupName; + // change BG every 4 bars for( float f=fFirstBeat; fm_BackgroundMode==PrefsManager::BGMODE_RANDOMMOVIES || - // PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_MOVIEVIS; - - CString sBGName = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir ); - if( sBGName != "" ) - m_Layer[0].m_aBGChanges.push_back( BackgroundChange(f,sBGName,1.f,bFade) ); + // Don't fade. It causes frame rate dip, especially on slower machines. + BackgroundDef bd = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir ); + if( !bd.IsEmpty() ) + { + BackgroundChange change; + (BackgroundDef&)change = bd; + change.m_fStartBeat = f; + m_Layer[0].m_aBGChanges.push_back( change ); + } } // change BG every BPM change that is at the beginning of a measure @@ -366,9 +412,14 @@ void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const Timing if( bpmseg.m_iStartIndex < iStartIndex || bpmseg.m_iStartIndex > iEndIndex ) continue; // skip - CString sBGName = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir ); - if( sBGName != "" ) - m_Layer[0].m_aBGChanges.push_back( BackgroundChange(NoteRowToBeat(bpmseg.m_iStartIndex),sBGName) ); + BackgroundDef bd = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir ); + if( !bd.IsEmpty() ) + { + BackgroundChange change; + (BackgroundDef&)change = bd; + change.m_fStartBeat = NoteRowToBeat(bpmseg.m_iStartIndex); + m_Layer[0].m_aBGChanges.push_back( change ); + } } } @@ -380,6 +431,8 @@ void Background::LoadFromSong( const Song* pSong ) m_pSong = pSong; + STATIC_BACKGROUND_DEF.m_sFile1 = m_pSong->HasBackground() ? m_pSong->GetBackgroundPath() : THEME->GetPathG("Common","fallback background"); + if( PREFSMAN->m_fBGBrightness == 0.0f ) return; @@ -405,22 +458,22 @@ void Background::LoadFromSong( const Song* pSong ) FOREACH_CONST( BackgroundChange, pSong->m_BackgroundChanges[i], bgc ) { BackgroundChange change = *bgc; - CString &sBGName = change.m_sBGName; + BackgroundDef &bd = change; - bool bIsAlreadyLoaded = layer.m_BGAnimations.find(sBGName) != layer.m_BGAnimations.end(); + bool bIsAlreadyLoaded = layer.m_BGAnimations.find(bd) != layer.m_BGAnimations.end(); - if( sBGName.CompareNoCase("-random-")!=0 && !bIsAlreadyLoaded ) + if( bd.m_sFile1.CompareNoCase(RANDOM_BACKGROUND_FILE)!=0 && !bIsAlreadyLoaded ) { - Actor *pTempBGA = layer.CreateSongBGA( m_pSong, sBGName ); - if( pTempBGA ) + if( layer.CreateBackground( m_pSong, bd ) ) { - layer.m_BGAnimations[sBGName] = pTempBGA; + ; // do nothing. Create was successful. } - else // the background was not found. Use a random one instead + else { - sBGName = layer.CreateRandomBGA( pSong, pSong->m_sGroupName ); - if( sBGName == "" ) - sBGName = STATIC_BACKGROUND; + // The background was not found. Try to use a random one instead. + bd = layer.CreateRandomBGA( pSong, pSong->m_sGroupName ); + if( bd.IsEmpty() ) + bd = STATIC_BACKGROUND_DEF; } } @@ -432,10 +485,13 @@ void Background::LoadFromSong( const Song* pSong ) { Layer &layer = m_Layer[0]; - LoadFromRandom( pSong->m_fFirstBeat, pSong->m_fLastBeat, pSong->m_Timing, pSong->m_sGroupName ); + LoadFromRandom( pSong->m_fFirstBeat, pSong->m_fLastBeat ); // end showing the static song background - layer.m_aBGChanges.push_back( BackgroundChange(pSong->m_fLastBeat,STATIC_BACKGROUND) ); + BackgroundChange change; + (BackgroundDef&)change = STATIC_BACKGROUND_DEF; + change.m_fStartBeat = pSong->m_fLastBeat; + layer.m_aBGChanges.push_back( change ); } @@ -453,21 +509,25 @@ void Background::LoadFromSong( const Song* pSong ) /* If the first BGAnimation isn't negative, add a lead-in image showing the song * background. */ if( mainlayer.m_aBGChanges.empty() || mainlayer.m_aBGChanges.front().m_fStartBeat >= 0 ) - mainlayer.m_aBGChanges.insert( mainlayer.m_aBGChanges.begin(), BackgroundChange(-10000,STATIC_BACKGROUND) ); + { + BackgroundChange change; + (BackgroundDef&)change = STATIC_BACKGROUND_DEF; + change.m_fStartBeat = -10000; + mainlayer.m_aBGChanges.insert( mainlayer.m_aBGChanges.begin(), change ); + } // If any BGChanges use the background image, load it. bool bStaticBackgroundUsed = false; - for( unsigned i=0; iHasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathG("Common","fallback background"); - Sprite* pSprite = new Sprite; - pSprite->LoadBG( sSongBGPath ); - pSprite->StretchTo( FullScreenRectF ); - mainlayer.m_BGAnimations[STATIC_BACKGROUND] = pSprite; + bool bSuccess = mainlayer.CreateBackground( m_pSong, STATIC_BACKGROUND_DEF ); + ASSERT( bSuccess ); } @@ -475,7 +535,7 @@ void Background::LoadFromSong( const Song* pSong ) for( unsigned i=0; im_Timing, pSong->m_sGroupName ); + LoadFromRandom( fStartBeat, fLastBeat ); } // At this point, we shouldn't have any BGChanges to "". "" is an invalid name. for( unsigned i=0; i::iterator it; - for( it = mainlayer.m_BGAnimations.begin(); it != mainlayer.m_BGAnimations.end(); ++it ) + FOREACHM( BackgroundDef, Actor*, mainlayer.m_BGAnimations, it ) { Actor *pBGA = it->second; @@ -558,7 +617,7 @@ int Background::Layer::FindBGSegmentForBeat( float fBeat ) const } /* If the BG segment has changed, move focus to it. Send Update() calls. */ -void Background::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime ) +void Background::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime, const map &mapNameToTransition ) { ASSERT( fCurrentTime != GameState::MUSIC_SECONDS_INVALID ); @@ -575,6 +634,7 @@ void Background::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSe // Find the BGSegment we're in const int i = FindBGSegmentForBeat( fBeat ); + float fDeltaTime = fCurrentTime - fLastMusicSeconds; if( i != -1 && i != m_iCurBGChangeIndex ) // we're changing backgrounds { LOG->Trace( "old bga %d -> new bga %d, %f, %f", m_iCurBGChangeIndex, i, m_aBGChanges[i].m_fStartBeat, fBeat ); @@ -583,51 +643,65 @@ void Background::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSe const BackgroundChange& change = m_aBGChanges[i]; - Actor *pOld = m_pCurrentBGA; + m_pFadingBGA = m_pCurrentBGA; - if( change.m_bFadeLast ) - m_pFadingBGA = m_pCurrentBGA; - else + m_pCurrentBGA = m_BGAnimations[ (BackgroundDef)change ]; + + if( m_pFadingBGA == m_pCurrentBGA ) + { m_pFadingBGA = NULL; - - m_pCurrentBGA = m_BGAnimations[ change.m_sBGName ]; - - if( pOld ) - { - pOld->LoseFocus(); - pOld->PlayCommand( "LoseFocus" ); + LOG->Trace( "bg didn't actually change. Ignoring." ); + m_fSecsLeftInFade = 0; } - if( m_pCurrentBGA ) + else { + if( m_pFadingBGA ) + { + m_pFadingBGA->LoseFocus(); + m_pFadingBGA->PlayCommand( "LoseFocus" ); + + if( !change.m_sTransition.empty() ) + { + map::const_iterator iter = mapNameToTransition.find( change.m_sTransition ); + ASSERT( iter != mapNameToTransition.end() ); + const BackgroundTransition &bt = iter->second; + m_pFadingBGA->RunCommandsOnLeaves( *bt.cmdLeaves ); + m_pFadingBGA->RunCommands( *bt.cmdRoot ); + } + } + + m_pCurrentBGA->Reset(); m_pCurrentBGA->GainFocus( change.m_fRate, change.m_bRewindMovie, change.m_bLoop ); m_pCurrentBGA->PlayCommand( "On" ); m_pCurrentBGA->PlayCommand( "GainFocus" ); + + m_fSecsLeftInFade = m_pFadingBGA ? m_pFadingBGA->GetTweenTimeLeft() : 0; + + /* How much time of this BGA have we skipped? (This happens with SetSeconds.) */ + const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat ); + + /* This is affected by the music rate. */ + fDeltaTime = fCurrentTime - fStartSecond; } - - m_fSecsLeftInFade = m_pFadingBGA!=NULL ? FADE_SECONDS : 0; - - /* How much time of this BGA have we skipped? (This happens with SetSeconds.) */ - const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat ); - - /* This is affected by the music rate. */ - float fDeltaTime = fCurrentTime - fStartSecond; - fDeltaTime /= fRate; - if( m_pCurrentBGA ) - m_pCurrentBGA->Update( max( fDeltaTime, 0 ) ); - } - else // we're not changing backgrounds - { - /* This is affected by the music rate. */ - float fDeltaTime = fCurrentTime - fLastMusicSeconds; - fDeltaTime /= fRate; - if( m_pCurrentBGA ) - m_pCurrentBGA->Update( max( fDeltaTime, 0 ) ); } - float fDeltaTime = fCurrentTime - fLastMusicSeconds; - fDeltaTime /= fRate; if( m_pFadingBGA ) - m_pFadingBGA->Update( max( fCurrentTime - fLastMusicSeconds, 0 ) ); + { + m_fSecsLeftInFade -= fDeltaTime; + if( m_fSecsLeftInFade < 0 ) + { + m_fSecsLeftInFade = 0; + m_pFadingBGA = NULL; + } + } + + /* This is affected by the music rate. */ + float fDeltaTimeMusicRate = max( fDeltaTime / fRate, 0 ); + + if( m_pCurrentBGA ) + m_pCurrentBGA->Update( fDeltaTimeMusicRate ); + if( m_pFadingBGA ) + m_pFadingBGA->Update( fDeltaTimeMusicRate ); } void Background::Update( float fDeltaTime ) @@ -658,21 +732,7 @@ void Background::Update( float fDeltaTime ) for( int i=0; im_fMusicSeconds ); - - if( layer.m_pFadingBGA ) - { - layer.m_pFadingBGA->Update( fDeltaTime ); - layer.m_fSecsLeftInFade -= fDeltaTime; - float fPercentOpaque = layer.m_fSecsLeftInFade / FADE_SECONDS; - layer.m_pFadingBGA->SetDiffuse( RageColor(1,1,1,fPercentOpaque) ); - if( fPercentOpaque <= 0 ) - { - /* Reset its diffuse color, in case we reuse it. */ - layer.m_pFadingBGA->SetDiffuse( RageColor(1,1,1,1) ); - layer.m_pFadingBGA = NULL; - } - } + layer.UpdateCurBGChange( m_pSong, m_fLastMusicSeconds, GAMESTATE->m_fMusicSeconds, m_mapNameToTransition ); } m_fLastMusicSeconds = GAMESTATE->m_fMusicSeconds; } diff --git a/stepmania/src/Background.h b/stepmania/src/Background.h index a1018a7bd0..ba466f0cb2 100644 --- a/stepmania/src/Background.h +++ b/stepmania/src/Background.h @@ -28,6 +28,12 @@ private: Quad m_quadBGBrightnessFade; }; +struct BackgroundTransition +{ + apActorCommands cmdLeaves; + apActorCommands cmdRoot; +}; + class Background : public ActorFrame { public: @@ -47,27 +53,30 @@ public: DancingCharacters* GetDancingCharacters() { return m_pDancingCharacters; }; protected: - const Song *m_pSong; - void LoadFromRandom( float fFirstBeat, float fLastBeat, const TimingData &timing, CString sPreferredSubDir ); - - bool IsDangerAllVisible(); - bool m_bInitted; DancingCharacters* m_pDancingCharacters; - + const Song *m_pSong; + map m_mapNameToTransition; + + void LoadFromRandom( float fFirstBeat, float fLastBeat ); + bool IsDangerAllVisible(); + class Layer { public: Layer(); void Unload(); - Actor *CreateSongBGA( const Song *pSong, CString sBGName ) const; - CString CreateRandomBGA( const Song *pSong, CString sPreferredSubDir ); - int FindBGSegmentForBeat( float fBeat ) const; - void UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime ); + // return true if created and added to m_BGAnimations + bool CreateBackground( const Song *pSong, const BackgroundDef &bd ); + // return def of the background that was created and added to m_BGAnimations. calls CreateBackground + BackgroundDef CreateRandomBGA( const Song *pSong, CString sPreferredSubDir ); - map m_BGAnimations; - deque m_RandomBGAnimations; + int FindBGSegmentForBeat( float fBeat ) const; + void UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime, const map &mapNameToTransition ); + + map m_BGAnimations; + deque m_RandomBGAnimations; vector m_aBGChanges; int m_iCurBGChangeIndex; Actor *m_pCurrentBGA; @@ -87,6 +96,8 @@ protected: Quad m_quadBorderLeft, m_quadBorderTop, m_quadBorderRight, m_quadBorderBottom; BrightnessOverlay m_Brightness; + + BackgroundDef STATIC_BACKGROUND_DEF; }; diff --git a/stepmania/src/Foreground.cpp b/stepmania/src/Foreground.cpp index fe08e6f6f6..ab54ba108a 100644 --- a/stepmania/src/Foreground.cpp +++ b/stepmania/src/Foreground.cpp @@ -32,7 +32,7 @@ void Foreground::LoadFromSong( const Song *pSong ) for( unsigned i=0; im_ForegroundChanges.size(); i++ ) { const BackgroundChange &change = pSong->m_ForegroundChanges[i]; - CString sBGName = change.m_sBGName; + CString sBGName = change.m_sFile1; LoadedBGA bga; bga.m_bga = ActorUtil::MakeActor( pSong->GetSongDir() + sBGName ); diff --git a/stepmania/src/GameConstantsAndTypes.cpp b/stepmania/src/GameConstantsAndTypes.cpp index 35ad06a41e..5bbc61c9bf 100644 --- a/stepmania/src/GameConstantsAndTypes.cpp +++ b/stepmania/src/GameConstantsAndTypes.cpp @@ -366,6 +366,19 @@ static const CString StageNames[] = { XToString( Stage, NUM_STAGES ); +static const CString StandardBackgroundEffectNames[] = { + "Centered", + "Stretch", +}; +XToString( StandardBackgroundEffect, NUM_StandardBackgroundEffect ); + +static const CString StandardBackgroundTransitionNames[] = { + "None", + "CrossFade", +}; +XToString( StandardBackgroundTransition, NUM_StandardBackgroundTransition ); + + /* * (c) 2001-2004 Chris Danford diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index 5a82957a57..9c78ee9711 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -419,6 +419,89 @@ enum Stage const CString& StageToString( Stage s ); +enum StandardBackgroundEffect +{ + SBE_Centered, + SBE_Stretch, + NUM_StandardBackgroundEffect +}; +const CString& StandardBackgroundEffectToString( StandardBackgroundEffect sbe ); + +const CString RANDOM_BACKGROUND_FILE = "-random-"; +struct BackgroundDef +{ + BackgroundDef() + { + } + bool operator<( const BackgroundDef &other ) const + { +#define COMPARE(x) if( x < other.x ) return true; else if( x > other.x ) return false; + COMPARE( m_sEffect ); + COMPARE( m_sFile1 ); + COMPARE( m_sFile2 ); +#undef COMPARE + return false; + } + bool operator==( const BackgroundDef &other ) const + { + return + m_sEffect == other.m_sEffect && + m_sFile1 == other.m_sFile1 && + m_sFile2 == other.m_sFile2; + } + bool IsEmpty() { return m_sFile1.empty() && m_sFile2.empty(); } + CString m_sEffect; // "" == automatically choose + CString m_sFile1; // must not be "" + CString m_sFile2; // may be "" +}; + +enum StandardBackgroundTransition +{ + SBT_None, + SBT_CrossFade, + NUM_StandardBackgroundTransition +}; +const CString& StandardBackgroundTransitionToString( StandardBackgroundTransition sbt ); + +struct BackgroundChange : public BackgroundDef +{ + BackgroundChange() + { + m_fStartBeat=-1; + m_fRate=1; + m_bRewindMovie=false; + m_bLoop=true; + } + BackgroundChange( + float s, + CString f1, + CString f2=CString(), + float r=1.f, + bool m=false, + bool l=true, + CString e=StandardBackgroundEffectToString(SBE_Centered), + CString t=CString() + ) + { + m_fStartBeat=s; + m_sFile1=f1; + m_sFile2=f2; + m_fRate=r; + m_bRewindMovie=m; + m_bLoop=l; + m_sEffect=e; + m_sTransition=t; + } + float m_fStartBeat; + float m_fRate; + bool m_bRewindMovie; + bool m_bLoop; + CString m_sTransition; +}; + +void SortBackgroundChangesArray( vector &arrayBackgroundChanges ); + + #endif /* diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 529ef7aabe..a4c57dcbe0 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -26,6 +26,7 @@ NoteField::NoteField() m_textMeasureNumber.LoadFromFont( THEME->GetPathF("Common","normal") ); m_textMeasureNumber.SetZoom( 1.0f ); m_textMeasureNumber.SetShadowLength( 2 ); + m_textMeasureNumber.SetWrapWidthPixels( 300 ); m_rectMarkerBar.SetEffectDiffuseShift( 2, RageColor(1,1,1,0.5f), RageColor(0.5f,0.5f,0.5f,0.5f) ); @@ -540,14 +541,15 @@ void NoteField::DrawPrimitives() aBackgroundChanges[i].m_fStartBeat <= fLastBeatToDraw ) { const BackgroundChange& change = aBackgroundChanges[i]; - CString sChangeText = ssprintf("%s%s\n%.0f%%%s%s%s", - ((b!=0) ? ssprintf("%d:",b) : CString()).c_str(), - change.m_sBGName.c_str(), - change.m_fRate*100, - change.m_bFadeLast ? " Fade" : "", + CString sChangeText = ssprintf("%s%s%s%s%s%s%s", + ((b!=0) ? ssprintf("%d: ",b) : CString()).c_str(), + (!change.m_sFile1.empty() ? " "+change.m_sFile1 : CString()).c_str(), + (!change.m_sFile2.empty() ? " "+change.m_sFile2 : CString()).c_str(), + ((change.m_fRate!=1.0f) ? ssprintf("%.2f%%",change.m_fRate*100) : CString()).c_str(), change.m_bRewindMovie ? " Rewind" : "", - change.m_bLoop ? " Loop" : "" ); - + change.m_bLoop ? " Loop" : "" , + (!change.m_sTransition.empty() ? " "+change.m_sTransition : CString()).c_str() + ); if( IS_ON_SCREEN(change.m_fStartBeat) ) DrawBGChangeText( change.m_fStartBeat, sChangeText ); } diff --git a/stepmania/src/NotesLoaderSM.cpp b/stepmania/src/NotesLoaderSM.cpp index 35de229810..ecfb9e6199 100644 --- a/stepmania/src/NotesLoaderSM.cpp +++ b/stepmania/src/NotesLoaderSM.cpp @@ -161,19 +161,26 @@ bool LoadFromBGChangesString( BackgroundChange &change, const CString &sBGChange CStringArray aBGChangeValues; split( sBGChangeExpression, "=", aBGChangeValues ); - switch( aBGChangeValues.size() ) + if( aBGChangeValues.size() >= 6 ) { - case 6: change.m_fRate = strtof( aBGChangeValues[2], NULL ); - change.m_bFadeLast = atoi( aBGChangeValues[3] ) != 0; + change.m_sTransition = (atoi( aBGChangeValues[3] ) != 0) ? "CrossFade" : ""; change.m_bRewindMovie = atoi( aBGChangeValues[4] ) != 0; change.m_bLoop = atoi( aBGChangeValues[5] ) != 0; - // fall through - case 2: + } + if( aBGChangeValues.size() >= 8 ) + { + change.m_sFile1 = aBGChangeValues[6]; + change.m_sTransition = aBGChangeValues[7]; + } + if( aBGChangeValues.size() >= 2 ) + { change.m_fStartBeat = strtof( aBGChangeValues[0], NULL ); - change.m_sBGName = aBGChangeValues[1]; + change.m_sFile1 = aBGChangeValues[1]; return true; - default: + } + else + { LOG->Warn("Invalid #BGCHANGES value \"%s\" was ignored", sBGChangeExpression.c_str()); return false; } @@ -543,7 +550,7 @@ void SMLoader::TidyUpData( Song &song, bool cache ) for( unsigned i = 0; !bHasNoSongBgTag && i < bg.size(); ++i ) { - if( !bg[i].m_sBGName.CompareNoCase("-nosongbg-") ) + if( !bg[i].m_sFile1.CompareNoCase("-nosongbg-") ) { bg.erase( bg.begin()+i ); bHasNoSongBgTag = true; @@ -564,7 +571,7 @@ void SMLoader::TidyUpData( Song &song, bool cache ) break; /* If the last BGA is already the song BGA, don't add a duplicate. */ - if( !bg.empty() && !bg.back().m_sBGName.CompareNoCase(song.m_sBackgroundFile) ) + if( !bg.empty() && !bg.back().m_sFile1.CompareNoCase(song.m_sBackgroundFile) ) break; if( !IsAFile( song.GetBackgroundPath() ) ) diff --git a/stepmania/src/NotesWriterSM.cpp b/stepmania/src/NotesWriterSM.cpp index 666e023fff..940eece52d 100644 --- a/stepmania/src/NotesWriterSM.cpp +++ b/stepmania/src/NotesWriterSM.cpp @@ -12,6 +12,11 @@ #include #include "Foreach.h" +static CString BackgroundChangeToString( const BackgroundChange &bgc ) +{ + return ssprintf( "%.3f=%s=%.3f=%d=%d=%d=%s,", bgc.m_fStartBeat, bgc.m_sFile1.c_str(), bgc.m_fRate, bgc.m_sTransition=="CrossFade", bgc.m_bRewindMovie, bgc.m_bLoop, bgc.m_sFile2.c_str(), bgc.m_sTransition ); +} + void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out ) { f.PutLine( ssprintf( "#TITLE:%s;", out.m_sMainTitle.c_str() ) ); @@ -92,7 +97,7 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out ) f.Write( ssprintf("#BGCHANGES%d:", b) ); FOREACH_CONST( BackgroundChange, out.m_BackgroundChanges[b], bgc ) - f.PutLine( ssprintf( "%.3f=%s=%.3f=%d=%d=%d,", bgc->m_fStartBeat, bgc->m_sBGName.c_str(), bgc->m_fRate, bgc->m_bFadeLast, bgc->m_bRewindMovie, bgc->m_bLoop ) ); + f.PutLine( BackgroundChangeToString(*bgc) ); /* If there's an animation plan at all, add a dummy "-nosongbg-" tag to indicate that * this file doesn't want a song BG entry added at the end. See SMLoader::TidyUpData. @@ -106,13 +111,9 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out ) if( out.m_ForegroundChanges.size() ) { f.Write( "#FGCHANGES:" ); - for( unsigned i=0; i &iAns // // m_pSong->GetSongDir() has trailing slash - g_BackgroundChange.rows[add_song_bganimation].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"*", g_BackgroundChange.rows[add_song_bganimation].choices, true ); + g_BackgroundChange.rows[file1_song_bganimation].choices.clear(); + GetDirListing( m_pSong->GetSongDir()+"*", g_BackgroundChange.rows[file1_song_bganimation].choices, true ); - g_BackgroundChange.rows[add_song_movie].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"*.avi", g_BackgroundChange.rows[add_song_movie].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"*.mpg", g_BackgroundChange.rows[add_song_movie].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"*.mpeg", g_BackgroundChange.rows[add_song_movie].choices, false ); + g_BackgroundChange.rows[file1_song_movie].choices.clear(); + GetDirListing( m_pSong->GetSongDir()+"*.avi", g_BackgroundChange.rows[file1_song_movie].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.mpg", g_BackgroundChange.rows[file1_song_movie].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.mpeg", g_BackgroundChange.rows[file1_song_movie].choices, false ); - g_BackgroundChange.rows[add_song_still].choices.clear(); - GetDirListing( m_pSong->GetSongDir()+"*.png", g_BackgroundChange.rows[add_song_still].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"*.jpg", g_BackgroundChange.rows[add_song_still].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"*.gif", g_BackgroundChange.rows[add_song_still].choices, false ); - GetDirListing( m_pSong->GetSongDir()+"*.bmp", g_BackgroundChange.rows[add_song_still].choices, false ); + g_BackgroundChange.rows[file1_song_still].choices.clear(); + GetDirListing( m_pSong->GetSongDir()+"*.png", g_BackgroundChange.rows[file1_song_still].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.jpg", g_BackgroundChange.rows[file1_song_still].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.gif", g_BackgroundChange.rows[file1_song_still].choices, false ); + GetDirListing( m_pSong->GetSongDir()+"*.bmp", g_BackgroundChange.rows[file1_song_still].choices, false ); - g_BackgroundChange.rows[add_global_random_movie].choices.clear(); - GetDirListing( RANDOMMOVIES_DIR+"*.avi", g_BackgroundChange.rows[add_global_random_movie].choices, false ); - GetDirListing( RANDOMMOVIES_DIR+"*.mpg", g_BackgroundChange.rows[add_global_random_movie].choices, false ); - GetDirListing( RANDOMMOVIES_DIR+"*.mpeg", g_BackgroundChange.rows[add_global_random_movie].choices, false ); + g_BackgroundChange.rows[file1_global_random_movie].choices.clear(); + GetDirListing( RANDOMMOVIES_DIR+"*.avi", g_BackgroundChange.rows[file1_global_random_movie].choices, false ); + GetDirListing( RANDOMMOVIES_DIR+"*.mpg", g_BackgroundChange.rows[file1_global_random_movie].choices, false ); + GetDirListing( RANDOMMOVIES_DIR+"*.mpeg", g_BackgroundChange.rows[file1_global_random_movie].choices, false ); vector vSubDirs; GetDirListing( RANDOMMOVIES_DIR+"*", vSubDirs, true ); @@ -2061,17 +2069,20 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns GetDirListing( RANDOMMOVIES_DIR+sSubDir+"/*.mpeg", vsMovies, false ); FOREACH_CONST( CString, vsMovies, m ) - g_BackgroundChange.rows[add_global_random_movie].choices.push_back( sSubDir +"/"+ *m ); + g_BackgroundChange.rows[file1_global_random_movie].choices.push_back( sSubDir +"/"+ *m ); } - g_BackgroundChange.rows[add_global_bganimation].choices.clear(); - GetDirListing( BG_ANIMS_DIR+"*", g_BackgroundChange.rows[add_global_bganimation].choices, true ); + g_BackgroundChange.rows[file1_global_bganimation].choices.clear(); + GetDirListing( BG_ANIMS_DIR+"*", g_BackgroundChange.rows[file1_global_bganimation].choices, true ); - g_BackgroundChange.rows[add_global_visualization].choices.clear(); - GetDirListing( VISUALIZATIONS_DIR+"*.avi", g_BackgroundChange.rows[add_global_visualization].choices, false ); - GetDirListing( VISUALIZATIONS_DIR+"*.mpg", g_BackgroundChange.rows[add_global_visualization].choices, false ); - GetDirListing( VISUALIZATIONS_DIR+"*.mpeg", g_BackgroundChange.rows[add_global_visualization].choices, false ); + g_BackgroundChange.rows[file2_type].choices = g_BackgroundChange.rows[file1_type].choices; + g_BackgroundChange.rows[file2_song_bganimation].choices = g_BackgroundChange.rows[file1_song_bganimation].choices; + g_BackgroundChange.rows[file2_song_movie].choices = g_BackgroundChange.rows[file1_song_movie].choices; + g_BackgroundChange.rows[file2_song_still].choices = g_BackgroundChange.rows[file1_song_still].choices; + g_BackgroundChange.rows[file2_global_random_movie].choices = g_BackgroundChange.rows[file1_global_random_movie].choices; + g_BackgroundChange.rows[file2_global_bganimation].choices = g_BackgroundChange.rows[file1_global_bganimation].choices; + // // Fill in line's enabled/disabled @@ -2092,28 +2103,39 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns } } - g_BackgroundChange.rows[add_random].bEnabled = true; - g_BackgroundChange.rows[add_song_bganimation].bEnabled = g_BackgroundChange.rows[add_song_bganimation].choices.size() > 0; - g_BackgroundChange.rows[add_song_movie].bEnabled = g_BackgroundChange.rows[add_song_movie].choices.size() > 0; - g_BackgroundChange.rows[add_song_still].bEnabled = g_BackgroundChange.rows[add_song_still].choices.size() > 0; - g_BackgroundChange.rows[add_global_random_movie].bEnabled = g_BackgroundChange.rows[add_global_random_movie].choices.size() > 0; - g_BackgroundChange.rows[add_global_bganimation].bEnabled = g_BackgroundChange.rows[add_global_bganimation].choices.size() > 0; - g_BackgroundChange.rows[add_global_visualization].bEnabled = g_BackgroundChange.rows[add_global_visualization].choices.size() > 0; - g_BackgroundChange.rows[delete_change].bEnabled = bAlreadyBGChangeHere; - + g_BackgroundChange.rows[file1_type].bEnabled = true; + g_BackgroundChange.rows[file1_song_bganimation].bEnabled = g_BackgroundChange.rows[file1_song_bganimation].choices.size() > 0; + g_BackgroundChange.rows[file1_song_movie].bEnabled = g_BackgroundChange.rows[file1_song_movie].choices.size() > 0; + g_BackgroundChange.rows[file1_song_still].bEnabled = g_BackgroundChange.rows[file1_song_still].choices.size() > 0; + g_BackgroundChange.rows[file1_global_random_movie].bEnabled = g_BackgroundChange.rows[file1_global_random_movie].choices.size() > 0; + g_BackgroundChange.rows[file1_global_bganimation].bEnabled = g_BackgroundChange.rows[file1_global_bganimation].choices.size() > 0; + g_BackgroundChange.rows[file2_type].bEnabled = g_BackgroundChange.rows[file1_type].bEnabled; + g_BackgroundChange.rows[file2_song_bganimation].bEnabled = g_BackgroundChange.rows[file1_song_bganimation].bEnabled; + g_BackgroundChange.rows[file2_song_movie].bEnabled = g_BackgroundChange.rows[file1_song_movie].bEnabled; + g_BackgroundChange.rows[file2_song_still].bEnabled = g_BackgroundChange.rows[file1_song_still].bEnabled; + g_BackgroundChange.rows[file2_global_random_movie].bEnabled = g_BackgroundChange.rows[file1_global_random_movie].bEnabled; + g_BackgroundChange.rows[file2_global_bganimation].bEnabled = g_BackgroundChange.rows[file1_global_bganimation].bEnabled; + g_BackgroundChange.rows[delete_change].bEnabled = bAlreadyBGChangeHere; + // set default choices g_BackgroundChange.rows[layer]. SetDefaultChoiceIfPresent( ssprintf("%d",iLayer) ); g_BackgroundChange.rows[rate]. SetDefaultChoiceIfPresent( ssprintf("%2.0f%%",bgChange.m_fRate*100) ); - g_BackgroundChange.rows[fade_last].iDefaultChoice = bgChange.m_bFadeLast ? 1 : 0; - g_BackgroundChange.rows[rewind_movie].iDefaultChoice = bgChange.m_bRewindMovie ? 1 : 0; - g_BackgroundChange.rows[loop].iDefaultChoice = bgChange.m_bLoop ? 1 : 0; - g_BackgroundChange.rows[add_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sBGName ); - g_BackgroundChange.rows[add_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_sBGName ); - g_BackgroundChange.rows[add_song_still]. SetDefaultChoiceIfPresent( bgChange.m_sBGName ); - g_BackgroundChange.rows[add_global_random_movie]. SetDefaultChoiceIfPresent( bgChange.m_sBGName ); - g_BackgroundChange.rows[add_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sBGName ); - g_BackgroundChange.rows[add_global_visualization]. SetDefaultChoiceIfPresent( bgChange.m_sBGName ); + g_BackgroundChange.rows[rewind_movie].iDefaultChoice= bgChange.m_bRewindMovie ? 1 : 0; + g_BackgroundChange.rows[loop].iDefaultChoice = bgChange.m_bLoop ? 1 : 0; + g_BackgroundChange.rows[transition]. SetDefaultChoiceIfPresent( bgChange.m_sTransition ); + g_BackgroundChange.rows[file1_type].iDefaultChoice = 0; // FIXME + g_BackgroundChange.rows[file1_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sFile1 ); + g_BackgroundChange.rows[file1_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_sFile1 ); + g_BackgroundChange.rows[file1_song_still]. SetDefaultChoiceIfPresent( bgChange.m_sFile1 ); + g_BackgroundChange.rows[file1_global_random_movie]. SetDefaultChoiceIfPresent( bgChange.m_sFile1 ); + g_BackgroundChange.rows[file1_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sFile1 ); + g_BackgroundChange.rows[file2_type].iDefaultChoice = 0; // FIXME + g_BackgroundChange.rows[file2_song_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sFile2 ); + g_BackgroundChange.rows[file2_song_movie]. SetDefaultChoiceIfPresent( bgChange.m_sFile2 ); + g_BackgroundChange.rows[file2_song_still]. SetDefaultChoiceIfPresent( bgChange.m_sFile2 ); + g_BackgroundChange.rows[file2_global_random_movie]. SetDefaultChoiceIfPresent( bgChange.m_sFile2 ); + g_BackgroundChange.rows[file2_global_bganimation]. SetDefaultChoiceIfPresent( bgChange.m_sFile2 ); SCREENMAN->MiniMenu( &g_BackgroundChange, SM_BackFromBGChange ); @@ -2639,35 +2661,20 @@ void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector &iAns } } + if( c == delete_change ) + return; // don't add + newChange.m_fStartBeat = GAMESTATE->m_fSongBeat; - - switch( c ) - { - case add_random: - newChange.m_sBGName = "-random-"; - break; - case add_song_bganimation: - case add_song_movie: - case add_song_still: - case add_global_random_movie: - case add_global_bganimation: - case add_global_visualization: - newChange.m_sBGName = g_BackgroundChange.rows[c].choices[iAnswers[c]]; - break; - case delete_change: - newChange.m_sBGName = ""; - break; - default: - break; - }; - newChange.m_fRate = strtof( g_BackgroundChange.rows[rate].choices[iAnswers[rate]], NULL )/100.f; - newChange.m_bFadeLast = !!iAnswers[fade_last]; newChange.m_bRewindMovie = !!iAnswers[rewind_movie]; newChange.m_bLoop = !!iAnswers[loop]; + newChange.m_sTransition = g_BackgroundChange.rows[transition].choices[iAnswers[transition]]; + int iRow1 = file1_song_bganimation + iAnswers[file1_type]; + newChange.m_sFile1 = g_BackgroundChange.rows[iRow1].choices[iAnswers[iRow1]]; + int iRow2 = file2_song_bganimation + iAnswers[file2_type]; + newChange.m_sFile2 = g_BackgroundChange.rows[iRow2].choices[iAnswers[iRow2]]; - if( newChange.m_sBGName != "" ) - m_pSong->AddBackgroundChange( iLayer, newChange ); + m_pSong->AddBackgroundChange( iLayer, newChange ); } void ScreenEdit::SetupCourseAttacks() diff --git a/stepmania/src/ScreenEdit.h b/stepmania/src/ScreenEdit.h index 92b4f8226d..57fbd690e3 100644 --- a/stepmania/src/ScreenEdit.h +++ b/stepmania/src/ScreenEdit.h @@ -366,16 +366,22 @@ public: enum BGChangeChoice { layer, rate, - fade_last, rewind_movie, loop, - add_random, - add_song_bganimation, - add_song_movie, - add_song_still, - add_global_random_movie, - add_global_bganimation, - add_global_visualization, + transition, + effect, + file1_type, + file1_song_bganimation, + file1_song_movie, + file1_song_still, + file1_global_random_movie, + file1_global_bganimation, + file2_type, + file2_song_bganimation, + file2_song_movie, + file2_song_still, + file2_global_random_movie, + file2_global_bganimation, delete_change, NUM_BGCHANGE_CHOICES }; diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index b94c8b2e24..79626e5f67 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -144,13 +144,13 @@ void Song::GetDisplayBpms( DisplayBpms &AddTo ) const } } -CString Song::GetBackgroundAtBeat( int iLayer, float fBeat ) const +const BackgroundChange &Song::GetBackgroundAtBeat( int iLayer, float fBeat ) const { unsigned i; for( i=0; i fBeat ) break; - return m_BackgroundChanges[iLayer][i].m_sBGName; + return m_BackgroundChanges[iLayer][i]; } @@ -721,7 +721,7 @@ void Song::TidyUpData() /* Use this->GetBeatFromElapsedTime(0) instead of 0 to start when the * music starts. */ if( arrayPossibleMovies.size() == 1 ) - this->AddBackgroundChange( 0, BackgroundChange(0,arrayPossibleMovies[0],1.f,true,true,false) ); + this->AddBackgroundChange( 0, BackgroundChange(0,arrayPossibleMovies[0],"",1.f,true,true,false) ); } diff --git a/stepmania/src/song.h b/stepmania/src/song.h index c5e9bdc436..8d64177635 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -24,20 +24,6 @@ extern const int FILE_CACHE_VERSION; const int NUM_BACKGROUND_LAYERS = 2; -struct BackgroundChange -{ - BackgroundChange() { m_fStartBeat=-1; m_fRate=1; m_bFadeLast=false; m_bRewindMovie=false; m_bLoop=true; }; - BackgroundChange( float s, CString n, float r=1.f, bool f=false, bool m=false, bool l=true ) { m_fStartBeat=s; m_sBGName=n; m_fRate=r; m_bFadeLast=f; m_bRewindMovie=m; m_bLoop=l; }; - float m_fStartBeat; - CString m_sBGName; - float m_fRate; - bool m_bFadeLast; - bool m_bRewindMovie; - bool m_bLoop; -}; - -void SortBackgroundChangesArray( vector &arrayBackgroundChanges ); - struct LyricSegment { float m_fStartTime; @@ -45,7 +31,6 @@ struct LyricSegment RageColor m_Color; }; - class Song { CString m_sSongDir; @@ -165,7 +150,7 @@ public: void AddLyricSegment( LyricSegment seg ); void GetDisplayBpms( DisplayBpms &AddTo ) const; - CString GetBackgroundAtBeat( int iLayer, float fBeat ) const; + const BackgroundChange &GetBackgroundAtBeat( int iLayer, float fBeat ) const; float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); } void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }