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 ); }