add multiple background layers

This commit is contained in:
Chris Danford
2005-05-26 09:35:57 +00:00
parent 87183c0551
commit 68a82faa6a
10 changed files with 275 additions and 182 deletions
+96 -62
View File
@@ -53,13 +53,17 @@ static RageColor GetBrightnessColor( float fBrightnessPercent )
} }
Background::Background() Background::Background()
{
m_pDancingCharacters = NULL;
m_bInitted = false;
}
Background::Layer::Layer()
{ {
m_iCurBGChangeIndex = -1; m_iCurBGChangeIndex = -1;
m_pCurrentBGA = NULL; m_pCurrentBGA = NULL;
m_pFadingBGA = NULL; m_pFadingBGA = NULL;
m_fSecsLeftInFade = 0; m_fSecsLeftInFade = 0;
m_pDancingCharacters = NULL;
m_bInitted = false;
} }
void Background::Init() void Background::Init()
@@ -114,6 +118,14 @@ Background::~Background()
} }
void Background::Unload() void Background::Unload()
{
for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
m_Layer[i].Unload();
m_pSong = NULL;
m_fLastMusicSeconds = -9999;
}
void Background::Layer::Unload()
{ {
for( map<CString,Actor*>::iterator iter = m_BGAnimations.begin(); for( map<CString,Actor*>::iterator iter = m_BGAnimations.begin();
iter != m_BGAnimations.end(); iter != m_BGAnimations.end();
@@ -125,10 +137,8 @@ void Background::Unload()
m_pCurrentBGA = NULL; m_pCurrentBGA = NULL;
m_pFadingBGA = NULL; m_pFadingBGA = NULL;
m_pSong = NULL;
m_fSecsLeftInFade = 0; m_fSecsLeftInFade = 0;
m_iCurBGChangeIndex = -1; m_iCurBGChangeIndex = -1;
m_fLastMusicSeconds = -9999;
} }
Actor *MakeVisualization( const CString &sVisPath ) Actor *MakeVisualization( const CString &sVisPath )
@@ -163,7 +173,7 @@ Actor *MakeMovie( const CString &sMoviePath )
return pSprite; return pSprite;
} }
Actor *Background::CreateSongBGA( CString sBGName ) const Actor *Background::Layer::CreateSongBGA( const Song *pSong, CString sBGName ) const
{ {
BGAnimation *pTempBGA; BGAnimation *pTempBGA;
@@ -173,7 +183,7 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
CStringArray asFiles; CStringArray asFiles;
// Look for BGAnims in the song dir // Look for BGAnims in the song dir
GetDirListing( m_pSong->GetSongDir()+sBGName, asFiles, true, true ); GetDirListing( pSong->GetSongDir()+sBGName, asFiles, true, true );
if( !asFiles.empty() ) if( !asFiles.empty() )
{ {
/* If default.xml exists, use the regular generic actor load. However, /* If default.xml exists, use the regular generic actor load. However,
@@ -187,7 +197,7 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
return pTempBGA; return pTempBGA;
} }
// Look for BG movies or static graphics in the song dir // Look for BG movies or static graphics in the song dir
GetDirListing( m_pSong->GetSongDir()+sBGName, asFiles, false, true ); GetDirListing( pSong->GetSongDir()+sBGName, asFiles, false, true );
if( !asFiles.empty() ) if( !asFiles.empty() )
{ {
const CString sExt = GetExtension( asFiles[0]) ; const CString sExt = GetExtension( asFiles[0]) ;
@@ -214,9 +224,9 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
GetDirListing( BG_ANIMS_DIR+sBGName, asFiles, true, true ); GetDirListing( BG_ANIMS_DIR+sBGName, asFiles, true, true );
if( !asFiles.empty() ) if( !asFiles.empty() )
{ {
pTempBGA = new BGAnimation; Actor *pActor = ActorUtil::MakeActor( asFiles[0] );
pTempBGA->LoadFromAniDir( asFiles[0] ); ASSERT( pActor );
return pTempBGA; return pActor;
} }
// Look for BGAnims in the BGAnims dir // Look for BGAnims in the BGAnims dir
@@ -228,7 +238,7 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
return NULL; return NULL;
} }
CString Background::CreateRandomBGA( CString sPreferredSubDir ) CString Background::Layer::CreateRandomBGA( const Song *pSong, CString sPreferredSubDir )
{ {
if( sPreferredSubDir.Right(1) != "/" ) if( sPreferredSubDir.Right(1) != "/" )
sPreferredSubDir += '/'; sPreferredSubDir += '/';
@@ -338,9 +348,9 @@ void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const Timing
//bool bFade = PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_RANDOMMOVIES || //bool bFade = PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_RANDOMMOVIES ||
// PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_MOVIEVIS; // PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_MOVIEVIS;
CString sBGName = CreateRandomBGA( sPreferredSubDir ); CString sBGName = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir );
if( sBGName != "" ) if( sBGName != "" )
m_aBGChanges.push_back( BackgroundChange(f,sBGName,1.f,bFade) ); m_Layer[0].m_aBGChanges.push_back( BackgroundChange(f,sBGName,1.f,bFade) );
} }
// change BG every BPM change that is at the beginning of a measure // change BG every BPM change that is at the beginning of a measure
@@ -356,9 +366,9 @@ void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const Timing
if( bpmseg.m_iStartIndex < iStartIndex || bpmseg.m_iStartIndex > iEndIndex ) if( bpmseg.m_iStartIndex < iStartIndex || bpmseg.m_iStartIndex > iEndIndex )
continue; // skip continue; // skip
CString sBGName = CreateRandomBGA( sPreferredSubDir ); CString sBGName = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir );
if( sBGName != "" ) if( sBGName != "" )
m_aBGChanges.push_back( BackgroundChange(NoteRowToBeat(bpmseg.m_iStartIndex),sBGName) ); m_Layer[0].m_aBGChanges.push_back( BackgroundChange(NoteRowToBeat(bpmseg.m_iStartIndex),sBGName) );
} }
} }
@@ -387,53 +397,68 @@ void Background::LoadFromSong( const Song* pSong )
if( pSong->HasBGChanges() ) if( pSong->HasBGChanges() )
{ {
// Load all song-specified backgrounds for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
for( unsigned i=0; i<pSong->m_BackgroundChanges.size(); i++ )
{ {
BackgroundChange change = pSong->m_BackgroundChanges[i]; Layer &layer = m_Layer[i];
// Load all song-specified backgrounds
FOREACH_CONST( BackgroundChange, pSong->m_BackgroundChanges[i], bgc )
{
BackgroundChange change = *bgc;
CString &sBGName = change.m_sBGName; CString &sBGName = change.m_sBGName;
bool bIsAlreadyLoaded = m_BGAnimations.find(sBGName) != m_BGAnimations.end(); bool bIsAlreadyLoaded = layer.m_BGAnimations.find(sBGName) != layer.m_BGAnimations.end();
if( sBGName.CompareNoCase("-random-")!=0 && !bIsAlreadyLoaded ) if( sBGName.CompareNoCase("-random-")!=0 && !bIsAlreadyLoaded )
{ {
Actor *pTempBGA = CreateSongBGA( sBGName ); Actor *pTempBGA = layer.CreateSongBGA( m_pSong, sBGName );
if( pTempBGA ) if( pTempBGA )
{ {
m_BGAnimations[sBGName] = pTempBGA; layer.m_BGAnimations[sBGName] = pTempBGA;
} }
else // the background was not found. Use a random one instead else // the background was not found. Use a random one instead
{ {
sBGName = CreateRandomBGA( pSong->m_sGroupName ); sBGName = layer.CreateRandomBGA( pSong, pSong->m_sGroupName );
if( sBGName == "" ) if( sBGName == "" )
sBGName = STATIC_BACKGROUND; sBGName = STATIC_BACKGROUND;
} }
} }
m_aBGChanges.push_back( change ); layer.m_aBGChanges.push_back( change );
}
} }
} }
else // pSong doesn't have an animation plan else // pSong doesn't have an animation plan
{ {
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, pSong->m_Timing, pSong->m_sGroupName );
// end showing the static song background // end showing the static song background
m_aBGChanges.push_back( BackgroundChange(pSong->m_fLastBeat,STATIC_BACKGROUND) ); layer.m_aBGChanges.push_back( BackgroundChange(pSong->m_fLastBeat,STATIC_BACKGROUND) );
} }
// sort segments // sort segments
SortBackgroundChangesArray( m_aBGChanges ); for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
{
Layer &layer = m_Layer[i];
SortBackgroundChangesArray( layer.m_aBGChanges );
}
Layer &mainlayer = m_Layer[0];
/* If the first BGAnimation isn't negative, add a lead-in image showing the song /* If the first BGAnimation isn't negative, add a lead-in image showing the song
* background. */ * background. */
if( m_aBGChanges.empty() || m_aBGChanges.front().m_fStartBeat >= 0 ) if( mainlayer.m_aBGChanges.empty() || mainlayer.m_aBGChanges.front().m_fStartBeat >= 0 )
m_aBGChanges.insert( m_aBGChanges.begin(), BackgroundChange(-10000,STATIC_BACKGROUND) ); mainlayer.m_aBGChanges.insert( mainlayer.m_aBGChanges.begin(), BackgroundChange(-10000,STATIC_BACKGROUND) );
// If any BGChanges use the background image, load it. // If any BGChanges use the background image, load it.
bool bStaticBackgroundUsed = false; bool bStaticBackgroundUsed = false;
for( unsigned i=0; i<m_aBGChanges.size(); i++ ) for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
if( m_aBGChanges[i].m_sBGName == STATIC_BACKGROUND ) if( mainlayer.m_aBGChanges[i].m_sBGName == STATIC_BACKGROUND )
bStaticBackgroundUsed = true; bStaticBackgroundUsed = true;
if( bStaticBackgroundUsed ) if( bStaticBackgroundUsed )
{ {
@@ -442,33 +467,33 @@ void Background::LoadFromSong( const Song* pSong )
Sprite* pSprite = new Sprite; Sprite* pSprite = new Sprite;
pSprite->LoadBG( sSongBGPath ); pSprite->LoadBG( sSongBGPath );
pSprite->StretchTo( FullScreenRectF ); pSprite->StretchTo( FullScreenRectF );
m_BGAnimations[STATIC_BACKGROUND] = pSprite; mainlayer.m_BGAnimations[STATIC_BACKGROUND] = pSprite;
} }
// Look for the filename "Random", and replace the segment with LoadFromRandom. // Look for the filename "Random", and replace the segment with LoadFromRandom.
for( unsigned i=0; i<m_aBGChanges.size(); i++ ) for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
{ {
BackgroundChange &change = m_aBGChanges[i]; BackgroundChange &change = mainlayer.m_aBGChanges[i];
if( change.m_sBGName.CompareNoCase("-random-") ) if( change.m_sBGName.CompareNoCase("-random-") )
continue; continue;
const float fStartBeat = change.m_fStartBeat; const float fStartBeat = change.m_fStartBeat;
const float fLastBeat = (i+1 < m_aBGChanges.size())? m_aBGChanges[i+1].m_fStartBeat: FLT_MAX; const float fLastBeat = (i+1 < mainlayer.m_aBGChanges.size())? mainlayer.m_aBGChanges[i+1].m_fStartBeat: FLT_MAX;
m_aBGChanges.erase( m_aBGChanges.begin()+i ); mainlayer.m_aBGChanges.erase( mainlayer.m_aBGChanges.begin()+i );
--i; --i;
LoadFromRandom( fStartBeat, fLastBeat, pSong->m_Timing, pSong->m_sGroupName ); LoadFromRandom( fStartBeat, fLastBeat, pSong->m_Timing, pSong->m_sGroupName );
} }
// At this point, we shouldn't have any BGChanges to "". "" is an invalid name. // At this point, we shouldn't have any BGChanges to "". "" is an invalid name.
for( unsigned i=0; i<m_aBGChanges.size(); i++ ) for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
ASSERT( !m_aBGChanges[i].m_sBGName.empty() ); ASSERT( !mainlayer.m_aBGChanges[i].m_sBGName.empty() );
// Re-sort. // Re-sort.
SortBackgroundChangesArray( m_aBGChanges ); SortBackgroundChangesArray( mainlayer.m_aBGChanges );
m_DangerAll.SetXY( (float)LEFT_EDGE, (float)TOP_EDGE ); m_DangerAll.SetXY( (float)LEFT_EDGE, (float)TOP_EDGE );
m_DangerAll.SetZoomX( fXZoom ); m_DangerAll.SetZoomX( fXZoom );
@@ -501,7 +526,7 @@ void Background::LoadFromSong( const Song* pSong )
* the clock back with "effectclock,timer" in your OnCommand. Note that at this * the clock back with "effectclock,timer" in your OnCommand. Note that at this
* point, we havn't run the OnCommand yet, so it'll override correctly. */ * point, we havn't run the OnCommand yet, so it'll override correctly. */
map<CString,Actor*>::iterator it; map<CString,Actor*>::iterator it;
for( it = m_BGAnimations.begin(); it != m_BGAnimations.end(); ++it ) for( it = mainlayer.m_BGAnimations.begin(); it != mainlayer.m_BGAnimations.end(); ++it )
{ {
Actor *pBGA = it->second; Actor *pBGA = it->second;
@@ -514,7 +539,7 @@ void Background::LoadFromSong( const Song* pSong )
} }
} }
int Background::FindBGSegmentForBeat( float fBeat ) const int Background::Layer::FindBGSegmentForBeat( float fBeat ) const
{ {
if( m_aBGChanges.empty() ) if( m_aBGChanges.empty() )
return -1; return -1;
@@ -533,7 +558,7 @@ int Background::FindBGSegmentForBeat( float fBeat ) const
} }
/* If the BG segment has changed, move focus to it. Send Update() calls. */ /* If the BG segment has changed, move focus to it. Send Update() calls. */
void Background::UpdateCurBGChange( float fCurrentTime ) void Background::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime )
{ {
ASSERT( fCurrentTime != GameState::MUSIC_SECONDS_INVALID ); ASSERT( fCurrentTime != GameState::MUSIC_SECONDS_INVALID );
@@ -542,7 +567,7 @@ void Background::UpdateCurBGChange( float fCurrentTime )
float fBeat, fBPS; float fBeat, fBPS;
bool bFreeze; bool bFreeze;
m_pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze ); pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze );
/* Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it. */ /* Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it. */
const float fRate = GAMESTATE->m_SongOptions.m_fMusicRate; const float fRate = GAMESTATE->m_SongOptions.m_fMusicRate;
@@ -582,7 +607,7 @@ void Background::UpdateCurBGChange( float fCurrentTime )
m_fSecsLeftInFade = m_pFadingBGA!=NULL ? FADE_SECONDS : 0; m_fSecsLeftInFade = m_pFadingBGA!=NULL ? FADE_SECONDS : 0;
/* How much time of this BGA have we skipped? (This happens with SetSeconds.) */ /* How much time of this BGA have we skipped? (This happens with SetSeconds.) */
const float fStartSecond = m_pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat ); const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat );
/* This is affected by the music rate. */ /* This is affected by the music rate. */
float fDeltaTime = fCurrentTime - fStartSecond; float fDeltaTime = fCurrentTime - fStartSecond;
@@ -593,17 +618,16 @@ void Background::UpdateCurBGChange( float fCurrentTime )
else // we're not changing backgrounds else // we're not changing backgrounds
{ {
/* This is affected by the music rate. */ /* This is affected by the music rate. */
float fDeltaTime = fCurrentTime - m_fLastMusicSeconds; float fDeltaTime = fCurrentTime - fLastMusicSeconds;
fDeltaTime /= fRate; fDeltaTime /= fRate;
if( m_pCurrentBGA ) if( m_pCurrentBGA )
m_pCurrentBGA->Update( max( fDeltaTime, 0 ) ); m_pCurrentBGA->Update( max( fDeltaTime, 0 ) );
} }
float fDeltaTime = fCurrentTime - m_fLastMusicSeconds; float fDeltaTime = fCurrentTime - fLastMusicSeconds;
fDeltaTime /= fRate; fDeltaTime /= fRate;
if( m_pFadingBGA ) if( m_pFadingBGA )
m_pFadingBGA->Update( max( fCurrentTime - m_fLastMusicSeconds, 0 ) ); m_pFadingBGA->Update( max( fCurrentTime - fLastMusicSeconds, 0 ) );
m_fLastMusicSeconds = fCurrentTime;
} }
void Background::Update( float fDeltaTime ) void Background::Update( float fDeltaTime )
@@ -624,28 +648,33 @@ void Background::Update( float fDeltaTime )
m_DeadPlayer[p].Update( fDeltaTime ); m_DeadPlayer[p].Update( fDeltaTime );
} }
if( m_pDancingCharacters )
m_pDancingCharacters->Update( fDeltaTime );
/* Always update the current background, even when m_DangerAll is being displayed. /* Always update the current background, even when m_DangerAll is being displayed.
* Otherwise, we'll stop updating movies during danger (which may stop them from * Otherwise, we'll stop updating movies during danger (which may stop them from
* playing), and we won't start clips at the right time, which will throw backgrounds * playing), and we won't start clips at the right time, which will throw backgrounds
* off sync. */ * off sync. */
UpdateCurBGChange( GAMESTATE->m_fMusicSeconds ); for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
if( m_pFadingBGA )
{ {
m_pFadingBGA->Update( fDeltaTime ); Layer &layer = m_Layer[i];
m_fSecsLeftInFade -= fDeltaTime; layer.UpdateCurBGChange( m_pSong, m_fLastMusicSeconds, GAMESTATE->m_fMusicSeconds );
float fPercentOpaque = m_fSecsLeftInFade / FADE_SECONDS;
m_pFadingBGA->SetDiffuse( RageColor(1,1,1,fPercentOpaque) ); 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 ) if( fPercentOpaque <= 0 )
{ {
/* Reset its diffuse color, in case we reuse it. */ /* Reset its diffuse color, in case we reuse it. */
m_pFadingBGA->SetDiffuse( RageColor(1,1,1,1) ); layer.m_pFadingBGA->SetDiffuse( RageColor(1,1,1,1) );
m_pFadingBGA = NULL; layer.m_pFadingBGA = NULL;
} }
} }
}
if( m_pDancingCharacters ) m_fLastMusicSeconds = GAMESTATE->m_fMusicSeconds;
m_pDancingCharacters->Update( fDeltaTime );
} }
void Background::DrawPrimitives() void Background::DrawPrimitives()
@@ -665,10 +694,15 @@ void Background::DrawPrimitives()
{ {
if( m_pDancingCharacters ) if( m_pDancingCharacters )
m_pDancingCharacters->m_bDrawDangerLight = false; m_pDancingCharacters->m_bDrawDangerLight = false;
if( m_pCurrentBGA )
m_pCurrentBGA->Draw(); for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
if( m_pFadingBGA ) {
m_pFadingBGA->Draw(); Layer &layer = m_Layer[i];
if( layer.m_pCurrentBGA )
layer.m_pCurrentBGA->Draw();
if( layer.m_pFadingBGA )
layer.m_pFadingBGA->Draw();
}
FOREACH_PlayerNumber( p ) FOREACH_PlayerNumber( p )
{ {
+17 -8
View File
@@ -49,21 +49,22 @@ public:
protected: protected:
const Song *m_pSong; const Song *m_pSong;
void LoadFromRandom( float fFirstBeat, float fLastBeat, const TimingData &timing, CString sPreferredSubDir ); void LoadFromRandom( float fFirstBeat, float fLastBeat, const TimingData &timing, CString sPreferredSubDir );
int FindBGSegmentForBeat( float fBeat ) const;
bool IsDangerAllVisible(); bool IsDangerAllVisible();
void UpdateCurBGChange( float fCurrentTime );
bool m_bInitted; bool m_bInitted;
DancingCharacters* m_pDancingCharacters; DancingCharacters* m_pDancingCharacters;
BGAnimation m_DangerPlayer[NUM_PLAYERS]; class Layer
BGAnimation m_DangerAll; {
public:
Layer();
void Unload();
BGAnimation m_DeadPlayer[NUM_PLAYERS]; Actor *CreateSongBGA( const Song *pSong, CString sBGName ) const;
CString CreateRandomBGA( const Song *pSong, CString sPreferredSubDir );
Actor *CreateSongBGA( CString sBGName ) const; int FindBGSegmentForBeat( float fBeat ) const;
CString CreateRandomBGA( CString sPreferredSubDir ); void UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime );
map<CString,Actor*> m_BGAnimations; map<CString,Actor*> m_BGAnimations;
deque<CString> m_RandomBGAnimations; deque<CString> m_RandomBGAnimations;
@@ -72,8 +73,16 @@ protected:
Actor *m_pCurrentBGA; Actor *m_pCurrentBGA;
Actor *m_pFadingBGA; Actor *m_pFadingBGA;
float m_fSecsLeftInFade; float m_fSecsLeftInFade;
};
Layer m_Layer[NUM_BACKGROUND_LAYERS];
float m_fLastMusicSeconds; float m_fLastMusicSeconds;
BGAnimation m_DangerPlayer[NUM_PLAYERS];
BGAnimation m_DangerAll;
BGAnimation m_DeadPlayer[NUM_PLAYERS];
// cover up the edge of animations that might hang outside of the background rectangle // cover up the edge of animations that might hang outside of the background rectangle
Quad m_quadBorderLeft, m_quadBorderTop, m_quadBorderRight, m_quadBorderBottom; Quad m_quadBorderLeft, m_quadBorderTop, m_quadBorderRight, m_quadBorderBottom;
+8 -4
View File
@@ -531,14 +531,17 @@ void NoteField::DrawPrimitives()
break; break;
case EDIT_MODE_FULL: case EDIT_MODE_FULL:
{ {
vector<BackgroundChange> &aBackgroundChanges = GAMESTATE->m_pCurSong->m_BackgroundChanges; for( int b=0; b<NUM_BACKGROUND_LAYERS; b++ )
{
vector<BackgroundChange> &aBackgroundChanges = GAMESTATE->m_pCurSong->m_BackgroundChanges[b];
for( unsigned i=0; i<aBackgroundChanges.size(); i++ ) for( unsigned i=0; i<aBackgroundChanges.size(); i++ )
{ {
if(aBackgroundChanges[i].m_fStartBeat >= fFirstBeatToDraw && if( aBackgroundChanges[i].m_fStartBeat >= fFirstBeatToDraw &&
aBackgroundChanges[i].m_fStartBeat <= fLastBeatToDraw) aBackgroundChanges[i].m_fStartBeat <= fLastBeatToDraw )
{ {
const BackgroundChange& change = aBackgroundChanges[i]; const BackgroundChange& change = aBackgroundChanges[i];
CString sChangeText = ssprintf("%s\n%.0f%%%s%s%s", 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_sBGName.c_str(),
change.m_fRate*100, change.m_fRate*100,
change.m_bFadeLast ? " Fade" : "", change.m_bFadeLast ? " Fade" : "",
@@ -550,6 +553,7 @@ void NoteField::DrawPrimitives()
} }
} }
} }
}
break; break;
default: default:
ASSERT(0); ASSERT(0);
+55 -40
View File
@@ -87,11 +87,14 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
for( unsigned i=0; i<msd.GetNumValues(); i++ ) for( unsigned i=0; i<msd.GetNumValues(); i++ )
{ {
const MsdFile::value_t &sParams = msd.GetValue(i); const MsdFile::value_t &sParams = msd.GetValue(i);
const CString sValueName = sParams[0]; CString sValueName = sParams[0];
sValueName.MakeUpper();
if( 0==stricmp(sValueName,"OFFSET") ) if( sValueName=="OFFSET" )
{
out.m_fBeat0OffsetInSeconds = strtof( sParams[1], NULL ); out.m_fBeat0OffsetInSeconds = strtof( sParams[1], NULL );
else if( 0==stricmp(sValueName,"STOPS") || 0==stricmp(sValueName,"FREEZES") ) }
else if( sValueName=="STOPS" || sValueName=="FREEZES" )
{ {
CStringArray arrayFreezeExpressions; CStringArray arrayFreezeExpressions;
split( sParams[1], ",", arrayFreezeExpressions ); split( sParams[1], ",", arrayFreezeExpressions );
@@ -122,7 +125,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
} }
} }
else if( 0==stricmp(sValueName,"BPMS") ) else if( sValueName=="BPMS" )
{ {
CStringArray arrayBPMChangeExpressions; CStringArray arrayBPMChangeExpressions;
split( sParams[1], ",", arrayBPMChangeExpressions ); split( sParams[1], ",", arrayBPMChangeExpressions );
@@ -194,99 +197,100 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
{ {
int iNumParams = msd.GetNumParams(i); int iNumParams = msd.GetNumParams(i);
const MsdFile::value_t &sParams = msd.GetValue(i); const MsdFile::value_t &sParams = msd.GetValue(i);
const CString sValueName = sParams[0]; CString sValueName = sParams[0];
sValueName.MakeUpper();
// handle the data // handle the data
/* Don't use GetMainAndSubTitlesFromFullTitle; that's only for heuristically /* Don't use GetMainAndSubTitlesFromFullTitle; that's only for heuristically
* splitting other formats that *don't* natively support #SUBTITLE. */ * splitting other formats that *don't* natively support #SUBTITLE. */
if( 0==stricmp(sValueName,"TITLE") ) if( sValueName=="TITLE" )
out.m_sMainTitle = sParams[1]; out.m_sMainTitle = sParams[1];
else if( 0==stricmp(sValueName,"SUBTITLE") ) else if( sValueName=="SUBTITLE" )
out.m_sSubTitle = sParams[1]; out.m_sSubTitle = sParams[1];
else if( 0==stricmp(sValueName,"ARTIST") ) else if( sValueName=="ARTIST" )
out.m_sArtist = sParams[1]; out.m_sArtist = sParams[1];
else if( 0==stricmp(sValueName,"TITLETRANSLIT") ) else if( sValueName=="TITLETRANSLIT" )
out.m_sMainTitleTranslit = sParams[1]; out.m_sMainTitleTranslit = sParams[1];
else if( 0==stricmp(sValueName,"SUBTITLETRANSLIT") ) else if( sValueName=="SUBTITLETRANSLIT" )
out.m_sSubTitleTranslit = sParams[1]; out.m_sSubTitleTranslit = sParams[1];
else if( 0==stricmp(sValueName,"ARTISTTRANSLIT") ) else if( sValueName=="ARTISTTRANSLIT" )
out.m_sArtistTranslit = sParams[1]; out.m_sArtistTranslit = sParams[1];
else if( 0==stricmp(sValueName,"GENRE") ) else if( sValueName=="GENRE" )
out.m_sGenre = sParams[1]; out.m_sGenre = sParams[1];
else if( 0==stricmp(sValueName,"CREDIT") ) else if( sValueName=="CREDIT" )
out.m_sCredit = sParams[1]; out.m_sCredit = sParams[1];
else if( 0==stricmp(sValueName,"BANNER") ) else if( sValueName=="BANNER" )
out.m_sBannerFile = sParams[1]; out.m_sBannerFile = sParams[1];
else if( 0==stricmp(sValueName,"BACKGROUND") ) else if( sValueName=="BACKGROUND" )
out.m_sBackgroundFile = sParams[1]; out.m_sBackgroundFile = sParams[1];
/* Save "#LYRICS" for later, so we can add an internal lyrics tag. */ /* Save "#LYRICS" for later, so we can add an internal lyrics tag. */
else if( 0==stricmp(sValueName,"LYRICSPATH") ) else if( sValueName=="LYRICSPATH" )
out.m_sLyricsFile = sParams[1]; out.m_sLyricsFile = sParams[1];
else if( 0==stricmp(sValueName,"CDTITLE") ) else if( sValueName=="CDTITLE" )
out.m_sCDTitleFile = sParams[1]; out.m_sCDTitleFile = sParams[1];
else if( 0==stricmp(sValueName,"MUSIC") ) else if( sValueName=="MUSIC" )
out.m_sMusicFile = sParams[1]; out.m_sMusicFile = sParams[1];
else if( 0==stricmp(sValueName,"MUSICLENGTH") ) else if( sValueName=="MUSICLENGTH" )
{ {
if(!FromCache) if(!FromCache)
continue; continue;
out.m_fMusicLengthSeconds = strtof( sParams[1], NULL ); out.m_fMusicLengthSeconds = strtof( sParams[1], NULL );
} }
else if( 0==stricmp(sValueName,"MUSICBYTES") ) else if( sValueName=="MUSICBYTES" )
; /* ignore */ ; /* ignore */
/* We calculate these. Some SMs in circulation have bogus values for /* We calculate these. Some SMs in circulation have bogus values for
* these, so make sure we always calculate it ourself. */ * these, so make sure we always calculate it ourself. */
else if( 0==stricmp(sValueName,"FIRSTBEAT") ) else if( sValueName=="FIRSTBEAT" )
{ {
if(!FromCache) if(!FromCache)
continue; continue;
out.m_fFirstBeat = strtof( sParams[1], NULL ); out.m_fFirstBeat = strtof( sParams[1], NULL );
} }
else if( 0==stricmp(sValueName,"LASTBEAT") ) else if( sValueName=="LASTBEAT" )
{ {
if(!FromCache) if(!FromCache)
LOG->Trace("Ignored #LASTBEAT (cache only)"); LOG->Trace("Ignored #LASTBEAT (cache only)");
out.m_fLastBeat = strtof( sParams[1], NULL ); out.m_fLastBeat = strtof( sParams[1], NULL );
} }
else if( 0==stricmp(sValueName,"SONGFILENAME") ) else if( sValueName=="SONGFILENAME" )
{ {
if( FromCache ) if( FromCache )
out.m_sSongFileName = sParams[1]; out.m_sSongFileName = sParams[1];
} }
else if( 0==stricmp(sValueName,"HASMUSIC") ) else if( sValueName=="HASMUSIC" )
{ {
if( FromCache ) if( FromCache )
out.m_bHasMusic = atoi( sParams[1] ) != 0; out.m_bHasMusic = atoi( sParams[1] ) != 0;
} }
else if( 0==stricmp(sValueName,"HASBANNER") ) else if( sValueName=="HASBANNER" )
{ {
if( FromCache ) if( FromCache )
out.m_bHasBanner = atoi( sParams[1] ) != 0; out.m_bHasBanner = atoi( sParams[1] ) != 0;
} }
else if( 0==stricmp(sValueName,"SAMPLESTART") ) else if( sValueName=="SAMPLESTART" )
out.m_fMusicSampleStartSeconds = HHMMSSToSeconds( sParams[1] ); out.m_fMusicSampleStartSeconds = HHMMSSToSeconds( sParams[1] );
else if( 0==stricmp(sValueName,"SAMPLELENGTH") ) else if( sValueName=="SAMPLELENGTH" )
out.m_fMusicSampleLengthSeconds = HHMMSSToSeconds( sParams[1] ); out.m_fMusicSampleLengthSeconds = HHMMSSToSeconds( sParams[1] );
else if( 0==stricmp(sValueName,"DISPLAYBPM") ) else if( sValueName=="DISPLAYBPM" )
{ {
// #DISPLAYBPM:[xxx][xxx:xxx]|[*]; // #DISPLAYBPM:[xxx][xxx:xxx]|[*];
if( sParams[1] == "*" ) if( sParams[1] == "*" )
@@ -302,7 +306,7 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
} }
} }
else if( 0==stricmp(sValueName,"SELECTABLE") ) else if( sValueName=="SELECTABLE" )
{ {
if(!stricmp(sParams[1],"YES")) if(!stricmp(sParams[1],"YES"))
out.m_SelectionDisplay = out.SHOW_ALWAYS; out.m_SelectionDisplay = out.SHOW_ALWAYS;
@@ -314,7 +318,16 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
LOG->Warn( "The song file '%s' has an unknown #SELECTABLE value, '%s'; ignored.", sPath.c_str(), sParams[1].c_str()); LOG->Warn( "The song file '%s' has an unknown #SELECTABLE value, '%s'; ignored.", sPath.c_str(), sParams[1].c_str());
} }
else if( 0==stricmp(sValueName,"BGCHANGES") || 0==stricmp(sValueName,"ANIMATIONS") ) else if( sValueName=="BGCHANGES" || sValueName=="ANIMATIONS" )
{
int iLayer = 0;
sscanf( sValueName, "BGCHANGES%d", &iLayer );
if( iLayer < 0 && iLayer >= NUM_BACKGROUND_LAYERS )
{
LOG->Warn( "The song file '%s' has a BGCHANGES tag '%s' that is out of range.", sPath.c_str(), sValueName.c_str() );
}
else
{ {
CStringArray aBGChangeExpressions; CStringArray aBGChangeExpressions;
split( sParams[1], ",", aBGChangeExpressions ); split( sParams[1], ",", aBGChangeExpressions );
@@ -323,11 +336,12 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
{ {
BackgroundChange change; BackgroundChange change;
if( LoadFromBGChangesString( change, aBGChangeExpressions[b] ) ) if( LoadFromBGChangesString( change, aBGChangeExpressions[b] ) )
out.AddBackgroundChange( change ); out.AddBackgroundChange( iLayer, change );
}
} }
} }
else if( 0==stricmp(sValueName,"FGCHANGES") ) else if( sValueName=="FGCHANGES" )
{ {
CStringArray aFGChangeExpressions; CStringArray aFGChangeExpressions;
split( sParams[1], ",", aFGChangeExpressions ); split( sParams[1], ",", aFGChangeExpressions );
@@ -340,7 +354,7 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
} }
} }
else if( 0==stricmp(sValueName,"KEYSOUNDS") ) else if( sValueName=="KEYSOUNDS" )
{ {
CStringArray aKeysoundFiles; CStringArray aKeysoundFiles;
split( sParams[1], ",", aKeysoundFiles ); split( sParams[1], ",", aKeysoundFiles );
@@ -351,7 +365,7 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
} }
} }
else if( 0==stricmp(sValueName,"NOTES") || 0==stricmp(sValueName,"NOTES2") ) else if( sValueName=="NOTES" || sValueName=="NOTES2" )
{ {
if( iNumParams < 7 ) if( iNumParams < 7 )
{ {
@@ -371,8 +385,8 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
out.AddSteps( pNewNotes ); out.AddSteps( pNewNotes );
} }
else if( 0==stricmp(sValueName,"OFFSET") || 0==stricmp(sValueName,"BPMS") || else if( sValueName=="OFFSET" || sValueName=="BPMS" ||
0==stricmp(sValueName,"STOPS") || 0==stricmp(sValueName,"FREEZES") ) sValueName=="STOPS" || sValueName=="FREEZES" )
; ;
else else
LOG->Trace( "Unexpected value named '%s'", sValueName.c_str() ); LOG->Trace( "Unexpected value named '%s'", sValueName.c_str() );
@@ -436,10 +450,11 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, CString sEditFilePath, Profi
{ {
int iNumParams = msd.GetNumParams(i); int iNumParams = msd.GetNumParams(i);
const MsdFile::value_t &sParams = msd.GetValue(i); const MsdFile::value_t &sParams = msd.GetValue(i);
const CString sValueName = sParams[0]; CString sValueName = sParams[0];
sValueName.MakeUpper();
// handle the data // handle the data
if( 0==stricmp(sValueName,"SONG") ) if( sValueName=="SONG" )
{ {
if( pSong ) if( pSong )
{ {
@@ -464,7 +479,7 @@ bool SMLoader::LoadEditFromMsd( const MsdFile &msd, CString sEditFilePath, Profi
} }
} }
else if( 0==stricmp(sValueName,"NOTES") ) else if( sValueName=="NOTES" )
{ {
if( pSong == NULL ) if( pSong == NULL )
{ {
@@ -519,7 +534,7 @@ void SMLoader::TidyUpData( Song &song, bool cache )
* have to add an explicit song BG tag if they want it. This is really a * have to add an explicit song BG tag if they want it. This is really a
* formatting hack only; nothing outside of SMLoader ever sees "-nosongbg-". * formatting hack only; nothing outside of SMLoader ever sees "-nosongbg-".
*/ */
vector<BackgroundChange> &bg = song.m_BackgroundChanges; vector<BackgroundChange> &bg = song.m_BackgroundChanges[0];
if( !bg.empty() ) if( !bg.empty() )
{ {
/* BGChanges have been sorted. On the odd chance that a BGChange exists /* BGChanges have been sorted. On the odd chance that a BGChange exists
+13 -6
View File
@@ -10,6 +10,7 @@
#include "NoteTypes.h" #include "NoteTypes.h"
#include <cstring> #include <cstring>
#include <cerrno> #include <cerrno>
#include "Foreach.h"
void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out ) void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out )
{ {
@@ -81,20 +82,26 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out )
} }
f.PutLine( ";" ); f.PutLine( ";" );
f.Write( "#BGCHANGES:" ); for( unsigned b=0; b<NUM_BACKGROUND_LAYERS; b++ )
for( unsigned i=0; i<out.m_BackgroundChanges.size(); i++ )
{ {
const BackgroundChange &seg = out.m_BackgroundChanges[i]; if( b==0 )
f.Write( "#BGCHANGES:" );
else if( out.m_BackgroundChanges[b].empty() )
continue; // skip
else
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( ssprintf( "%.3f=%s=%.3f=%d=%d=%d,", seg.m_fStartBeat, seg.m_sBGName.c_str(), seg.m_fRate, seg.m_bFadeLast, seg.m_bRewindMovie, seg.m_bLoop ) );
}
/* If there's an animation plan at all, add a dummy "-nosongbg-" tag to indicate that /* 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. * this file doesn't want a song BG entry added at the end. See SMLoader::TidyUpData.
* This tag will be removed on load. Add it at a very high beat, so it won't cause * This tag will be removed on load. Add it at a very high beat, so it won't cause
* problems if loaded in older versions. */ * problems if loaded in older versions. */
if( !out.m_BackgroundChanges.empty() ) if( b==0 && !out.m_BackgroundChanges[b].empty() )
f.PutLine( "99999=-nosongbg-=1.000=0=0=0 // don't automatically add -songbackground-" ); f.PutLine( "99999=-nosongbg-=1.000=0=0=0 // don't automatically add -songbackground-" );
f.PutLine( ";" ); f.PutLine( ";" );
}
if( out.m_ForegroundChanges.size() ) if( out.m_ForegroundChanges.size() )
{ {
+13 -5
View File
@@ -441,6 +441,7 @@ static Menu g_SongInformation(
static Menu g_BackgroundChange( static Menu g_BackgroundChange(
"ScreenMiniMenuBackgroundChange", "ScreenMiniMenuBackgroundChange",
MenuRow( ScreenEdit::layer, "Layer (applies to new adds)", true, EDIT_MODE_PRACTICE, 0, "0","1" ),
MenuRow( ScreenEdit::rate, "Rate (applies to new adds)", true, EDIT_MODE_PRACTICE, 10, "0%","10%","20%","30%","40%","50%","60%","70%","80%","90%","100%","120%","140%","160%","180%","200%" ), MenuRow( ScreenEdit::rate, "Rate (applies to new adds)", true, EDIT_MODE_PRACTICE, 10, "0%","10%","20%","30%","40%","50%","60%","70%","80%","90%","100%","120%","140%","160%","180%","200%" ),
MenuRow( ScreenEdit::fade_last, "Fade Last (applies to new adds)", true, EDIT_MODE_PRACTICE, 0, "NO","YES" ), MenuRow( ScreenEdit::fade_last, "Fade Last (applies to new adds)", true, EDIT_MODE_PRACTICE, 0, "NO","YES" ),
MenuRow( ScreenEdit::rewind_movie, "Rewind Movie (applies to new adds)", true, EDIT_MODE_PRACTICE, 0, "NO","YES" ), MenuRow( ScreenEdit::rewind_movie, "Rewind Movie (applies to new adds)", true, EDIT_MODE_PRACTICE, 0, "NO","YES" ),
@@ -2073,18 +2074,23 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
// //
// Fill in line enabled/disabled // Fill in line's enabled/disabled
// //
bool bAlreadyBGChangeHere = false; bool bAlreadyBGChangeHere = false;
int iLayer = 0;
BackgroundChange bgChange; BackgroundChange bgChange;
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges, bgc ) for( int l=0; l<NUM_BACKGROUND_LAYERS; l++ )
{
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges[l], bgc )
{ {
if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat ) if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat )
{ {
bAlreadyBGChangeHere = true; bAlreadyBGChangeHere = true;
iLayer = l;
bgChange = *bgc; bgChange = *bgc;
} }
} }
}
g_BackgroundChange.rows[add_random].bEnabled = true; 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_bganimation].bEnabled = g_BackgroundChange.rows[add_song_bganimation].choices.size() > 0;
@@ -2097,6 +2103,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
// set default choices // 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[rate]. SetDefaultChoiceIfPresent( ssprintf("%2.0f%%",bgChange.m_fRate*100) );
g_BackgroundChange.rows[fade_last].iDefaultChoice = bgChange.m_bFadeLast ? 1 : 0; 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[rewind_movie].iDefaultChoice = bgChange.m_bRewindMovie ? 1 : 0;
@@ -2618,15 +2625,16 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec
void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector<int> &iAnswers ) void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector<int> &iAnswers )
{ {
int iLayer = atoi( g_BackgroundChange.rows[layer].choices[iAnswers[layer]] );
BackgroundChange newChange; BackgroundChange newChange;
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges, iter ) FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges[iLayer], iter )
{ {
if( iter->m_fStartBeat == GAMESTATE->m_fSongBeat ) if( iter->m_fStartBeat == GAMESTATE->m_fSongBeat )
{ {
newChange = *iter; newChange = *iter;
// delete the old change. We'll add a new one below. // delete the old change. We'll add a new one below.
m_pSong->m_BackgroundChanges.erase( iter ); m_pSong->m_BackgroundChanges[iLayer].erase( iter );
break; break;
} }
} }
@@ -2659,7 +2667,7 @@ void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector<int> &iAns
newChange.m_bLoop = !!iAnswers[loop]; newChange.m_bLoop = !!iAnswers[loop];
if( newChange.m_sBGName != "" ) if( newChange.m_sBGName != "" )
m_pSong->AddBackgroundChange( newChange ); m_pSong->AddBackgroundChange( iLayer, newChange );
} }
void ScreenEdit::SetupCourseAttacks() void ScreenEdit::SetupCourseAttacks()
+1
View File
@@ -364,6 +364,7 @@ public:
void HandleSongInformationChoice( SongInformationChoice c, const vector<int> &iAnswers ); void HandleSongInformationChoice( SongInformationChoice c, const vector<int> &iAnswers );
enum BGChangeChoice { enum BGChangeChoice {
layer,
rate, rate,
fade_last, fade_last,
rewind_movie, rewind_movie,
+18 -9
View File
@@ -110,10 +110,11 @@ void Song::Reset()
} }
void Song::AddBackgroundChange( BackgroundChange seg ) void Song::AddBackgroundChange( int iLayer, BackgroundChange seg )
{ {
m_BackgroundChanges.push_back( seg ); ASSERT( iLayer >= 0 && iLayer < NUM_BACKGROUND_LAYERS );
SortBackgroundChangesArray( m_BackgroundChanges ); m_BackgroundChanges[iLayer].push_back( seg );
SortBackgroundChangesArray( m_BackgroundChanges[iLayer] );
} }
void Song::AddForegroundChange( BackgroundChange seg ) void Song::AddForegroundChange( BackgroundChange seg )
@@ -143,13 +144,13 @@ void Song::GetDisplayBpms( DisplayBpms &AddTo ) const
} }
} }
CString Song::GetBackgroundAtBeat( float fBeat ) const CString Song::GetBackgroundAtBeat( int iLayer, float fBeat ) const
{ {
unsigned i; unsigned i;
for( i=0; i<m_BackgroundChanges.size()-1; i++ ) for( i=0; i<m_BackgroundChanges[iLayer].size()-1; i++ )
if( m_BackgroundChanges[i+1].m_fStartBeat > fBeat ) if( m_BackgroundChanges[iLayer][i+1].m_fStartBeat > fBeat )
break; break;
return m_BackgroundChanges[i].m_sBGName; return m_BackgroundChanges[iLayer][i].m_sBGName;
} }
@@ -720,7 +721,7 @@ void Song::TidyUpData()
/* Use this->GetBeatFromElapsedTime(0) instead of 0 to start when the /* Use this->GetBeatFromElapsedTime(0) instead of 0 to start when the
* music starts. */ * music starts. */
if( arrayPossibleMovies.size() == 1 ) if( arrayPossibleMovies.size() == 1 )
this->AddBackgroundChange( BackgroundChange(0,arrayPossibleMovies[0],1.f,true,true,false) ); this->AddBackgroundChange( 0, BackgroundChange(0,arrayPossibleMovies[0],1.f,true,true,false) );
} }
@@ -1209,7 +1210,15 @@ bool Song::HasBanner() const {return m_sBannerFile != "" && IsAFile(GetBann
bool Song::HasLyrics() const {return m_sLyricsFile != "" && IsAFile(GetLyricsPath()); } bool Song::HasLyrics() const {return m_sLyricsFile != "" && IsAFile(GetLyricsPath()); }
bool Song::HasBackground() const {return m_sBackgroundFile != "" && IsAFile(GetBackgroundPath()); } bool Song::HasBackground() const {return m_sBackgroundFile != "" && IsAFile(GetBackgroundPath()); }
bool Song::HasCDTitle() const {return m_sCDTitleFile != "" && IsAFile(GetCDTitlePath()); } bool Song::HasCDTitle() const {return m_sCDTitleFile != "" && IsAFile(GetCDTitlePath()); }
bool Song::HasBGChanges() const {return !m_BackgroundChanges.empty(); } bool Song::HasBGChanges() const
{
for( unsigned i=0; i<NUM_BACKGROUND_LAYERS; i++ )
{
if( !m_BackgroundChanges[i].empty() )
return true;
}
return false;
}
CString GetSongAssetPath( CString sPath, const CString &sSongPath ) CString GetSongAssetPath( CString sPath, const CString &sSongPath )
{ {
+6 -1
View File
@@ -229,6 +229,8 @@ void SongManager::LoadStepManiaSongDir( CString sDir, LoadingWindow *ld )
} }
} }
// Why Symlink instead of allowing membership in multiple groups via song tags?
// -Chris
void SongManager::LoadGroupSymLinks(CString sDir, CString sGroupFolder) void SongManager::LoadGroupSymLinks(CString sDir, CString sGroupFolder)
{ {
// Find all symlink files in this folder // Find all symlink files in this folder
@@ -243,14 +245,17 @@ void SongManager::LoadGroupSymLinks(CString sDir, CString sGroupFolder)
Song* pNewSong = new Song; Song* pNewSong = new Song;
if( !pNewSong->LoadFromSongDir( sSymDestination ) ) if( !pNewSong->LoadFromSongDir( sSymDestination ) )
{
delete pNewSong; // The song failed to load. delete pNewSong; // The song failed to load.
}
else else
{ {
const vector<Steps*>& vpSteps = pNewSong->GetAllSteps(); const vector<Steps*>& vpSteps = pNewSong->GetAllSteps();
while( vpSteps.size() ) while( vpSteps.size() )
pNewSong->RemoveSteps( vpSteps[0] ); pNewSong->RemoveSteps( vpSteps[0] );
pNewSong->m_BackgroundChanges.clear(); for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
pNewSong->m_BackgroundChanges[i].clear();
pNewSong->m_bIsSymLink = true; // Very important so we don't double-parse later pNewSong->m_bIsSymLink = true; // Very important so we don't double-parse later
pNewSong->m_sGroupName = sGroupFolder; pNewSong->m_sGroupName = sGroupFolder;
+6 -5
View File
@@ -17,11 +17,12 @@ class Profile;
class StepsID; class StepsID;
struct lua_State; struct lua_State;
#define MAX_EDITS_PER_SONG_PER_PROFILE 5 const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
#define MAX_EDITS_PER_SONG 5*NUM_PROFILE_SLOTS const int MAX_EDITS_PER_SONG = 5*NUM_PROFILE_SLOTS;
extern const int FILE_CACHE_VERSION; extern const int FILE_CACHE_VERSION;
const int NUM_BACKGROUND_LAYERS = 2;
struct BackgroundChange struct BackgroundChange
{ {
@@ -153,18 +154,18 @@ public:
bool Matches(CString sGroup, CString sSong) const; bool Matches(CString sGroup, CString sSong) const;
TimingData m_Timing; TimingData m_Timing;
vector<BackgroundChange> m_BackgroundChanges; // this must be sorted before gameplay vector<BackgroundChange> m_BackgroundChanges[NUM_BACKGROUND_LAYERS]; // these must be sorted before gameplay
vector<BackgroundChange> m_ForegroundChanges; // this must be sorted before gameplay vector<BackgroundChange> m_ForegroundChanges; // this must be sorted before gameplay
vector<LyricSegment> m_LyricSegments; // this must be sorted before gameplay vector<LyricSegment> m_LyricSegments; // this must be sorted before gameplay
void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); } void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); }
void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); } void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); }
void AddBackgroundChange( BackgroundChange seg ); void AddBackgroundChange( int iLayer, BackgroundChange seg );
void AddForegroundChange( BackgroundChange seg ); void AddForegroundChange( BackgroundChange seg );
void AddLyricSegment( LyricSegment seg ); void AddLyricSegment( LyricSegment seg );
void GetDisplayBpms( DisplayBpms &AddTo ) const; void GetDisplayBpms( DisplayBpms &AddTo ) const;
CString GetBackgroundAtBeat( float fBeat ) const; CString GetBackgroundAtBeat( int iLayer, float fBeat ) const;
float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); } float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); }
void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); } void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }