add multiple background layers
This commit is contained in:
+108
-74
@@ -53,13 +53,17 @@ static RageColor GetBrightnessColor( float fBrightnessPercent )
|
||||
}
|
||||
|
||||
Background::Background()
|
||||
{
|
||||
m_pDancingCharacters = NULL;
|
||||
m_bInitted = false;
|
||||
}
|
||||
|
||||
Background::Layer::Layer()
|
||||
{
|
||||
m_iCurBGChangeIndex = -1;
|
||||
m_pCurrentBGA = NULL;
|
||||
m_pFadingBGA = NULL;
|
||||
m_fSecsLeftInFade = 0;
|
||||
m_pDancingCharacters = NULL;
|
||||
m_bInitted = false;
|
||||
}
|
||||
|
||||
void Background::Init()
|
||||
@@ -114,6 +118,14 @@ Background::~Background()
|
||||
}
|
||||
|
||||
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();
|
||||
iter != m_BGAnimations.end();
|
||||
@@ -125,10 +137,8 @@ void Background::Unload()
|
||||
|
||||
m_pCurrentBGA = NULL;
|
||||
m_pFadingBGA = NULL;
|
||||
m_pSong = NULL;
|
||||
m_fSecsLeftInFade = 0;
|
||||
m_iCurBGChangeIndex = -1;
|
||||
m_fLastMusicSeconds = -9999;
|
||||
}
|
||||
|
||||
Actor *MakeVisualization( const CString &sVisPath )
|
||||
@@ -163,7 +173,7 @@ Actor *MakeMovie( const CString &sMoviePath )
|
||||
return pSprite;
|
||||
}
|
||||
|
||||
Actor *Background::CreateSongBGA( CString sBGName ) const
|
||||
Actor *Background::Layer::CreateSongBGA( const Song *pSong, CString sBGName ) const
|
||||
{
|
||||
BGAnimation *pTempBGA;
|
||||
|
||||
@@ -173,7 +183,7 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
|
||||
CStringArray asFiles;
|
||||
|
||||
// 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 default.xml exists, use the regular generic actor load. However,
|
||||
@@ -187,7 +197,7 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
|
||||
return pTempBGA;
|
||||
}
|
||||
// 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() )
|
||||
{
|
||||
const CString sExt = GetExtension( asFiles[0]) ;
|
||||
@@ -214,9 +224,9 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
|
||||
GetDirListing( BG_ANIMS_DIR+sBGName, asFiles, true, true );
|
||||
if( !asFiles.empty() )
|
||||
{
|
||||
pTempBGA = new BGAnimation;
|
||||
pTempBGA->LoadFromAniDir( asFiles[0] );
|
||||
return pTempBGA;
|
||||
Actor *pActor = ActorUtil::MakeActor( asFiles[0] );
|
||||
ASSERT( pActor );
|
||||
return pActor;
|
||||
}
|
||||
|
||||
// Look for BGAnims in the BGAnims dir
|
||||
@@ -228,7 +238,7 @@ Actor *Background::CreateSongBGA( CString sBGName ) const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CString Background::CreateRandomBGA( CString sPreferredSubDir )
|
||||
CString Background::Layer::CreateRandomBGA( const Song *pSong, CString sPreferredSubDir )
|
||||
{
|
||||
if( sPreferredSubDir.Right(1) != "/" )
|
||||
sPreferredSubDir += '/';
|
||||
@@ -338,9 +348,9 @@ void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const Timing
|
||||
//bool bFade = PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_RANDOMMOVIES ||
|
||||
// PREFSMAN->m_BackgroundMode==PrefsManager::BGMODE_MOVIEVIS;
|
||||
|
||||
CString sBGName = CreateRandomBGA( sPreferredSubDir );
|
||||
CString sBGName = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir );
|
||||
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
|
||||
@@ -356,9 +366,9 @@ void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const Timing
|
||||
if( bpmseg.m_iStartIndex < iStartIndex || bpmseg.m_iStartIndex > iEndIndex )
|
||||
continue; // skip
|
||||
|
||||
CString sBGName = CreateRandomBGA( sPreferredSubDir );
|
||||
CString sBGName = m_Layer[0].CreateRandomBGA( m_pSong, sPreferredSubDir );
|
||||
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() )
|
||||
{
|
||||
// Load all song-specified backgrounds
|
||||
for( unsigned i=0; i<pSong->m_BackgroundChanges.size(); i++ )
|
||||
for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
|
||||
{
|
||||
BackgroundChange change = pSong->m_BackgroundChanges[i];
|
||||
CString &sBGName = change.m_sBGName;
|
||||
|
||||
bool bIsAlreadyLoaded = m_BGAnimations.find(sBGName) != m_BGAnimations.end();
|
||||
Layer &layer = m_Layer[i];
|
||||
|
||||
if( sBGName.CompareNoCase("-random-")!=0 && !bIsAlreadyLoaded )
|
||||
// Load all song-specified backgrounds
|
||||
FOREACH_CONST( BackgroundChange, pSong->m_BackgroundChanges[i], bgc )
|
||||
{
|
||||
Actor *pTempBGA = CreateSongBGA( sBGName );
|
||||
if( pTempBGA )
|
||||
BackgroundChange change = *bgc;
|
||||
CString &sBGName = change.m_sBGName;
|
||||
|
||||
bool bIsAlreadyLoaded = layer.m_BGAnimations.find(sBGName) != layer.m_BGAnimations.end();
|
||||
|
||||
if( sBGName.CompareNoCase("-random-")!=0 && !bIsAlreadyLoaded )
|
||||
{
|
||||
m_BGAnimations[sBGName] = pTempBGA;
|
||||
}
|
||||
else // the background was not found. Use a random one instead
|
||||
{
|
||||
sBGName = CreateRandomBGA( pSong->m_sGroupName );
|
||||
if( sBGName == "" )
|
||||
sBGName = STATIC_BACKGROUND;
|
||||
Actor *pTempBGA = layer.CreateSongBGA( m_pSong, sBGName );
|
||||
if( pTempBGA )
|
||||
{
|
||||
layer.m_BGAnimations[sBGName] = pTempBGA;
|
||||
}
|
||||
else // the background was not found. Use a random one instead
|
||||
{
|
||||
sBGName = layer.CreateRandomBGA( pSong, pSong->m_sGroupName );
|
||||
if( sBGName == "" )
|
||||
sBGName = STATIC_BACKGROUND;
|
||||
}
|
||||
}
|
||||
|
||||
layer.m_aBGChanges.push_back( change );
|
||||
}
|
||||
|
||||
m_aBGChanges.push_back( change );
|
||||
}
|
||||
}
|
||||
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 );
|
||||
|
||||
// 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
|
||||
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
|
||||
* background. */
|
||||
if( m_aBGChanges.empty() || m_aBGChanges.front().m_fStartBeat >= 0 )
|
||||
m_aBGChanges.insert( m_aBGChanges.begin(), BackgroundChange(-10000,STATIC_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) );
|
||||
|
||||
// If any BGChanges use the background image, load it.
|
||||
bool bStaticBackgroundUsed = false;
|
||||
for( unsigned i=0; i<m_aBGChanges.size(); i++ )
|
||||
if( m_aBGChanges[i].m_sBGName == STATIC_BACKGROUND )
|
||||
for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
|
||||
if( mainlayer.m_aBGChanges[i].m_sBGName == STATIC_BACKGROUND )
|
||||
bStaticBackgroundUsed = true;
|
||||
if( bStaticBackgroundUsed )
|
||||
{
|
||||
@@ -442,33 +467,33 @@ void Background::LoadFromSong( const Song* pSong )
|
||||
Sprite* pSprite = new Sprite;
|
||||
pSprite->LoadBG( sSongBGPath );
|
||||
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.
|
||||
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-") )
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
LoadFromRandom( fStartBeat, fLastBeat, pSong->m_Timing, pSong->m_sGroupName );
|
||||
}
|
||||
|
||||
// At this point, we shouldn't have any BGChanges to "". "" is an invalid name.
|
||||
for( unsigned i=0; i<m_aBGChanges.size(); i++ )
|
||||
ASSERT( !m_aBGChanges[i].m_sBGName.empty() );
|
||||
for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
|
||||
ASSERT( !mainlayer.m_aBGChanges[i].m_sBGName.empty() );
|
||||
|
||||
|
||||
// Re-sort.
|
||||
SortBackgroundChangesArray( m_aBGChanges );
|
||||
SortBackgroundChangesArray( mainlayer.m_aBGChanges );
|
||||
|
||||
m_DangerAll.SetXY( (float)LEFT_EDGE, (float)TOP_EDGE );
|
||||
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
|
||||
* point, we havn't run the OnCommand yet, so it'll override correctly. */
|
||||
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;
|
||||
|
||||
@@ -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() )
|
||||
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. */
|
||||
void Background::UpdateCurBGChange( float fCurrentTime )
|
||||
void Background::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime )
|
||||
{
|
||||
ASSERT( fCurrentTime != GameState::MUSIC_SECONDS_INVALID );
|
||||
|
||||
@@ -542,7 +567,7 @@ void Background::UpdateCurBGChange( float fCurrentTime )
|
||||
|
||||
float fBeat, fBPS;
|
||||
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. */
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
float fDeltaTime = fCurrentTime - fStartSecond;
|
||||
@@ -593,17 +618,16 @@ void Background::UpdateCurBGChange( float fCurrentTime )
|
||||
else // we're not changing backgrounds
|
||||
{
|
||||
/* This is affected by the music rate. */
|
||||
float fDeltaTime = fCurrentTime - m_fLastMusicSeconds;
|
||||
float fDeltaTime = fCurrentTime - fLastMusicSeconds;
|
||||
fDeltaTime /= fRate;
|
||||
if( m_pCurrentBGA )
|
||||
m_pCurrentBGA->Update( max( fDeltaTime, 0 ) );
|
||||
}
|
||||
|
||||
float fDeltaTime = fCurrentTime - m_fLastMusicSeconds;
|
||||
float fDeltaTime = fCurrentTime - fLastMusicSeconds;
|
||||
fDeltaTime /= fRate;
|
||||
if( m_pFadingBGA )
|
||||
m_pFadingBGA->Update( max( fCurrentTime - m_fLastMusicSeconds, 0 ) );
|
||||
m_fLastMusicSeconds = fCurrentTime;
|
||||
m_pFadingBGA->Update( max( fCurrentTime - fLastMusicSeconds, 0 ) );
|
||||
}
|
||||
|
||||
void Background::Update( float fDeltaTime )
|
||||
@@ -624,28 +648,33 @@ void Background::Update( float 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.
|
||||
* 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
|
||||
* off sync. */
|
||||
UpdateCurBGChange( GAMESTATE->m_fMusicSeconds );
|
||||
|
||||
if( m_pFadingBGA )
|
||||
for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
|
||||
{
|
||||
m_pFadingBGA->Update( fDeltaTime );
|
||||
m_fSecsLeftInFade -= fDeltaTime;
|
||||
float fPercentOpaque = m_fSecsLeftInFade / FADE_SECONDS;
|
||||
m_pFadingBGA->SetDiffuse( RageColor(1,1,1,fPercentOpaque) );
|
||||
if( fPercentOpaque <= 0 )
|
||||
Layer &layer = m_Layer[i];
|
||||
layer.UpdateCurBGChange( m_pSong, m_fLastMusicSeconds, GAMESTATE->m_fMusicSeconds );
|
||||
|
||||
if( layer.m_pFadingBGA )
|
||||
{
|
||||
/* Reset its diffuse color, in case we reuse it. */
|
||||
m_pFadingBGA->SetDiffuse( RageColor(1,1,1,1) );
|
||||
m_pFadingBGA = NULL;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_pDancingCharacters )
|
||||
m_pDancingCharacters->Update( fDeltaTime );
|
||||
m_fLastMusicSeconds = GAMESTATE->m_fMusicSeconds;
|
||||
}
|
||||
|
||||
void Background::DrawPrimitives()
|
||||
@@ -665,10 +694,15 @@ void Background::DrawPrimitives()
|
||||
{
|
||||
if( m_pDancingCharacters )
|
||||
m_pDancingCharacters->m_bDrawDangerLight = false;
|
||||
if( m_pCurrentBGA )
|
||||
m_pCurrentBGA->Draw();
|
||||
if( m_pFadingBGA )
|
||||
m_pFadingBGA->Draw();
|
||||
|
||||
for( int i=0; i<NUM_BACKGROUND_LAYERS; i++ )
|
||||
{
|
||||
Layer &layer = m_Layer[i];
|
||||
if( layer.m_pCurrentBGA )
|
||||
layer.m_pCurrentBGA->Draw();
|
||||
if( layer.m_pFadingBGA )
|
||||
layer.m_pFadingBGA->Draw();
|
||||
}
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
|
||||
+23
-14
@@ -49,30 +49,39 @@ public:
|
||||
protected:
|
||||
const Song *m_pSong;
|
||||
void LoadFromRandom( float fFirstBeat, float fLastBeat, const TimingData &timing, CString sPreferredSubDir );
|
||||
int FindBGSegmentForBeat( float fBeat ) const;
|
||||
|
||||
bool IsDangerAllVisible();
|
||||
void UpdateCurBGChange( float fCurrentTime );
|
||||
|
||||
bool m_bInitted;
|
||||
DancingCharacters* m_pDancingCharacters;
|
||||
|
||||
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 );
|
||||
|
||||
map<CString,Actor*> m_BGAnimations;
|
||||
deque<CString> m_RandomBGAnimations;
|
||||
vector<BackgroundChange> m_aBGChanges;
|
||||
int m_iCurBGChangeIndex;
|
||||
Actor *m_pCurrentBGA;
|
||||
Actor *m_pFadingBGA;
|
||||
float m_fSecsLeftInFade;
|
||||
};
|
||||
Layer m_Layer[NUM_BACKGROUND_LAYERS];
|
||||
|
||||
float m_fLastMusicSeconds;
|
||||
|
||||
BGAnimation m_DangerPlayer[NUM_PLAYERS];
|
||||
BGAnimation m_DangerAll;
|
||||
|
||||
BGAnimation m_DeadPlayer[NUM_PLAYERS];
|
||||
|
||||
Actor *CreateSongBGA( CString sBGName ) const;
|
||||
CString CreateRandomBGA( CString sPreferredSubDir );
|
||||
|
||||
map<CString,Actor*> m_BGAnimations;
|
||||
deque<CString> m_RandomBGAnimations;
|
||||
vector<BackgroundChange> m_aBGChanges;
|
||||
int m_iCurBGChangeIndex;
|
||||
Actor *m_pCurrentBGA;
|
||||
Actor *m_pFadingBGA;
|
||||
float m_fSecsLeftInFade;
|
||||
float m_fLastMusicSeconds;
|
||||
|
||||
// cover up the edge of animations that might hang outside of the background rectangle
|
||||
Quad m_quadBorderLeft, m_quadBorderTop, m_quadBorderRight, m_quadBorderBottom;
|
||||
|
||||
+17
-13
@@ -531,22 +531,26 @@ void NoteField::DrawPrimitives()
|
||||
break;
|
||||
case EDIT_MODE_FULL:
|
||||
{
|
||||
vector<BackgroundChange> &aBackgroundChanges = GAMESTATE->m_pCurSong->m_BackgroundChanges;
|
||||
for( unsigned i=0; i<aBackgroundChanges.size(); i++ )
|
||||
for( int b=0; b<NUM_BACKGROUND_LAYERS; b++ )
|
||||
{
|
||||
if(aBackgroundChanges[i].m_fStartBeat >= fFirstBeatToDraw &&
|
||||
aBackgroundChanges[i].m_fStartBeat <= fLastBeatToDraw)
|
||||
vector<BackgroundChange> &aBackgroundChanges = GAMESTATE->m_pCurSong->m_BackgroundChanges[b];
|
||||
for( unsigned i=0; i<aBackgroundChanges.size(); i++ )
|
||||
{
|
||||
const BackgroundChange& change = aBackgroundChanges[i];
|
||||
CString sChangeText = ssprintf("%s\n%.0f%%%s%s%s",
|
||||
change.m_sBGName.c_str(),
|
||||
change.m_fRate*100,
|
||||
change.m_bFadeLast ? " Fade" : "",
|
||||
change.m_bRewindMovie ? " Rewind" : "",
|
||||
change.m_bLoop ? " Loop" : "" );
|
||||
if( aBackgroundChanges[i].m_fStartBeat >= fFirstBeatToDraw &&
|
||||
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" : "",
|
||||
change.m_bRewindMovie ? " Rewind" : "",
|
||||
change.m_bLoop ? " Loop" : "" );
|
||||
|
||||
if( IS_ON_SCREEN(change.m_fStartBeat) )
|
||||
DrawBGChangeText( change.m_fStartBeat, sChangeText );
|
||||
if( IS_ON_SCREEN(change.m_fStartBeat) )
|
||||
DrawBGChangeText( change.m_fStartBeat, sChangeText );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,11 +87,14 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
|
||||
for( unsigned i=0; i<msd.GetNumValues(); 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 );
|
||||
else if( 0==stricmp(sValueName,"STOPS") || 0==stricmp(sValueName,"FREEZES") )
|
||||
}
|
||||
else if( sValueName=="STOPS" || sValueName=="FREEZES" )
|
||||
{
|
||||
CStringArray 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;
|
||||
split( sParams[1], ",", arrayBPMChangeExpressions );
|
||||
@@ -194,99 +197,100 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
|
||||
{
|
||||
int iNumParams = msd.GetNumParams(i);
|
||||
const MsdFile::value_t &sParams = msd.GetValue(i);
|
||||
const CString sValueName = sParams[0];
|
||||
CString sValueName = sParams[0];
|
||||
sValueName.MakeUpper();
|
||||
|
||||
// handle the data
|
||||
/* Don't use GetMainAndSubTitlesFromFullTitle; that's only for heuristically
|
||||
* splitting other formats that *don't* natively support #SUBTITLE. */
|
||||
if( 0==stricmp(sValueName,"TITLE") )
|
||||
if( sValueName=="TITLE" )
|
||||
out.m_sMainTitle = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"SUBTITLE") )
|
||||
else if( sValueName=="SUBTITLE" )
|
||||
out.m_sSubTitle = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"ARTIST") )
|
||||
else if( sValueName=="ARTIST" )
|
||||
out.m_sArtist = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"TITLETRANSLIT") )
|
||||
else if( sValueName=="TITLETRANSLIT" )
|
||||
out.m_sMainTitleTranslit = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"SUBTITLETRANSLIT") )
|
||||
else if( sValueName=="SUBTITLETRANSLIT" )
|
||||
out.m_sSubTitleTranslit = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"ARTISTTRANSLIT") )
|
||||
else if( sValueName=="ARTISTTRANSLIT" )
|
||||
out.m_sArtistTranslit = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"GENRE") )
|
||||
else if( sValueName=="GENRE" )
|
||||
out.m_sGenre = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"CREDIT") )
|
||||
else if( sValueName=="CREDIT" )
|
||||
out.m_sCredit = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"BANNER") )
|
||||
else if( sValueName=="BANNER" )
|
||||
out.m_sBannerFile = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"BACKGROUND") )
|
||||
else if( sValueName=="BACKGROUND" )
|
||||
out.m_sBackgroundFile = sParams[1];
|
||||
|
||||
/* 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];
|
||||
|
||||
else if( 0==stricmp(sValueName,"CDTITLE") )
|
||||
else if( sValueName=="CDTITLE" )
|
||||
out.m_sCDTitleFile = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"MUSIC") )
|
||||
else if( sValueName=="MUSIC" )
|
||||
out.m_sMusicFile = sParams[1];
|
||||
|
||||
else if( 0==stricmp(sValueName,"MUSICLENGTH") )
|
||||
else if( sValueName=="MUSICLENGTH" )
|
||||
{
|
||||
if(!FromCache)
|
||||
continue;
|
||||
out.m_fMusicLengthSeconds = strtof( sParams[1], NULL );
|
||||
}
|
||||
|
||||
else if( 0==stricmp(sValueName,"MUSICBYTES") )
|
||||
else if( sValueName=="MUSICBYTES" )
|
||||
; /* ignore */
|
||||
|
||||
/* We calculate these. Some SMs in circulation have bogus values for
|
||||
* these, so make sure we always calculate it ourself. */
|
||||
else if( 0==stricmp(sValueName,"FIRSTBEAT") )
|
||||
else if( sValueName=="FIRSTBEAT" )
|
||||
{
|
||||
if(!FromCache)
|
||||
continue;
|
||||
out.m_fFirstBeat = strtof( sParams[1], NULL );
|
||||
}
|
||||
|
||||
else if( 0==stricmp(sValueName,"LASTBEAT") )
|
||||
else if( sValueName=="LASTBEAT" )
|
||||
{
|
||||
if(!FromCache)
|
||||
LOG->Trace("Ignored #LASTBEAT (cache only)");
|
||||
out.m_fLastBeat = strtof( sParams[1], NULL );
|
||||
}
|
||||
else if( 0==stricmp(sValueName,"SONGFILENAME") )
|
||||
else if( sValueName=="SONGFILENAME" )
|
||||
{
|
||||
if( FromCache )
|
||||
out.m_sSongFileName = sParams[1];
|
||||
}
|
||||
else if( 0==stricmp(sValueName,"HASMUSIC") )
|
||||
else if( sValueName=="HASMUSIC" )
|
||||
{
|
||||
if( FromCache )
|
||||
out.m_bHasMusic = atoi( sParams[1] ) != 0;
|
||||
}
|
||||
else if( 0==stricmp(sValueName,"HASBANNER") )
|
||||
else if( sValueName=="HASBANNER" )
|
||||
{
|
||||
if( FromCache )
|
||||
out.m_bHasBanner = atoi( sParams[1] ) != 0;
|
||||
}
|
||||
|
||||
else if( 0==stricmp(sValueName,"SAMPLESTART") )
|
||||
else if( sValueName=="SAMPLESTART" )
|
||||
out.m_fMusicSampleStartSeconds = HHMMSSToSeconds( sParams[1] );
|
||||
|
||||
else if( 0==stricmp(sValueName,"SAMPLELENGTH") )
|
||||
else if( sValueName=="SAMPLELENGTH" )
|
||||
out.m_fMusicSampleLengthSeconds = HHMMSSToSeconds( sParams[1] );
|
||||
|
||||
else if( 0==stricmp(sValueName,"DISPLAYBPM") )
|
||||
else if( sValueName=="DISPLAYBPM" )
|
||||
{
|
||||
// #DISPLAYBPM:[xxx][xxx:xxx]|[*];
|
||||
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"))
|
||||
out.m_SelectionDisplay = out.SHOW_ALWAYS;
|
||||
@@ -314,20 +318,30 @@ 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());
|
||||
}
|
||||
|
||||
else if( 0==stricmp(sValueName,"BGCHANGES") || 0==stricmp(sValueName,"ANIMATIONS") )
|
||||
else if( sValueName=="BGCHANGES" || sValueName=="ANIMATIONS" )
|
||||
{
|
||||
CStringArray aBGChangeExpressions;
|
||||
split( sParams[1], ",", aBGChangeExpressions );
|
||||
int iLayer = 0;
|
||||
sscanf( sValueName, "BGCHANGES%d", &iLayer );
|
||||
|
||||
for( unsigned b=0; b<aBGChangeExpressions.size(); b++ )
|
||||
if( iLayer < 0 && iLayer >= NUM_BACKGROUND_LAYERS )
|
||||
{
|
||||
BackgroundChange change;
|
||||
if( LoadFromBGChangesString( change, aBGChangeExpressions[b] ) )
|
||||
out.AddBackgroundChange( change );
|
||||
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;
|
||||
split( sParams[1], ",", aBGChangeExpressions );
|
||||
|
||||
for( unsigned b=0; b<aBGChangeExpressions.size(); b++ )
|
||||
{
|
||||
BackgroundChange change;
|
||||
if( LoadFromBGChangesString( change, aBGChangeExpressions[b] ) )
|
||||
out.AddBackgroundChange( iLayer, change );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if( 0==stricmp(sValueName,"FGCHANGES") )
|
||||
else if( sValueName=="FGCHANGES" )
|
||||
{
|
||||
CStringArray 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;
|
||||
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 )
|
||||
{
|
||||
@@ -371,8 +385,8 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
|
||||
|
||||
out.AddSteps( pNewNotes );
|
||||
}
|
||||
else if( 0==stricmp(sValueName,"OFFSET") || 0==stricmp(sValueName,"BPMS") ||
|
||||
0==stricmp(sValueName,"STOPS") || 0==stricmp(sValueName,"FREEZES") )
|
||||
else if( sValueName=="OFFSET" || sValueName=="BPMS" ||
|
||||
sValueName=="STOPS" || sValueName=="FREEZES" )
|
||||
;
|
||||
else
|
||||
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);
|
||||
const MsdFile::value_t &sParams = msd.GetValue(i);
|
||||
const CString sValueName = sParams[0];
|
||||
CString sValueName = sParams[0];
|
||||
sValueName.MakeUpper();
|
||||
|
||||
// handle the data
|
||||
if( 0==stricmp(sValueName,"SONG") )
|
||||
if( sValueName=="SONG" )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
@@ -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
|
||||
* 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() )
|
||||
{
|
||||
/* BGChanges have been sorted. On the odd chance that a BGChange exists
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "NoteTypes.h"
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include "Foreach.h"
|
||||
|
||||
void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out )
|
||||
{
|
||||
@@ -80,21 +81,27 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out )
|
||||
f.Write( "," );
|
||||
}
|
||||
f.PutLine( ";" );
|
||||
|
||||
f.Write( "#BGCHANGES:" );
|
||||
for( unsigned i=0; i<out.m_BackgroundChanges.size(); i++ )
|
||||
{
|
||||
const BackgroundChange &seg = out.m_BackgroundChanges[i];
|
||||
|
||||
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 ) );
|
||||
for( unsigned b=0; b<NUM_BACKGROUND_LAYERS; b++ )
|
||||
{
|
||||
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 ) );
|
||||
|
||||
/* 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 tag will be removed on load. Add it at a very high beat, so it won't cause
|
||||
* problems if loaded in older versions. */
|
||||
if( b==0 && !out.m_BackgroundChanges[b].empty() )
|
||||
f.PutLine( "99999=-nosongbg-=1.000=0=0=0 // don't automatically add -songbackground-" );
|
||||
f.PutLine( ";" );
|
||||
}
|
||||
/* 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 tag will be removed on load. Add it at a very high beat, so it won't cause
|
||||
* problems if loaded in older versions. */
|
||||
if( !out.m_BackgroundChanges.empty() )
|
||||
f.PutLine( "99999=-nosongbg-=1.000=0=0=0 // don't automatically add -songbackground-" );
|
||||
f.PutLine( ";" );
|
||||
|
||||
if( out.m_ForegroundChanges.size() )
|
||||
{
|
||||
|
||||
@@ -441,6 +441,7 @@ static Menu g_SongInformation(
|
||||
|
||||
static Menu g_BackgroundChange(
|
||||
"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::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" ),
|
||||
@@ -2073,16 +2074,21 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
|
||||
|
||||
|
||||
//
|
||||
// Fill in line enabled/disabled
|
||||
// Fill in line's enabled/disabled
|
||||
//
|
||||
bool bAlreadyBGChangeHere = false;
|
||||
int iLayer = 0;
|
||||
BackgroundChange bgChange;
|
||||
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges, bgc )
|
||||
for( int l=0; l<NUM_BACKGROUND_LAYERS; l++ )
|
||||
{
|
||||
if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat )
|
||||
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges[l], bgc )
|
||||
{
|
||||
bAlreadyBGChangeHere = true;
|
||||
bgChange = *bgc;
|
||||
if( bgc->m_fStartBeat == GAMESTATE->m_fSongBeat )
|
||||
{
|
||||
bAlreadyBGChangeHere = true;
|
||||
iLayer = l;
|
||||
bgChange = *bgc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2097,6 +2103,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
|
||||
|
||||
|
||||
// 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;
|
||||
@@ -2618,15 +2625,16 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec
|
||||
|
||||
void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector<int> &iAnswers )
|
||||
{
|
||||
int iLayer = atoi( g_BackgroundChange.rows[layer].choices[iAnswers[layer]] );
|
||||
BackgroundChange newChange;
|
||||
|
||||
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges, iter )
|
||||
FOREACH( BackgroundChange, m_pSong->m_BackgroundChanges[iLayer], iter )
|
||||
{
|
||||
if( iter->m_fStartBeat == GAMESTATE->m_fSongBeat )
|
||||
{
|
||||
newChange = *iter;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -2659,7 +2667,7 @@ void ScreenEdit::HandleBGChangeChoice( BGChangeChoice c, const vector<int> &iAns
|
||||
newChange.m_bLoop = !!iAnswers[loop];
|
||||
|
||||
if( newChange.m_sBGName != "" )
|
||||
m_pSong->AddBackgroundChange( newChange );
|
||||
m_pSong->AddBackgroundChange( iLayer, newChange );
|
||||
}
|
||||
|
||||
void ScreenEdit::SetupCourseAttacks()
|
||||
|
||||
@@ -364,6 +364,7 @@ public:
|
||||
void HandleSongInformationChoice( SongInformationChoice c, const vector<int> &iAnswers );
|
||||
|
||||
enum BGChangeChoice {
|
||||
layer,
|
||||
rate,
|
||||
fade_last,
|
||||
rewind_movie,
|
||||
|
||||
+18
-9
@@ -110,10 +110,11 @@ void Song::Reset()
|
||||
}
|
||||
|
||||
|
||||
void Song::AddBackgroundChange( BackgroundChange seg )
|
||||
void Song::AddBackgroundChange( int iLayer, BackgroundChange seg )
|
||||
{
|
||||
m_BackgroundChanges.push_back( seg );
|
||||
SortBackgroundChangesArray( m_BackgroundChanges );
|
||||
ASSERT( iLayer >= 0 && iLayer < NUM_BACKGROUND_LAYERS );
|
||||
m_BackgroundChanges[iLayer].push_back( seg );
|
||||
SortBackgroundChangesArray( m_BackgroundChanges[iLayer] );
|
||||
}
|
||||
|
||||
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;
|
||||
for( i=0; i<m_BackgroundChanges.size()-1; i++ )
|
||||
if( m_BackgroundChanges[i+1].m_fStartBeat > fBeat )
|
||||
for( i=0; i<m_BackgroundChanges[iLayer].size()-1; i++ )
|
||||
if( m_BackgroundChanges[iLayer][i+1].m_fStartBeat > fBeat )
|
||||
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
|
||||
* music starts. */
|
||||
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::HasBackground() const {return m_sBackgroundFile != "" && IsAFile(GetBackgroundPath()); }
|
||||
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 )
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
// Find all symlink files in this folder
|
||||
@@ -243,14 +245,17 @@ void SongManager::LoadGroupSymLinks(CString sDir, CString sGroupFolder)
|
||||
|
||||
Song* pNewSong = new Song;
|
||||
if( !pNewSong->LoadFromSongDir( sSymDestination ) )
|
||||
{
|
||||
delete pNewSong; // The song failed to load.
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector<Steps*>& vpSteps = pNewSong->GetAllSteps();
|
||||
while( vpSteps.size() )
|
||||
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_sGroupName = sGroupFolder;
|
||||
|
||||
@@ -17,11 +17,12 @@ class Profile;
|
||||
class StepsID;
|
||||
struct lua_State;
|
||||
|
||||
#define MAX_EDITS_PER_SONG_PER_PROFILE 5
|
||||
#define MAX_EDITS_PER_SONG 5*NUM_PROFILE_SLOTS
|
||||
const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
|
||||
const int MAX_EDITS_PER_SONG = 5*NUM_PROFILE_SLOTS;
|
||||
|
||||
extern const int FILE_CACHE_VERSION;
|
||||
|
||||
const int NUM_BACKGROUND_LAYERS = 2;
|
||||
|
||||
struct BackgroundChange
|
||||
{
|
||||
@@ -153,18 +154,18 @@ public:
|
||||
bool Matches(CString sGroup, CString sSong) const;
|
||||
|
||||
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<LyricSegment> m_LyricSegments; // this must be sorted before gameplay
|
||||
|
||||
void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( 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 AddLyricSegment( LyricSegment seg );
|
||||
|
||||
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 ); }
|
||||
void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }
|
||||
|
||||
Reference in New Issue
Block a user