fix MiniMenu crashes for rows with 0 choices

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