Files
itgmania212121/stepmania/src/Background.cpp
T

1066 lines
32 KiB
C++
Raw Normal View History

2003-02-16 04:01:45 +00:00
#include "global.h"
#include "Background.h"
#include "RageUtil.h"
2002-05-01 19:14:55 +00:00
#include "GameConstantsAndTypes.h"
2002-07-27 19:29:51 +00:00
#include "RageException.h"
#include "RageTimer.h"
2003-03-24 20:57:19 +00:00
#include "RageLog.h"
#include "RageTextureManager.h"
#include "GameState.h"
#include "PrefsManager.h"
#include "NoteTypes.h"
#include "Steps.h"
2003-06-27 08:06:22 +00:00
#include "DancingCharacters.h"
2003-08-31 07:28:19 +00:00
#include "BeginnerHelper.h"
2005-02-16 03:25:45 +00:00
#include "StatsManager.h"
#include "ScreenDimensions.h"
#include "ThemeMetric.h"
#include "PlayerState.h"
2005-01-26 11:21:43 +00:00
#include "Command.h"
2005-02-25 06:56:03 +00:00
#include "ActorUtil.h"
2004-01-23 02:23:11 +00:00
#include <set>
#include <float.h>
#include "XmlFile.h"
#include "XmlFileUtil.h"
#include "BackgroundUtil.h"
2005-06-04 21:22:50 +00:00
#include "song.h"
2005-08-31 19:17:39 +00:00
#include "AutoActor.h"
2005-12-01 00:07:47 +00:00
static ThemeMetric<float> LEFT_EDGE ("Background","LeftEdge");
static ThemeMetric<float> TOP_EDGE ("Background","TopEdge");
static ThemeMetric<float> RIGHT_EDGE ("Background","RightEdge");
static ThemeMetric<float> BOTTOM_EDGE ("Background","BottomEdge");
#define RECT_BACKGROUND RectF (LEFT_EDGE,TOP_EDGE,RIGHT_EDGE,BOTTOM_EDGE)
2005-12-01 00:07:47 +00:00
static ThemeMetric<bool> BLINK_DANGER_ALL ("Background","BlinkDangerAll");
static ThemeMetric<bool> DANGER_ALL_IS_OPAQUE ("Background","DangerAllIsOpaque");
static ThemeMetric<apActorCommands> BRIGHTNESS_FADE_COMMAND ("Background","BrightnessFadeCommand");
static ThemeMetric<float> CLAMP_OUTPUT_PERCENT ("Background","ClampOutputPercent");
2002-07-11 19:02:26 +00:00
2005-12-01 00:08:36 +00:00
// Width of the region separating the left and right brightness areas:
static float g_fBackgroundCenterWidth = 40;
2005-06-04 21:22:50 +00:00
class BrightnessOverlay: public ActorFrame
{
public:
BrightnessOverlay();
void Update( float fDeltaTime );
void FadeToActualBrightness();
void SetActualBrightness();
void Set( float fBrightness );
private:
Quad m_quadBGBrightness[NUM_PLAYERS];
Quad m_quadBGBrightnessFade;
};
struct BackgroundTransition
{
apActorCommands cmdLeaves;
apActorCommands cmdRoot;
};
class BackgroundImpl : public ActorFrame
{
public:
BackgroundImpl();
~BackgroundImpl();
void Init();
virtual void LoadFromSong( const Song *pSong );
virtual void Unload();
virtual void ProcessMessages( float fDeltaTime );
2005-06-04 21:22:50 +00:00
virtual void Update( float fDeltaTime );
virtual void DrawPrimitives();
void FadeToActualBrightness() { m_Brightness.FadeToActualBrightness(); }
void SetBrightness( float fBrightness ) { m_Brightness.Set(fBrightness); } /* overrides pref and Cover */
DancingCharacters* GetDancingCharacters() { return m_pDancingCharacters; };
2005-07-18 01:52:01 +00:00
void GetLoadedBackgroundChanges( vector<BackgroundChange> *pBackgroundChangesOut[NUM_BackgroundLayer] );
2005-06-04 21:22:50 +00:00
protected:
bool m_bInitted;
DancingCharacters* m_pDancingCharacters;
const Song *m_pSong;
2006-01-22 01:00:06 +00:00
map<RString,BackgroundTransition> m_mapNameToTransition;
2005-06-04 21:22:50 +00:00
deque<BackgroundDef> m_RandomBGAnimations; // random background to choose from. These may or may not be loaded into m_BGAnimations.
void LoadFromRandom( float fFirstBeat, float fEndBeat, const BackgroundChange &change );
2005-06-04 21:22:50 +00:00
bool IsDangerAllVisible();
class Layer
{
public:
Layer();
void Unload();
// return true if created and added to m_BGAnimations
bool CreateBackground( const Song *pSong, const BackgroundDef &bd );
// return def of the background that was created and added to m_BGAnimations. calls CreateBackground
2006-01-22 01:00:06 +00:00
BackgroundDef CreateRandomBGA( const Song *pSong, const RString &sEffect, deque<BackgroundDef> &RandomBGAnimations );
2005-06-04 21:22:50 +00:00
int FindBGSegmentForBeat( float fBeat ) const;
2006-01-22 01:00:06 +00:00
void UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime, const map<RString,BackgroundTransition> &mapNameToTransition );
void ProcessMessages( float fDeltaTime );
2005-06-04 21:22:50 +00:00
map<BackgroundDef,Actor*> m_BGAnimations;
vector<BackgroundChange> m_aBGChanges;
int m_iCurBGChangeIndex;
Actor *m_pCurrentBGA;
Actor *m_pFadingBGA;
};
Layer m_Layer[NUM_BackgroundLayer];
float m_fLastMusicSeconds;
2005-08-31 19:21:29 +00:00
AutoActor m_DangerPlayer[NUM_PLAYERS];
AutoActor m_DangerAll;
2005-06-04 21:22:50 +00:00
2005-08-31 19:17:39 +00:00
AutoActor m_DeadPlayer[NUM_PLAYERS];
2005-06-04 21:22:50 +00:00
// cover up the edge of animations that might hang outside of the background rectangle
Quad m_quadBorderLeft, m_quadBorderTop, m_quadBorderRight, m_quadBorderBottom;
BrightnessOverlay m_Brightness;
2005-10-27 19:29:04 +00:00
BackgroundDef m_StaticBackgroundDef;
2005-06-04 21:22:50 +00:00
};
static RageColor GetBrightnessColor( float fBrightnessPercent )
{
RageColor cBrightness = RageColor( 0,0,0,1-fBrightnessPercent );
RageColor cClamp = RageColor( 0.5f,0.5f,0.5f,CLAMP_OUTPUT_PERCENT );
// blend the two colors above as if cBrightness is drawn, then cClamp drawn on top
cBrightness.a *= (1-cClamp.a); // premultiply alpha
RageColor ret;
ret.a = cBrightness.a + cClamp.a;
ret.r = (cBrightness.r * cBrightness.a + cClamp.r * cClamp.a) / ret.a;
ret.g = (cBrightness.g * cBrightness.a + cClamp.g * cClamp.a) / ret.a;
ret.b = (cBrightness.b * cBrightness.a + cClamp.b * cClamp.a) / ret.a;
return ret;
}
2005-06-04 21:22:50 +00:00
BackgroundImpl::BackgroundImpl()
2005-05-26 09:35:57 +00:00
{
m_bInitted = false;
m_pDancingCharacters = NULL;
m_pSong = NULL;
2005-05-26 09:35:57 +00:00
}
2005-06-04 21:22:50 +00:00
BackgroundImpl::Layer::Layer()
{
m_iCurBGChangeIndex = -1;
2003-04-13 00:44:50 +00:00
m_pCurrentBGA = NULL;
m_pFadingBGA = NULL;
}
2005-06-04 21:22:50 +00:00
void BackgroundImpl::Init()
{
if( m_bInitted )
return;
m_bInitted = true;
2005-10-27 19:29:04 +00:00
m_StaticBackgroundDef = BackgroundDef();
// load transitions
{
ASSERT( m_mapNameToTransition.empty() );
2006-01-22 01:00:06 +00:00
vector<RString> vsPaths, vsNames;
BackgroundUtil::GetBackgroundTransitions( "", vsPaths, vsNames );
for( unsigned i=0; i<vsPaths.size(); i++ )
{
2006-01-22 01:00:06 +00:00
const RString &sPath = vsPaths[i];
const RString &sName = vsNames[i];
XNode xml;
XmlFileUtil::LoadFromFileShowErrors(xml, sPath);
ASSERT( xml.m_sName == "BackgroundTransition" );
BackgroundTransition &bgt = m_mapNameToTransition[sName];
2006-01-22 01:00:06 +00:00
RString sCmdLeaves;
bool bSuccess = xml.GetAttrValue( "LeavesCommand", sCmdLeaves );
ASSERT( bSuccess );
bgt.cmdLeaves = apActorCommands( new ActorCommands(sCmdLeaves) );
2006-01-22 01:00:06 +00:00
RString sCmdRoot;
bSuccess = xml.GetAttrValue( "RootCommand", sCmdRoot );
ASSERT( bSuccess );
bgt.cmdRoot = apActorCommands( new ActorCommands(sCmdRoot) );
}
}
2005-08-31 19:21:29 +00:00
m_DangerAll.Load( THEME->GetPathB("ScreenGameplay","danger all") );
FOREACH_PlayerNumber( p )
2005-08-31 19:21:29 +00:00
m_DangerPlayer[p].Load( THEME->GetPathB("ScreenGameplay",ssprintf("danger p%d",p+1)) );
FOREACH_PlayerNumber( p )
2005-08-31 19:17:39 +00:00
m_DeadPlayer[p].Load( THEME->GetPathB("ScreenGameplay",ssprintf("dead p%d",p+1)) );
2002-06-24 22:20:51 +00:00
2003-06-27 08:06:22 +00:00
bool bOneOrMoreChars = false;
bool bShowingBeginnerHelper = false;
FOREACH_HumanPlayer( p )
2003-09-04 07:21:31 +00:00
{
bOneOrMoreChars = true;
// Disable dancing characters if BH will be showing.
if( PREFSMAN->m_bShowBeginnerHelper && BeginnerHelper::CanUse() &&
2004-05-24 06:12:17 +00:00
GAMESTATE->m_pCurSteps[p] && GAMESTATE->m_pCurSteps[p]->GetDifficulty() == DIFFICULTY_BEGINNER )
2003-09-04 07:21:31 +00:00
bShowingBeginnerHelper = true;
}
if( bOneOrMoreChars && !bShowingBeginnerHelper )
2003-06-27 08:06:22 +00:00
m_pDancingCharacters = new DancingCharacters;
RageColor c = GetBrightnessColor(0);
2004-04-19 20:28:10 +00:00
m_quadBorderLeft.StretchTo( RectF(SCREEN_LEFT,SCREEN_TOP,LEFT_EDGE,SCREEN_BOTTOM) );
m_quadBorderLeft.SetDiffuse( c );
m_quadBorderTop.StretchTo( RectF(LEFT_EDGE,SCREEN_TOP,RIGHT_EDGE,TOP_EDGE) );
m_quadBorderTop.SetDiffuse( c );
m_quadBorderRight.StretchTo( RectF(RIGHT_EDGE,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
m_quadBorderRight.SetDiffuse( c );
m_quadBorderBottom.StretchTo( RectF(LEFT_EDGE,BOTTOM_EDGE,RIGHT_EDGE,SCREEN_BOTTOM) );
m_quadBorderBottom.SetDiffuse( c );
this->AddChild( &m_quadBorderLeft );
this->AddChild( &m_quadBorderTop );
this->AddChild( &m_quadBorderRight );
this->AddChild( &m_quadBorderBottom );
2004-04-19 20:28:10 +00:00
this->AddChild( &m_Brightness );
2002-07-11 19:02:26 +00:00
}
2005-06-04 21:22:50 +00:00
BackgroundImpl::~BackgroundImpl()
{
Unload();
2003-06-27 09:05:51 +00:00
delete m_pDancingCharacters;
}
2005-06-04 21:22:50 +00:00
void BackgroundImpl::Unload()
2005-05-26 09:35:57 +00:00
{
2005-06-04 21:22:50 +00:00
FOREACH_BackgroundLayer( i )
2005-05-26 09:35:57 +00:00
m_Layer[i].Unload();
m_pSong = NULL;
m_fLastMusicSeconds = -9999;
2005-06-02 04:37:33 +00:00
m_RandomBGAnimations.clear();
2005-05-26 09:35:57 +00:00
}
2005-06-04 21:22:50 +00:00
void BackgroundImpl::Layer::Unload()
2002-07-11 19:02:26 +00:00
{
2006-03-24 18:28:03 +00:00
FOREACHM( BackgroundDef, Actor*, m_BGAnimations, iter )
delete iter->second;
2002-10-24 20:15:24 +00:00
m_BGAnimations.clear();
m_aBGChanges.clear();
2004-01-23 05:44:15 +00:00
2003-04-13 00:44:50 +00:00
m_pCurrentBGA = NULL;
m_pFadingBGA = NULL;
2004-01-24 19:05:54 +00:00
m_iCurBGChangeIndex = -1;
2002-06-23 02:57:51 +00:00
}
2006-01-22 01:00:06 +00:00
Actor *MakeVisualization( const RString &sVisPath )
{
ActorFrame *pFrame = new ActorFrame;
pFrame->DeleteChildrenWhenDone();
const Song* pSong = GAMESTATE->m_pCurSong;
2006-01-22 01:00:06 +00:00
RString sSongBGPath =
2005-02-06 03:32:53 +00:00
(pSong && pSong->HasBackground()) ? pSong->GetBackgroundPath() : THEME->GetPathG("Common","fallback background");
Sprite* pSprite = new Sprite;
pSprite->LoadBG( sSongBGPath );
pSprite->StretchTo( FullScreenRectF );
pFrame->AddChild( pSprite );
pSprite = new Sprite;
pSprite->LoadBG( sVisPath );
pSprite->StretchTo( FullScreenRectF );
pSprite->SetBlendMode( BLEND_ADD );
pFrame->AddChild( pSprite );
return pFrame;
}
2005-06-04 21:22:50 +00:00
bool BackgroundImpl::Layer::CreateBackground( const Song *pSong, const BackgroundDef &bd )
2002-10-30 19:55:19 +00:00
{
2005-06-02 04:37:33 +00:00
ASSERT( m_BGAnimations.find(bd) == m_BGAnimations.end() );
// Resolve the background names
2006-01-22 01:00:06 +00:00
vector<RString> vsToResolve;
vsToResolve.push_back( bd.m_sFile1 );
vsToResolve.push_back( bd.m_sFile2 );
2002-10-30 19:55:19 +00:00
2006-01-22 01:00:06 +00:00
vector<RString> vsResolved;
vsResolved.resize( vsToResolve.size() );
for( unsigned i=0; i<vsToResolve.size(); i++ )
2002-10-30 19:55:19 +00:00
{
2006-01-22 01:00:06 +00:00
const RString &sToResolve = vsToResolve[i];
2006-01-22 01:00:06 +00:00
LUA->SetGlobal( ssprintf("File%d",i+1), RString() );
if( sToResolve.empty() )
{
if( i == 0 )
2005-10-16 01:35:06 +00:00
return false;
else
continue;
}
// Look for vsFileToResolve[i] in:
// - song's dir
// - RandomMovies dir
// - BGAnimations dir.
2006-01-22 01:00:06 +00:00
vector<RString> vsPaths, vsThrowAway;
// Look for BGAnims in the song dir
if( sToResolve == SONG_BACKGROUND_FILE )
vsPaths.push_back( pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathG("Common","fallback background") );
if( vsPaths.empty() ) BackgroundUtil::GetSongBGAnimations( pSong, sToResolve, vsPaths, vsThrowAway );
2006-03-18 09:17:20 +00:00
if( vsPaths.empty() ) BackgroundUtil::GetSongMovies( pSong, sToResolve, vsPaths, vsThrowAway );
if( vsPaths.empty() ) BackgroundUtil::GetSongBitmaps( pSong, sToResolve, vsPaths, vsThrowAway );
if( vsPaths.empty() ) BackgroundUtil::GetGlobalBGAnimations( pSong, sToResolve, vsPaths, vsThrowAway );
if( vsPaths.empty() ) BackgroundUtil::GetGlobalRandomMovies( pSong, sToResolve, vsPaths, vsThrowAway );
2006-01-22 01:00:06 +00:00
RString &sResolved = vsResolved[i];
if( !vsPaths.empty() )
{
sResolved = vsPaths[0];
}
2003-04-13 23:22:27 +00:00
else
{
2005-12-01 00:10:09 +00:00
// If the main background file is missing, we failed.
if( i == 0 )
return false;
else
sResolved = ThemeManager::GetBlankGraphicPath();
}
ASSERT( !sResolved.empty() );
LUA->SetGlobal( ssprintf("File%d",i+1), sResolved );
2002-10-30 19:55:19 +00:00
}
2006-01-22 01:00:06 +00:00
RString sEffect = bd.m_sEffect;
if( sEffect.empty() )
2002-10-30 19:55:19 +00:00
{
FileType ft = ActorUtil::GetFileType(vsResolved[0]);
switch( ft )
{
default:
2006-03-18 09:17:20 +00:00
LOG->Warn( "CreateBackground() Unknown file type '%s'", vsResolved[0].c_str() );
// fall through
case FT_Bitmap:
case FT_Movie:
sEffect = SBE_StretchNormal;
break;
case FT_Directory:
case FT_Xml:
case FT_Model:
sEffect = SBE_UpperLeft;
break;
}
2002-10-30 19:55:19 +00:00
}
ASSERT( !sEffect.empty() );
2002-10-30 19:55:19 +00:00
2005-06-05 22:21:55 +00:00
// Set Lua color globals
2006-01-22 01:00:06 +00:00
LUA->SetGlobal( "Color1", bd.m_sColor1.empty() ? RString("1,1,1,1") : bd.m_sColor1 );
LUA->SetGlobal( "Color2", bd.m_sColor2.empty() ? RString("1,1,1,1") : bd.m_sColor2 );
2005-06-05 22:21:55 +00:00
// Resolve the effect file.
2006-01-22 01:00:06 +00:00
RString sEffectFile;
2005-06-05 22:21:55 +00:00
for( int i=0; i<2; i++ )
{
2006-01-22 01:00:06 +00:00
vector<RString> vsPaths, vsThrowAway;
2005-06-05 22:21:55 +00:00
BackgroundUtil::GetBackgroundEffects( sEffect, vsPaths, vsThrowAway );
if( vsPaths.empty() )
{
LOG->Warn( "BackgroundEffect '%s' is missing.",sEffect.c_str() );
sEffect = SBE_Centered;
}
else if( vsPaths.size() > 1 )
{
LOG->Warn( "BackgroundEffect '%s' has more than one match.",sEffect.c_str() );
sEffect = SBE_Centered;
}
else
{
sEffectFile = vsPaths[0];
break;
}
}
ASSERT( !sEffectFile.empty() );
Actor *pActor = ActorUtil::MakeActor( sEffectFile );
2005-07-18 01:52:01 +00:00
ASSERT( pActor );
m_BGAnimations[bd] = pActor;
for( unsigned i=0; i<vsResolved.size(); i++ )
2006-01-22 01:00:06 +00:00
LUA->SetGlobal( ssprintf("File%d",i+1), RString() );
2005-07-18 01:52:01 +00:00
LUA->UnsetGlobal( "Color1" );
LUA->UnsetGlobal( "Color2" );
return true;
2002-10-30 19:55:19 +00:00
}
2006-01-22 01:00:06 +00:00
BackgroundDef BackgroundImpl::Layer::CreateRandomBGA( const Song *pSong, const RString &sEffect, deque<BackgroundDef> &RandomBGAnimations )
{
2005-10-29 20:04:57 +00:00
if( PREFSMAN->m_RandomBackgroundMode == PrefsManager::BGMODE_OFF )
return BackgroundDef();
2005-03-02 03:20:12 +00:00
2005-06-02 04:37:33 +00:00
if( RandomBGAnimations.empty() )
return BackgroundDef();
2004-01-23 02:23:11 +00:00
2005-06-02 04:37:33 +00:00
/* XXX: every time we fully loop, shuffle, so we don't play the same sequence
* over and over; and nudge the shuffle so the next one won't be a repeat */
BackgroundDef bd = RandomBGAnimations.front();
RandomBGAnimations.push_back( RandomBGAnimations.front() );
RandomBGAnimations.pop_front();
2004-01-23 02:23:11 +00:00
if( !sEffect.empty() )
bd.m_sEffect = sEffect;
2005-06-02 04:37:33 +00:00
map<BackgroundDef,Actor*>::const_iterator iter = m_BGAnimations.find( bd );
// create the background if it's not already created
if( iter == m_BGAnimations.end() )
2004-01-23 02:23:11 +00:00
{
2005-06-02 04:37:33 +00:00
bool bSuccess = CreateBackground( pSong, bd );
ASSERT( bSuccess ); // we fed it valid files, so this shouldn't fail
2004-01-23 02:23:11 +00:00
}
return bd;
}
void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const BackgroundChange &change )
2004-01-23 03:53:23 +00:00
{
const TimingData &timing = m_pSong->m_Timing;
2004-01-23 03:53:23 +00:00
// change BG every 4 bars
for( float f=fFirstBeat; f<fEndBeat; f+=BEATS_PER_MEASURE*4 )
2004-01-23 03:53:23 +00:00
{
// Don't fade. It causes frame rate dip, especially on slower machines.
BackgroundDef bd = m_Layer[0].CreateRandomBGA( m_pSong, change.m_def.m_sEffect, m_RandomBGAnimations );
if( !bd.IsEmpty() )
{
2005-06-02 04:37:33 +00:00
BackgroundChange c = change;
c.m_def = bd;
2005-06-02 04:37:33 +00:00
c.m_fStartBeat = f;
m_Layer[0].m_aBGChanges.push_back( c );
}
2004-01-23 03:53:23 +00:00
}
// change BG every BPM change that is at the beginning of a measure
int iStartIndex = BeatToNoteRow(fFirstBeat);
int iEndIndex = BeatToNoteRow(fEndBeat);
2004-01-23 03:53:23 +00:00
for( unsigned i=0; i<timing.m_BPMSegments.size(); i++ )
{
const BPMSegment& bpmseg = timing.m_BPMSegments[i];
if( bpmseg.m_iStartIndex % BeatToNoteRow((float) BEATS_PER_MEASURE) != 0 )
2004-01-23 03:53:23 +00:00
continue; // skip
// start so that we don't create a BGChange right on top of fEndBeat
bool bInRange = bpmseg.m_iStartIndex >= iStartIndex && bpmseg.m_iStartIndex < iEndIndex;
if( !bInRange )
2004-01-23 03:53:23 +00:00
continue; // skip
BackgroundDef bd = m_Layer[0].CreateRandomBGA( m_pSong, change.m_def.m_sEffect, m_RandomBGAnimations );
if( !bd.IsEmpty() )
{
2005-06-02 04:37:33 +00:00
BackgroundChange c = change;
c.m_def.m_sFile1 = bd.m_sFile1;
c.m_def.m_sFile2 = bd.m_sFile2;
2005-06-02 04:37:33 +00:00
c.m_fStartBeat = NoteRowToBeat(bpmseg.m_iStartIndex);
m_Layer[0].m_aBGChanges.push_back( c );
}
2004-01-23 03:53:23 +00:00
}
}
2005-06-04 21:22:50 +00:00
void BackgroundImpl::LoadFromSong( const Song* pSong )
{
Init();
2002-08-21 04:11:21 +00:00
Unload();
m_pSong = pSong;
2005-10-27 19:29:04 +00:00
m_StaticBackgroundDef.m_sFile1 = SONG_BACKGROUND_FILE;
2004-12-04 10:35:50 +00:00
if( PREFSMAN->m_fBGBrightness == 0.0f )
return;
2005-06-02 04:37:33 +00:00
//
// Choose a bunch of background that we'll use for the random file marker
//
{
2006-01-22 01:00:06 +00:00
vector<RString> vsThrowAway, vsNames;
2005-10-29 20:04:57 +00:00
switch( PREFSMAN->m_RandomBackgroundMode )
2005-06-02 04:37:33 +00:00
{
default:
2005-10-30 23:59:12 +00:00
ASSERT_M( 0, ssprintf("Invalid RandomBackgroundMode: %i", int(PREFSMAN->m_RandomBackgroundMode)) );
break;
case PrefsManager::BGMODE_OFF:
break;
case PrefsManager::BGMODE_ANIMATIONS:
BackgroundUtil::GetGlobalBGAnimations( pSong, "", vsThrowAway, vsNames );
break;
case PrefsManager::BGMODE_RANDOMMOVIES:
BackgroundUtil::GetGlobalRandomMovies( pSong, "", vsThrowAway, vsNames );
break;
2005-06-02 04:37:33 +00:00
}
random_shuffle( vsNames.begin(), vsNames.end() );
int iSize = min( (int)PREFSMAN->m_iNumBackgrounds, (int)vsNames.size() );
vsNames.resize( iSize );
2006-01-22 01:00:06 +00:00
FOREACH_CONST( RString, vsNames, s )
2005-06-02 04:37:33 +00:00
{
BackgroundDef bd;
bd.m_sFile1 = *s;
m_RandomBGAnimations.push_back( bd );
}
}
2004-02-05 21:59:26 +00:00
/* Song backgrounds (even just background stills) can get very big; never keep them
* in memory. */
RageTextureID::TexPolicy OldPolicy = TEXTUREMAN->GetDefaultTexturePolicy();
TEXTUREMAN->SetDefaultTexturePolicy( RageTextureID::TEX_VOLATILE );
2004-02-05 21:59:26 +00:00
TEXTUREMAN->DisableOddDimensionWarning();
2002-12-17 06:25:03 +00:00
const float fXZoom = RECT_BACKGROUND.GetWidth() / (float)SCREEN_WIDTH;
const float fYZoom = RECT_BACKGROUND.GetHeight() / (float)SCREEN_HEIGHT;
2002-08-28 22:42:40 +00:00
if( !PREFSMAN->m_bSongBackgrounds )
{
/* Backgrounds are disabled; just display the song background. */
BackgroundChange change;
change.m_def = m_StaticBackgroundDef;
change.m_fStartBeat = 0;
m_Layer[0].m_aBGChanges.push_back( change );
}
else if( pSong->HasBGChanges() )
{
2005-06-04 21:22:50 +00:00
FOREACH_BackgroundLayer( i )
2002-07-11 19:02:26 +00:00
{
2005-05-26 09:35:57 +00:00
Layer &layer = m_Layer[i];
2005-05-26 09:35:57 +00:00
// Load all song-specified backgrounds
2005-06-04 21:22:50 +00:00
FOREACH_CONST( BackgroundChange, pSong->GetBackgroundChanges(i), bgc )
2002-10-25 07:35:07 +00:00
{
2005-05-26 09:35:57 +00:00
BackgroundChange change = *bgc;
2005-06-04 21:22:50 +00:00
BackgroundDef &bd = change.m_def;
2005-05-26 09:35:57 +00:00
bool bIsAlreadyLoaded = layer.m_BGAnimations.find(bd) != layer.m_BGAnimations.end();
2005-05-26 09:35:57 +00:00
if( bd.m_sFile1 != RANDOM_BACKGROUND_FILE && !bIsAlreadyLoaded )
2004-01-23 02:23:11 +00:00
{
if( layer.CreateBackground( m_pSong, bd ) )
2005-05-26 09:35:57 +00:00
{
; // do nothing. Create was successful.
2005-05-26 09:35:57 +00:00
}
else
2005-05-26 09:35:57 +00:00
{
if( i == BACKGROUND_LAYER_1 )
2005-06-02 04:37:33 +00:00
{
// The background was not found. Try to use a random one instead.
bd = layer.CreateRandomBGA( pSong, "", m_RandomBGAnimations );
2005-06-02 04:37:33 +00:00
if( bd.IsEmpty() )
2005-10-27 19:29:04 +00:00
bd = m_StaticBackgroundDef;
2005-06-02 04:37:33 +00:00
}
2005-05-26 09:35:57 +00:00
}
2004-01-23 02:23:11 +00:00
}
2005-06-02 04:37:33 +00:00
if( !bd.IsEmpty() )
layer.m_aBGChanges.push_back( change );
2002-10-25 07:35:07 +00:00
}
}
}
else // pSong doesn't have an animation plan
{
2005-05-26 09:35:57 +00:00
Layer &layer = m_Layer[0];
2005-06-02 04:37:33 +00:00
LoadFromRandom( pSong->m_fFirstBeat, pSong->m_fLastBeat, BackgroundChange() );
// end showing the static song background
BackgroundChange change;
2005-10-27 19:29:04 +00:00
change.m_def = m_StaticBackgroundDef;
change.m_fStartBeat = pSong->m_fLastBeat;
layer.m_aBGChanges.push_back( change );
}
// sort segments
2005-06-04 21:22:50 +00:00
FOREACH_BackgroundLayer( i )
2005-05-26 09:35:57 +00:00
{
Layer &layer = m_Layer[i];
BackgroundUtil::SortBackgroundChangesArray( layer.m_aBGChanges );
2005-05-26 09:35:57 +00:00
}
Layer &mainlayer = m_Layer[0];
/* If the first BGAnimation isn't negative, add a lead-in image showing the song
* background. */
2005-05-26 09:35:57 +00:00
if( mainlayer.m_aBGChanges.empty() || mainlayer.m_aBGChanges.front().m_fStartBeat >= 0 )
{
BackgroundChange change;
2005-10-27 19:29:04 +00:00
change.m_def = m_StaticBackgroundDef;
change.m_fStartBeat = -10000;
mainlayer.m_aBGChanges.insert( mainlayer.m_aBGChanges.begin(), change );
}
// If any BGChanges use the background image, load it.
bool bStaticBackgroundUsed = false;
2005-06-04 21:22:50 +00:00
FOREACH_BackgroundLayer( i )
{
2005-06-02 04:37:33 +00:00
Layer &layer = m_Layer[i];
FOREACH_CONST( BackgroundChange, layer.m_aBGChanges, bgc )
{
2005-06-04 21:22:50 +00:00
const BackgroundDef &bd = bgc->m_def;
2005-10-27 19:29:04 +00:00
if( bd == m_StaticBackgroundDef )
2005-06-02 04:37:33 +00:00
{
bStaticBackgroundUsed = true;
break;
}
}
if( bStaticBackgroundUsed )
break;
}
2005-06-02 04:37:33 +00:00
if( bStaticBackgroundUsed )
{
2005-10-27 19:29:04 +00:00
bool bIsAlreadyLoaded = mainlayer.m_BGAnimations.find(m_StaticBackgroundDef) != mainlayer.m_BGAnimations.end();
if( !bIsAlreadyLoaded )
{
2005-10-27 19:29:04 +00:00
bool bSuccess = mainlayer.CreateBackground( m_pSong, m_StaticBackgroundDef );
ASSERT( bSuccess );
}
}
2005-06-02 04:37:33 +00:00
// Look for the random file marker, and replace the segment with LoadFromRandom.
2005-05-26 09:35:57 +00:00
for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
{
2005-06-02 04:37:33 +00:00
const BackgroundChange change = mainlayer.m_aBGChanges[i];
2005-06-04 21:22:50 +00:00
if( change.m_def.m_sFile1 != RANDOM_BACKGROUND_FILE )
continue;
const float fStartBeat = change.m_fStartBeat;
const float fEndBeat = (i+1 < mainlayer.m_aBGChanges.size())? mainlayer.m_aBGChanges[i+1].m_fStartBeat: FLT_MAX;
2005-05-26 09:35:57 +00:00
mainlayer.m_aBGChanges.erase( mainlayer.m_aBGChanges.begin()+i );
--i;
LoadFromRandom( fStartBeat, fEndBeat, change );
}
2004-01-24 19:05:54 +00:00
// At this point, we shouldn't have any BGChanges to "". "" is an invalid name.
2005-05-26 09:35:57 +00:00
for( unsigned i=0; i<mainlayer.m_aBGChanges.size(); i++ )
2005-06-04 21:22:50 +00:00
ASSERT( !mainlayer.m_aBGChanges[i].m_def.m_sFile1.empty() );
2004-01-24 19:05:54 +00:00
2004-01-24 19:05:54 +00:00
// Re-sort.
BackgroundUtil::SortBackgroundChangesArray( mainlayer.m_aBGChanges );
2005-08-31 19:21:29 +00:00
m_DangerAll->SetXY( (float)LEFT_EDGE, (float)TOP_EDGE );
m_DangerAll->SetZoomX( fXZoom );
m_DangerAll->SetZoomY( fYZoom );
FOREACH_PlayerNumber( p )
{
2005-08-31 19:21:29 +00:00
m_DangerPlayer[p]->SetXY( (float)LEFT_EDGE, (float)TOP_EDGE );
m_DangerPlayer[p]->SetZoomX( fXZoom );
m_DangerPlayer[p]->SetZoomY( fYZoom );
m_DangerPlayer[p]->FinishTweening();
m_DangerPlayer[p]->PlayCommand( "On" );
2005-08-31 19:17:39 +00:00
m_DeadPlayer[p]->SetXY( (float)LEFT_EDGE, (float)TOP_EDGE );
m_DeadPlayer[p]->SetZoomX( fXZoom );
m_DeadPlayer[p]->SetZoomY( fYZoom );
m_DeadPlayer[p]->FinishTweening();
m_DeadPlayer[p]->PlayCommand( "On" );
}
TEXTUREMAN->EnableOddDimensionWarning();
if( m_pDancingCharacters )
m_pDancingCharacters->LoadNextSong();
2004-02-05 21:59:26 +00:00
TEXTUREMAN->SetDefaultTexturePolicy( OldPolicy );
/* Song backgrounds always sync from the music by default, unlike other actors
* which sync from the regular clock by default. If you don't want this, set
* 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. */
FOREACHM( BackgroundDef, Actor*, mainlayer.m_BGAnimations, it )
{
Actor *pBGA = it->second;
/* Be sure that we run this command recursively on all children; the tree
* may look something like "BGAnimation, BGAnimationLayer, Sprite" or it
* may be deeper, like "BGAnimation, BGAnimationLayer, BGAnimation,
* BGAnimationLayer, Sprite". */
ActorCommands acmds( "effectclock,music" );
2005-01-26 11:21:43 +00:00
pBGA->RunCommands( acmds );
}
}
2005-06-04 21:22:50 +00:00
int BackgroundImpl::Layer::FindBGSegmentForBeat( float fBeat ) const
{
2004-02-13 08:13:21 +00:00
if( m_aBGChanges.empty() )
return -1;
if( fBeat < m_aBGChanges[0].m_fStartBeat )
return -1;
// assumption: m_aBGChanges are sorted by m_fStartBeat
2004-09-21 07:53:39 +00:00
int i;
2006-03-24 18:28:03 +00:00
for( i=m_aBGChanges.size()-1; i>=0; i-- )
2004-02-13 08:13:21 +00:00
{
if( fBeat >= m_aBGChanges[i].m_fStartBeat )
return i;
2004-02-13 08:13:21 +00:00
}
2004-02-13 08:13:21 +00:00
return i;
}
/* If the BG segment has changed, move focus to it. Send Update() calls. */
2006-01-22 01:00:06 +00:00
void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMusicSeconds, float fCurrentTime, const map<RString,BackgroundTransition> &mapNameToTransition )
{
2004-01-29 05:20:27 +00:00
ASSERT( fCurrentTime != GameState::MUSIC_SECONDS_INVALID );
2003-09-23 19:26:36 +00:00
if( m_aBGChanges.size() == 0 )
return;
2003-02-07 23:49:38 +00:00
float fBeat, fBPS;
bool bFreeze;
2005-05-26 09:35:57 +00:00
pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze );
2003-04-13 00:44:50 +00:00
/* Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it. */
const float fRate = GAMESTATE->m_SongOptions.m_fMusicRate;
2002-06-24 22:20:51 +00:00
2004-01-24 19:05:54 +00:00
// Find the BGSegment we're in
const int i = FindBGSegmentForBeat( fBeat );
float fDeltaTime = fCurrentTime - fLastMusicSeconds;
2004-01-24 19:05:54 +00:00
if( i != -1 && i != m_iCurBGChangeIndex ) // we're changing backgrounds
{
2004-03-17 05:06:49 +00:00
LOG->Trace( "old bga %d -> new bga %d, %f, %f", m_iCurBGChangeIndex, i, m_aBGChanges[i].m_fStartBeat, fBeat );
2005-06-05 22:21:55 +00:00
BackgroundChange oldChange;
if( m_iCurBGChangeIndex != -1 )
oldChange = m_aBGChanges[m_iCurBGChangeIndex];
m_iCurBGChangeIndex = i;
const BackgroundChange& change = m_aBGChanges[i];
m_pFadingBGA = m_pCurrentBGA;
2005-06-04 21:22:50 +00:00
map<BackgroundDef,Actor*>::const_iterator iter = m_BGAnimations.find( change.m_def );
if( iter == m_BGAnimations.end() )
{
XNode *pNode = change.m_def.CreateNode();
2005-06-16 03:08:45 +00:00
LOG->Warn( "Tried to switch to a background that was never loaded\n" + pNode->GetXML() );
SAFE_DELETE( pNode );
return;
}
2005-06-02 04:37:33 +00:00
m_pCurrentBGA = iter->second;
if( m_pFadingBGA == m_pCurrentBGA )
{
m_pFadingBGA = NULL;
LOG->Trace( "bg didn't actually change. Ignoring." );
}
else
{
if( m_pFadingBGA )
{
m_pFadingBGA->PlayCommand( "LoseFocus" );
if( !change.m_sTransition.empty() )
{
2006-01-22 01:00:06 +00:00
map<RString,BackgroundTransition>::const_iterator iter = mapNameToTransition.find( change.m_sTransition );
ASSERT( iter != mapNameToTransition.end() );
const BackgroundTransition &bt = iter->second;
m_pFadingBGA->RunCommandsOnLeaves( *bt.cmdLeaves );
m_pFadingBGA->RunCommands( *bt.cmdRoot );
}
}
}
m_pCurrentBGA->SetUpdateRate( change.m_fRate );
2005-06-05 22:21:55 +00:00
// Set Lua color globals before calling Init and On
2006-01-22 01:00:06 +00:00
LUA->SetGlobal( "Color1", change.m_def.m_sColor1.empty() ? RString("1,1,1,1") : change.m_def.m_sColor1 );
LUA->SetGlobal( "Color2", change.m_def.m_sColor2.empty() ? RString("1,1,1,1") : change.m_def.m_sColor2 );
2005-06-05 22:21:55 +00:00
m_pCurrentBGA->PlayCommand( "Init" );
m_pCurrentBGA->PlayCommand( "On" );
m_pCurrentBGA->PlayCommand( "GainFocus" );
2005-09-06 19:01:14 +00:00
LUA->UnsetGlobal( "Color1" );
LUA->UnsetGlobal( "Color2" );
2005-06-05 22:21:55 +00:00
/* How much time of this BGA have we skipped? (This happens with SetSeconds.) */
const float fStartSecond = pSong->m_Timing.GetElapsedTimeFromBeat( change.m_fStartBeat );
/* This is affected by the music rate. */
fDeltaTime = fCurrentTime - fStartSecond;
}
if( m_pFadingBGA )
{
2005-10-29 20:09:10 +00:00
if( m_pFadingBGA->GetTweenTimeLeft() == 0 )
m_pFadingBGA = NULL;
}
2002-07-31 22:37:58 +00:00
/* This is affected by the music rate. */
float fDeltaTimeMusicRate = max( fDeltaTime / fRate, 0 );
if( m_pCurrentBGA )
m_pCurrentBGA->Update( fDeltaTimeMusicRate );
if( m_pFadingBGA )
m_pFadingBGA->Update( fDeltaTimeMusicRate );
2003-09-23 19:26:36 +00:00
}
void BackgroundImpl::Layer::ProcessMessages( float fDeltaTime )
{
if( m_pCurrentBGA )
m_pCurrentBGA->ProcessMessages( fDeltaTime );
if( m_pFadingBGA )
m_pFadingBGA->ProcessMessages( fDeltaTime );
}
2005-06-04 21:22:50 +00:00
void BackgroundImpl::Update( float fDeltaTime )
2003-09-23 19:26:36 +00:00
{
ActorFrame::Update( fDeltaTime );
if( IsDangerAllVisible() )
2003-09-23 19:26:36 +00:00
{
2005-08-31 19:21:29 +00:00
m_DangerAll->Update( fDeltaTime );
}
2003-09-23 19:26:36 +00:00
FOREACH_PlayerNumber( p )
{
if( GAMESTATE->IsPlayerInDanger(GAMESTATE->m_pPlayerState[p]) )
2005-08-31 19:21:29 +00:00
m_DangerPlayer[p]->Update( fDeltaTime );
if( GAMESTATE->IsPlayerDead(GAMESTATE->m_pPlayerState[p]) )
2005-08-31 19:17:39 +00:00
m_DeadPlayer[p]->Update( fDeltaTime );
}
2005-05-26 09:35:57 +00:00
if( m_pDancingCharacters )
m_pDancingCharacters->Update( fDeltaTime );
/* Always update the current background, even when m_DangerAll is being displayed.
2003-09-23 19:26:36 +00:00
* 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. */
2005-06-04 21:22:50 +00:00
FOREACH_BackgroundLayer( i )
2003-09-23 19:26:36 +00:00
{
2005-05-26 09:35:57 +00:00
Layer &layer = m_Layer[i];
layer.UpdateCurBGChange( m_pSong, m_fLastMusicSeconds, GAMESTATE->m_fMusicSeconds, m_mapNameToTransition );
2003-09-23 19:26:36 +00:00
}
2005-05-26 09:35:57 +00:00
m_fLastMusicSeconds = GAMESTATE->m_fMusicSeconds;
}
void BackgroundImpl::ProcessMessages( float fDeltaTime )
{
ActorFrame::ProcessMessages( fDeltaTime );
FOREACH_BackgroundLayer( i )
{
Layer &layer = m_Layer[i];
layer.ProcessMessages( fDeltaTime );
}
}
2005-06-04 21:22:50 +00:00
void BackgroundImpl::DrawPrimitives()
{
2004-12-04 10:35:50 +00:00
if( PREFSMAN->m_fBGBrightness == 0.0f )
return;
if( IsDangerAllVisible() )
{
// Since this only shows when DANGER is visible, it will flash red on it's own accord :)
if( m_pDancingCharacters )
m_pDancingCharacters->m_bDrawDangerLight = true;
2005-08-31 19:21:29 +00:00
m_DangerAll->Draw();
}
2003-12-07 21:40:00 +00:00
if( !IsDangerAllVisible() || !(bool)DANGER_ALL_IS_OPAQUE )
2003-04-13 00:44:50 +00:00
{
if( m_pDancingCharacters )
m_pDancingCharacters->m_bDrawDangerLight = false;
2005-05-26 09:35:57 +00:00
2005-06-04 21:22:50 +00:00
FOREACH_BackgroundLayer( i )
2005-05-26 09:35:57 +00:00
{
Layer &layer = m_Layer[i];
if( layer.m_pCurrentBGA )
layer.m_pCurrentBGA->Draw();
if( layer.m_pFadingBGA )
layer.m_pFadingBGA->Draw();
}
FOREACH_PlayerNumber( p )
{
if( GAMESTATE->IsPlayerInDanger(GAMESTATE->m_pPlayerState[p]) )
2005-08-31 19:21:29 +00:00
m_DangerPlayer[p]->Draw();
if( GAMESTATE->IsPlayerDead(GAMESTATE->m_pPlayerState[p]) )
2005-08-31 19:17:39 +00:00
m_DeadPlayer[p]->Draw();
}
}
2003-06-27 08:06:22 +00:00
if( m_pDancingCharacters )
m_pDancingCharacters->Draw();
ActorFrame::DrawPrimitives();
}
2005-07-18 01:52:01 +00:00
void BackgroundImpl::GetLoadedBackgroundChanges( vector<BackgroundChange> *pBackgroundChangesOut[NUM_BackgroundLayer] )
{
FOREACH_BackgroundLayer( i )
*pBackgroundChangesOut[i] = m_Layer[i].m_aBGChanges;
}
2005-06-04 21:22:50 +00:00
bool BackgroundImpl::IsDangerAllVisible()
{
FOREACH_PlayerNumber( p )
if( GAMESTATE->GetPlayerFailType(GAMESTATE->m_pPlayerState[p]) == SongOptions::FAIL_OFF )
return false;
if( !PREFSMAN->m_bShowDanger )
return false;
/* Don't show it if everyone is already failing: it's already too late and it's
* annoying for it to show for the entire duration of a song. */
2005-02-16 03:25:45 +00:00
if( STATSMAN->m_CurStageStats.AllFailedEarlier() )
return false;
if( !GAMESTATE->AllAreInDangerOrWorse() )
return false;
if( BLINK_DANGER_ALL )
return (RageTimer::GetTimeSinceStartFast() - (int)RageTimer::GetTimeSinceStartFast()) < 0.5f;
else
return true;
}
BrightnessOverlay::BrightnessOverlay()
{
float fQuadWidth = (RIGHT_EDGE-LEFT_EDGE)/2;
fQuadWidth -= g_fBackgroundCenterWidth/2;
m_quadBGBrightness[0].StretchTo( RectF(LEFT_EDGE,TOP_EDGE,LEFT_EDGE+fQuadWidth,BOTTOM_EDGE) );
m_quadBGBrightnessFade.StretchTo( RectF(LEFT_EDGE+fQuadWidth,TOP_EDGE,RIGHT_EDGE-fQuadWidth,BOTTOM_EDGE) );
m_quadBGBrightness[1].StretchTo( RectF(RIGHT_EDGE-fQuadWidth,TOP_EDGE,RIGHT_EDGE,BOTTOM_EDGE) );
this->AddChild( &m_quadBGBrightness[0] );
this->AddChild( &m_quadBGBrightness[1] );
this->AddChild( &m_quadBGBrightnessFade );
2004-04-19 20:28:10 +00:00
SetActualBrightness();
}
void BrightnessOverlay::Update( float fDeltaTime )
{
ActorFrame::Update( fDeltaTime );
/* If we're actually playing, then we're past fades, etc; update the background
* brightness to follow Cover. */
if( !GAMESTATE->m_bGameplayLeadIn )
2004-04-19 20:28:10 +00:00
SetActualBrightness();
}
2004-04-19 20:28:10 +00:00
void BrightnessOverlay::SetActualBrightness()
2002-07-11 19:02:26 +00:00
{
float fLeftBrightness = 1-GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fCover;
float fRightBrightness = 1-GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.m_fCover;
2005-03-17 02:16:31 +00:00
float fBaseBGBrightness = PREFSMAN->m_fBGBrightness;
2005-03-16 23:27:00 +00:00
2005-03-17 02:16:31 +00:00
// HACK: Always show training in full brightness
if( GAMESTATE->m_pCurSong && GAMESTATE->m_pCurSong->IsTutorial() )
fBaseBGBrightness = 1.0f;
2005-03-16 23:27:00 +00:00
fLeftBrightness *= fBaseBGBrightness;
fRightBrightness *= fBaseBGBrightness;
if( !GAMESTATE->IsHumanPlayer(PLAYER_1) )
fLeftBrightness = fRightBrightness;
if( !GAMESTATE->IsHumanPlayer(PLAYER_2) )
fRightBrightness = fLeftBrightness;
RageColor LeftColor = GetBrightnessColor(fLeftBrightness);
RageColor RightColor = GetBrightnessColor(fRightBrightness);
m_quadBGBrightness[PLAYER_1].SetDiffuse( LeftColor );
m_quadBGBrightness[PLAYER_2].SetDiffuse( RightColor );
m_quadBGBrightnessFade.SetDiffuseLeftEdge( LeftColor );
m_quadBGBrightnessFade.SetDiffuseRightEdge( RightColor );
2002-07-11 19:02:26 +00:00
}
void BrightnessOverlay::Set( float fBrightness )
2002-07-11 19:02:26 +00:00
{
RageColor c = GetBrightnessColor(fBrightness);
FOREACH_PlayerNumber(pn)
m_quadBGBrightness[pn].SetDiffuse( c );
m_quadBGBrightnessFade.SetDiffuse( c );
}
2002-07-11 19:02:26 +00:00
void BrightnessOverlay::FadeToActualBrightness()
{
2005-01-26 11:21:43 +00:00
this->RunCommandsOnChildren( BRIGHTNESS_FADE_COMMAND );
2004-04-19 20:28:10 +00:00
SetActualBrightness();
2002-06-24 22:20:51 +00:00
}
2004-06-08 00:08:04 +00:00
2005-06-04 21:22:50 +00:00
2006-02-03 19:24:14 +00:00
Background::Background() { m_pImpl = new BackgroundImpl; this->AddChild(m_pImpl); }
Background::~Background() { SAFE_DELETE( m_pImpl ); }
void Background::Init() { m_pImpl->Init(); }
void Background::LoadFromSong( const Song *pSong ) { m_pImpl->LoadFromSong(pSong); }
void Background::Unload() { m_pImpl->Unload(); }
void Background::FadeToActualBrightness() { m_pImpl->FadeToActualBrightness(); }
void Background::SetBrightness( float fBrightness ) { m_pImpl->SetBrightness(fBrightness); }
2005-06-04 21:22:50 +00:00
DancingCharacters* Background::GetDancingCharacters() { return m_pImpl->GetDancingCharacters(); }
2005-07-18 01:52:01 +00:00
void Background::GetLoadedBackgroundChanges( vector<BackgroundChange> *pBackgroundChangesOut[NUM_BackgroundLayer] ) { m_pImpl->GetLoadedBackgroundChanges(pBackgroundChangesOut); }
2005-06-04 21:22:50 +00:00
2004-06-08 00:08:04 +00:00
/*
* (c) 2001-2004 Chris Danford, Ben Nordstrom
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/