Exemplo n.º 1
0
ScreenMusicScroll::ScreenMusicScroll( CString sClassName ) : ScreenAttract( sClassName )
{
	vector<Song*> arraySongs;
	SONGMAN->GetSongs( arraySongs );
	SongUtil::SortSongPointerArrayByTitle( arraySongs );
	
	unsigned i;
	for( i=0; i < arraySongs.size(); i++ )
	{
		BitmapText *bt = new BitmapText;
		m_textLines.push_back(bt);
		
		Song* pSong = arraySongs[i];
		bt->LoadFromFont( THEME->GetPathToF("ScreenMusicScroll titles") );
		bt->SetText( pSong->GetFullDisplayTitle(), pSong->GetFullTranslitTitle() );
		bt->SetDiffuse( SONGMAN->GetSongColor(pSong) );
		bt->SetZoom( TEXT_ZOOM );

		this->AddChild( bt );
	}

//	for( i=0; i<min(NUM_CREDIT_LINES, MAX_CREDIT_LINES); i++ )
//	{
//		m_textLines[m_iNumLines].LoadFromFont( THEME->GetPathToF("ScreenMusicScroll titles") );
//		m_textLines[m_iNumLines].SetText( CREDIT_LINES[i] );
//		m_textLines[m_iNumLines].SetZoom( TEXT_ZOOM );
//
//		m_iNumLines++;
//	}

	for( i=0; i<m_textLines.size(); i++ )
	{
		m_textLines[i]->SetXY( CENTER_X, SCREEN_BOTTOM + 40 );
		m_textLines[i]->BeginTweening( SCROLL_DELAY * i );
		m_textLines[i]->BeginTweening( 2.0f*SCROLL_SPEED );
		m_textLines[i]->SetXY( CENTER_X, SCREEN_TOP - 40 );	
	}
	
	this->MoveToTail( &m_In );		// put it in the back so it covers up the stuff we just added
	this->MoveToTail( &m_Out );		// put it in the back so it covers up the stuff we just added

	this->ClearMessageQueue( SM_BeginFadingOut );	// ignore ScreenAttract's SecsToShow
	this->PostScreenMessage( SM_BeginFadingOut, 0.2f * i + 3.0f );

	SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("music scroll") );
}
Exemplo n.º 2
0
void ScreenUnlockStatus::Init()
{
	ScreenAttract::Init();

	unsigned iNumUnlocks = UNLOCKMAN->m_UnlockEntries.size();

	if( !PREFSMAN->m_bUseUnlockSystem || iNumUnlocks == 0 )
	{
		this->PostScreenMessage( SM_GoToNextScreen, 0 );
		return;
	}

	unsigned NumUnlocks = UNLOCKMAN->m_UnlockEntries.size();

	PointsUntilNextUnlock.LoadFromFont( THEME->GetPathF("Common","normal") );
	PointsUntilNextUnlock.SetHorizAlign( align_left );

	apActorCommands IconCommand = ICON_COMMAND;
	for( unsigned i=1; i <= NumUnlocks; i++ )
	{
		// get pertaining UnlockEntry
		const UnlockEntry &entry = UNLOCKMAN->m_UnlockEntries[i-1];
		const Song *pSong = entry.m_Song.ToSong();

		if( pSong == NULL)
			continue;

		Sprite* pSpr = new Sprite;

		// new unlock graphic
		pSpr->Load( THEME->GetPathG("ScreenUnlockStatus",ssprintf("%04d icon", i)) );

		// set graphic location
		pSpr->SetName( ssprintf("Unlock%04d",i) );
		LOAD_ALL_COMMANDS_AND_SET_XY( pSpr );

		pSpr->RunCommands(IconCommand);
		Unlocks.push_back(pSpr);

		if ( !entry.IsLocked() )
			this->AddChild(Unlocks[Unlocks.size() - 1]);
	}

	// scrolling text
	if (UNLOCK_TEXT_SCROLL != 0)
	{
		float ScrollingTextX = UNLOCK_TEXT_SCROLL_X;
		float ScrollingTextStartY = UNLOCK_TEXT_SCROLL_START_Y;
		float ScrollingTextEndY = UNLOCK_TEXT_SCROLL_END_Y;
		float ScrollingTextZoom = UNLOCK_TEXT_SCROLL_ZOOM;
		float ScrollingTextRows = UNLOCK_TEXT_SCROLL_ROWS;
		float MaxWidth = UNLOCK_TEXT_SCROLL_MAX_WIDTH;

		float SecondsToScroll = TIME_TO_DISPLAY;
		
		if (SecondsToScroll > 2) SecondsToScroll--;

		float SECS_PER_CYCLE = 0;

		if (UNLOCK_TEXT_SCROLL != 3)
			SECS_PER_CYCLE = (float)SecondsToScroll/(ScrollingTextRows + NumUnlocks);
		else
			SECS_PER_CYCLE = (float)SecondsToScroll/(ScrollingTextRows * 3 + NumUnlocks + 4);

		for(unsigned i = 1; i <= NumUnlocks; i++)
		{
			const UnlockEntry &entry = UNLOCKMAN->m_UnlockEntries[i-1];
			
			BitmapText* text = new BitmapText;

			text->LoadFromFont( THEME->GetPathF("ScreenUnlockStatus","text") );
			text->SetHorizAlign( align_left );
			text->SetZoom(ScrollingTextZoom);

			switch( entry.m_Type )
			{
			case UnlockRewardType_Song:
				{
					const Song *pSong = entry.m_Song.ToSong();
					ASSERT( pSong != NULL );
		
					RString title = pSong->GetDisplayMainTitle();
					RString subtitle = pSong->GetDisplaySubTitle();
					if( subtitle != "" )
						title = title + "\n" + subtitle;
					text->SetMaxWidth( MaxWidth );
					text->SetText( title );
				}
				break;
			case UnlockRewardType_Course:
				{
					const Course *pCourse = entry.m_Course.ToCourse();
					ASSERT( pCourse != NULL );

					text->SetMaxWidth( MaxWidth );
					text->SetText( pCourse->GetDisplayFullTitle() );
					text->SetDiffuse( RageColor(0,1,0,1) );
				}
				break;
			default:
				text->SetText( "" );
				text->SetDiffuse( RageColor(0.5f,0,0,1) );
				break;
			}

			if( entry.IsLocked() )
			{
				text->SetText("???");
				text->SetZoomX(1);
			}
			else
			{
				// unlocked. change color
				const Song *pSong = entry.m_Song.ToSong();
				RageColor color = RageColor(1,1,1,1);
				if( pSong )
					color = SONGMAN->GetSongGroupColor(pSong->m_sGroupName);
				text->SetGlobalDiffuseColor(color);
			}

			text->SetXY( ScrollingTextX, ScrollingTextStartY );

			if (UNLOCK_TEXT_SCROLL == 3 && UNLOCK_TEXT_SCROLL_ROWS + i > NumUnlocks)
			{   // special command for last unlocks when scrolling is in effect
				float TargetRow = -0.5f + i + UNLOCK_TEXT_SCROLL_ROWS - NumUnlocks;
				float StopOffPoint = ScrollingTextEndY - TargetRow / UNLOCK_TEXT_SCROLL_ROWS * (ScrollingTextEndY - ScrollingTextStartY);
				float FirstCycleTime = (UNLOCK_TEXT_SCROLL_ROWS - TargetRow) * SECS_PER_CYCLE;
				float SecondCycleTime = (6 + TargetRow) * SECS_PER_CYCLE - FirstCycleTime;
				//LOG->Trace("Target Row: %f", TargetRow);
				//LOG->Trace("command for icon %d: %s", i, ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;linear,%f;y,%f;linear,0.1;diffusealpha,0", SECS_PER_CYCLE * (i - 1), FirstCycleTime, StopOffPoint, SecondCycleTime * 2, ScrollingTextEndY).c_str() );
				RString sCommand = ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;linear,%f;y,%f;linear,0.1;diffusealpha,0", SECS_PER_CYCLE * (i - 1), FirstCycleTime, StopOffPoint, SecondCycleTime, ScrollingTextEndY);
				text->RunCommands( ActorUtil::ParseActorCommands(sCommand) );
			}
			else
			{
				RString sCommand = ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;linear,0.1;diffusealpha,0", SECS_PER_CYCLE * (i - 1), SECS_PER_CYCLE * (ScrollingTextRows), ScrollingTextEndY);
				text->RunCommands( ActorUtil::ParseActorCommands(sCommand) );
			}

			item.push_back(text);

			if (UNLOCK_TEXT_SCROLL >= 2)
			{
				Sprite* IconCount = new Sprite;

				// new unlock graphic
				IconCount->Load( THEME->GetPathG("ScreenUnlockStatus",ssprintf("%04d icon", i)) );

				// set graphic location
				IconCount->SetXY( UNLOCK_TEXT_SCROLL_ICON_X, ScrollingTextStartY);

				IconCount->SetHeight(UNLOCK_TEXT_SCROLL_ICON_SIZE);
				IconCount->SetWidth(UNLOCK_TEXT_SCROLL_ICON_SIZE);

				if (UNLOCK_TEXT_SCROLL == 3 && UNLOCK_TEXT_SCROLL_ROWS + i > NumUnlocks)
				{
					float TargetRow = -0.5f + i + UNLOCK_TEXT_SCROLL_ROWS - NumUnlocks;
					float StopOffPoint = ScrollingTextEndY - TargetRow / UNLOCK_TEXT_SCROLL_ROWS * (ScrollingTextEndY - ScrollingTextStartY);
					float FirstCycleTime = (UNLOCK_TEXT_SCROLL_ROWS - TargetRow) * SECS_PER_CYCLE;
					float SecondCycleTime = (6 + TargetRow) * SECS_PER_CYCLE - FirstCycleTime;
					//LOG->Trace("Target Row: %f", TargetRow);
					//LOG->Trace("command for icon %d: %s", i, ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;linear,%f;y,%f;linear,0.1;diffusealpha,0", SECS_PER_CYCLE * (i - 1), FirstCycleTime, StopOffPoint, SecondCycleTime * 2, ScrollingTextEndY).c_str() );
					RString sCommand = ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;linear,%f;y,%f;linear,0.1;diffusealpha,0", SECS_PER_CYCLE * (i - 1), FirstCycleTime, StopOffPoint, SecondCycleTime, ScrollingTextEndY);
					IconCount->RunCommands( ActorUtil::ParseActorCommands(sCommand) );
				}
				else
				{
					RString sCommand = ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;linear,0.1;diffusealpha,0", SECS_PER_CYCLE * (i - 1), SECS_PER_CYCLE * (ScrollingTextRows), ScrollingTextEndY);
					IconCount->RunCommands( ActorUtil::ParseActorCommands(sCommand) );
				}

				ItemIcons.push_back(IconCount);

				//LOG->Trace("Added unlock text %d", i);
					
				if (UNLOCK_TEXT_SCROLL == 3)
				{
					if ( !entry.IsLocked() )
						LastUnlocks.push_back(i);
				}
			}
		}
	}

	if (UNLOCK_TEXT_SCROLL == 3)
	{
		float ScrollingTextX = UNLOCK_TEXT_SCROLL_X;
		float ScrollingTextStartY = UNLOCK_TEXT_SCROLL_START_Y;
		float ScrollingTextEndY = UNLOCK_TEXT_SCROLL_END_Y;
		float ScrollingTextRows = UNLOCK_TEXT_SCROLL_ROWS;
		float MaxWidth = UNLOCK_TEXT_SCROLL_MAX_WIDTH;
		float SecondsToScroll = TIME_TO_DISPLAY - 1;
		float SECS_PER_CYCLE = (float)SecondsToScroll/(ScrollingTextRows * 3 + NumUnlocks + 4);

		for(unsigned i=1; i <= UNLOCK_TEXT_SCROLL_ROWS; i++)
		{
			if (i > LastUnlocks.size())
				continue;

			unsigned NextIcon = LastUnlocks[LastUnlocks.size() - i];

			const UnlockEntry &entry = UNLOCKMAN->m_UnlockEntries[NextIcon-1];
			const Song *pSong = entry.m_Song.ToSong();
			if( pSong == NULL )
				continue;

			BitmapText* NewText = new BitmapText;

			NewText->LoadFromFont( THEME->GetPathF("ScreenUnlockStatus","text") );
			NewText->SetHorizAlign( align_left );

			RString title = pSong->GetDisplayMainTitle();
			RString subtitle = pSong->GetDisplaySubTitle();

			if( subtitle != "" )
				title = title + "\n" + subtitle;
			NewText->SetZoom(UNLOCK_TEXT_SCROLL_ZOOM);
			NewText->SetMaxWidth( MaxWidth );
			NewText->SetText( title );

			RageColor color = SONGMAN->GetSongGroupColor(pSong->m_sGroupName);
			NewText->SetGlobalDiffuseColor(color);

			NewText->SetXY(ScrollingTextX, ScrollingTextStartY);
			{
				RString sCommand = ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;", SECS_PER_CYCLE * (NumUnlocks + 2 * i - 2), SECS_PER_CYCLE * ((ScrollingTextRows - i) * 2 + 1 ), (ScrollingTextStartY + (ScrollingTextEndY - ScrollingTextStartY) * (ScrollingTextRows - i + 0.5) / ScrollingTextRows ));
				NewText->RunCommands( ActorUtil::ParseActorCommands(sCommand) );
			}

			// new unlock graphic
			Sprite* NewIcon = new Sprite;
			NewIcon->Load( THEME->GetPathG("ScreenUnlockStatus",ssprintf("%04d icon", NextIcon)) );
			NewIcon->SetXY( UNLOCK_TEXT_SCROLL_ICON_X, ScrollingTextStartY);
			NewIcon->SetHeight(UNLOCK_TEXT_SCROLL_ICON_SIZE);
			NewIcon->SetWidth(UNLOCK_TEXT_SCROLL_ICON_SIZE);
			{
				RString sCommand = ssprintf("diffusealpha,0;sleep,%f;diffusealpha,1;linear,%f;y,%f;", SECS_PER_CYCLE * (NumUnlocks + 2 * i - 2), SECS_PER_CYCLE * ((ScrollingTextRows - i) * 2 + 1 ), (ScrollingTextStartY + (ScrollingTextEndY - ScrollingTextStartY) * (ScrollingTextRows - i + 0.5) / ScrollingTextRows ));
				NewIcon->RunCommands( ActorUtil::ParseActorCommands(sCommand) );
			}

			ItemIcons.push_back(NewIcon);
			item.push_back(NewText);
		}
	}

	// NOTE: the following two loops require the iterator to 
	// be ints because if you decrement an unsigned when it
	// equals zero, you get the maximum value of an unsigned,
	// which is still greater than 0.  By typecasting it as
	// an integer, you can achieve -1, which exits the loop.

	for(int i = item.size() - 1; (int)i >= 0; i--)
		this->AddChild(item[i]);

	for(int i = ItemIcons.size() - 1; (int)i >= 0; i--)
		this->AddChild(ItemIcons[i]);

	PointsUntilNextUnlock.SetName( "PointsDisplay" );
	
	RString PointDisplay = TYPE_TO_DISPLAY;
	if (PointDisplay == "DP" || PointDisplay == "Dance")
	{
		RString sDP = ssprintf( "%d", (int)UNLOCKMAN->PointsUntilNextUnlock(UnlockRequirement_DancePoints) );
		PointsUntilNextUnlock.SetText( sDP );
	}
	else if (PointDisplay == "AP" || PointDisplay == "Arcade") 
	{
		RString sAP = ssprintf( "%d", (int)UNLOCKMAN->PointsUntilNextUnlock(UnlockRequirement_ArcadePoints) );
		PointsUntilNextUnlock.SetText( sAP );
	}
	else if (PointDisplay == "SP" || PointDisplay == "Song") 
	{
		RString sSP = ssprintf( "%d", (int)UNLOCKMAN->PointsUntilNextUnlock(UnlockRequirement_SongPoints) );
		PointsUntilNextUnlock.SetText( sSP );
	}

	PointsUntilNextUnlock.SetZoom( POINTS_ZOOM );
	LOAD_ALL_COMMANDS_AND_SET_XY( PointsUntilNextUnlock );
	this->AddChild( &PointsUntilNextUnlock );

	this->ClearMessageQueue( SM_BeginFadingOut );	// ignore ScreenAttract's SecsToShow

	this->PostScreenMessage( SM_BeginFadingOut, TIME_TO_DISPLAY );
}
Exemplo n.º 3
0
void MusicWheelItem::LoadFromWheelItemData( WheelItemData* pWID )
{
	ASSERT( pWID != NULL );
	
	
	
	data = pWID;
	/*
	// copy all data items
	this->m_Type	= pWID->m_Type;
	this->m_sSectionName	= pWID->m_sSectionName;
	this->m_pCourse			= pWID->m_pCourse;
	this->m_pSong			= pWID->m_pSong;
	this->m_color			= pWID->m_color;
	this->m_Type		= pWID->m_Type; */


	// init type specific stuff
	switch( pWID->m_Type )
	{
	case TYPE_SECTION:
	case TYPE_COURSE:
	case TYPE_SORT:
		{
			CString sDisplayName, sTranslitName;
			BitmapText *bt = NULL;
			switch( pWID->m_Type )
			{
				case TYPE_SECTION:
					sDisplayName = SONGMAN->ShortenGroupName(data->m_sSectionName);
					bt = &m_textSectionName;
					break;
				case TYPE_COURSE:
					sDisplayName = data->m_pCourse->GetFullDisplayTitle();
					sTranslitName = data->m_pCourse->GetFullTranslitTitle();
					bt = &m_textCourse;
					break;
				case TYPE_SORT:
					sDisplayName = data->m_sLabel;
					bt = &m_textSort;
					break;
				default:
					ASSERT(0);
			}

			bt->SetZoom( 1 );
			bt->SetText( sDisplayName, sTranslitName );
			bt->SetDiffuse( data->m_color );
			bt->TurnRainbowOff();

			const float fSourcePixelWidth = (float)bt->GetUnzoomedWidth();
			const float fMaxTextWidth = 200;
			if( fSourcePixelWidth > fMaxTextWidth  )
				bt->SetZoomX( fMaxTextWidth / fSourcePixelWidth );
		}
		break;
	case TYPE_SONG:
		{
			m_TextBanner.LoadFromSong( data->m_pSong );
			m_TextBanner.SetDiffuse( data->m_color );
			m_WheelNotifyIcon.SetFlags( data->m_Flags );
			RefreshGrades();
		}
		break;
	case TYPE_ROULETTE:
		m_textRoulette.SetText( THEME->GetMetric("MusicWheel","Roulette") );
		break;

	case TYPE_RANDOM:
		m_textRoulette.SetText( THEME->GetMetric("MusicWheel","Random") );
		break;

	case TYPE_PORTAL:
		m_textRoulette.SetText( THEME->GetMetric("MusicWheel","Portal") );
		break;

	default:
		ASSERT( 0 );	// invalid type
	}
}
Exemplo n.º 4
0
ScreenCredits::ScreenCredits( CString sName ) : ScreenAttract( sName )
{
	vector<Song*> arraySongs;
	SONGMAN->GetSongs( arraySongs );
	SongUtil::SortSongPointerArrayByTitle( arraySongs );

	// FIXME:  Redo this screen with a BGA
	m_ScrollerBackgrounds.SetName( "Backgrounds" );
	m_ScrollerBackgrounds.Load(
		BACKGROUNDS_SCROLL_SECONDS_PER_ITEM,
		4,
		RageVector3(0, 0, 0),
		RageVector3(0, 0, 0),
		RageVector3(BACKGROUNDS_SPACING_X, BACKGROUNDS_SPACING_Y, 0),
		RageVector3(0, 0, 0) );
	SET_XY( m_ScrollerBackgrounds );
	this->AddChild( &m_ScrollerBackgrounds );

	m_ScrollerFrames.SetName( "Backgrounds" );
	m_ScrollerFrames.Load(
		BACKGROUNDS_SCROLL_SECONDS_PER_ITEM,
		4,
		RageVector3(0, 0, 0),
		RageVector3(0, 0, 0),
		RageVector3(BACKGROUNDS_SPACING_X, BACKGROUNDS_SPACING_Y, 0),
		RageVector3(0, 0, 0) );
	SET_XY( m_ScrollerFrames );
	this->AddChild( &m_ScrollerFrames );

	float fTime = 0;
	{
		for( int i=0; i<NUM_BACKGROUNDS; i++ )
		{
			Song* pSong = NULL;
			for( int j=0; j<50; j++ )
			{
				pSong = arraySongs[ rand()%arraySongs.size() ];
				if( pSong->HasBackground() )
					break;
			}

			Sprite* pBackground = new Sprite;
			pBackground->LoadBG( pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathToG("Common fallback background") );
			pBackground->ScaleToClipped( BACKGROUNDS_WIDTH, BACKGROUNDS_HEIGHT );
			m_ScrollerBackgrounds.AddChild( pBackground );

			Sprite* pFrame = new Sprite;
			pFrame->Load( THEME->GetPathToG("ScreenCredits background frame") );
			m_ScrollerFrames.AddChild( pFrame );
		}
		const int iFirst = -2, iLast = NUM_BACKGROUNDS+2;
		m_ScrollerBackgrounds.SetCurrentAndDestinationItem( iFirst );
		m_ScrollerBackgrounds.SetDestinationItem( iLast );

		m_ScrollerFrames.SetCurrentAndDestinationItem( iFirst );
		m_ScrollerFrames.SetDestinationItem( iLast );

		fTime = max( fTime, BACKGROUNDS_SCROLL_SECONDS_PER_ITEM*(iLast-iFirst) );
	}
	
	m_ScrollerTexts.SetName( "Texts" );
	m_ScrollerTexts.Load(
		TEXTS_SCROLL_SECONDS_PER_ITEM,
		40,
		RageVector3(0, 0, 0),
		RageVector3(0, 0, 0),
		RageVector3(TEXTS_SPACING_X, TEXTS_SPACING_Y, 0),
		RageVector3(0, 0, 0) );
	SET_XY( m_ScrollerTexts );
	this->AddChild( &m_ScrollerTexts );
	
	{
		for( unsigned i=0; i<ARRAYSIZE(CREDIT_LINES); i++ )
		{
			BitmapText* pText = new BitmapText;
			pText->LoadFromFont( THEME->GetPathToF("ScreenCredits titles") );
			pText->SetText( CREDIT_LINES[i].text );
			switch( CREDIT_LINES[i].colorIndex )
			{
			case 1:	pText->SetDiffuse( TEXTS_COLOR_INTRO );		break;
			case 2:	pText->SetDiffuse( TEXTS_COLOR_HEADER );	break;
			case 0:	pText->SetDiffuse( TEXTS_COLOR_NORMAL );	break;
			default:	ASSERT(0);
			}
			pText->SetZoom( TEXTS_ZOOM );
			m_ScrollerTexts.AddChild( pText );
		}

		const int iFirst = -10, iLast = ARRAYSIZE(CREDIT_LINES)+10;
		m_ScrollerTexts.SetCurrentAndDestinationItem( iFirst );
		m_ScrollerTexts.SetDestinationItem( iLast );
		fTime = max( fTime, TEXTS_SCROLL_SECONDS_PER_ITEM*(iLast-iFirst) );
	}

	m_Overlay.LoadFromAniDir( THEME->GetPathToB("ScreenCredits overlay") );
	this->AddChild( &m_Overlay );

	this->MoveToTail( &m_In );		// put it in the back so it covers up the stuff we just added
	this->MoveToTail( &m_Out );		// put it in the back so it covers up the stuff we just added

	this->ClearMessageQueue( SM_BeginFadingOut );	// ignore ScreenAttract's SecsToShow
	LOG->Trace("XXXXXXXXX %f", fTime);
	this->PostScreenMessage( SM_BeginFadingOut, fTime );
//	this->PostScreenMessage( SM_BeginFadingOut, m_Background.GetLengthSeconds() );
	SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("credits") );
}
Exemplo n.º 5
0
ScreenCredits::ScreenCredits( CString sName ) : ScreenAttract( sName )
{
	vector<Song*> arraySongs;
	SONGMAN->GetSongs( arraySongs );
	SongUtil::SortSongPointerArrayByTitle( arraySongs );

	// FIXME:  Redo this screen with a BGA
	CString sBackgroundsTransformFunction = ssprintf(
		"function(self,offset,itemIndex,numItems) "
		"	self:x(%f*offset); "
		"	self:y(%f*offset); "
		"end",
		(float)BACKGROUNDS_SPACING_X, 
		(float)BACKGROUNDS_SPACING_Y );

	m_ScrollerBackgrounds.SetName( "Backgrounds" );
	m_ScrollerBackgrounds.Load3(
		BACKGROUNDS_SCROLL_SECONDS_PER_ITEM,
		4,
		false,
		sBackgroundsTransformFunction,
		false );
	SET_XY( m_ScrollerBackgrounds );
	this->AddChild( &m_ScrollerBackgrounds );

	m_ScrollerFrames.SetName( "Backgrounds" );
	m_ScrollerFrames.Load3(
		BACKGROUNDS_SCROLL_SECONDS_PER_ITEM,
		4,
		false,
		sBackgroundsTransformFunction,
		false );
	SET_XY( m_ScrollerFrames );
	this->AddChild( &m_ScrollerFrames );

	float fTime = 0;
	{
		for( int i=0; i<NUM_BACKGROUNDS; i++ )
		{
			Song* pSong = NULL;
			for( int j=0; j<50; j++ )
			{
				pSong = arraySongs[ rand()%arraySongs.size() ];
				if( pSong->HasBackground() )
					break;
			}

			Sprite* pBackground = new Sprite;
			pBackground->LoadBG( pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathG("Common","fallback background") );
			pBackground->ScaleToClipped( BACKGROUNDS_WIDTH, BACKGROUNDS_HEIGHT );
			m_ScrollerBackgrounds.AddChild( pBackground );

			Sprite* pFrame = new Sprite;
			pFrame->Load( THEME->GetPathG("ScreenCredits","background frame") );
			m_ScrollerFrames.AddChild( pFrame );
		}
		float fFirst = -2;
		float fLast = NUM_BACKGROUNDS+2;
		m_ScrollerBackgrounds.SetCurrentAndDestinationItem( fFirst );
		m_ScrollerBackgrounds.SetDestinationItem( fLast );

		m_ScrollerFrames.SetCurrentAndDestinationItem( fFirst );
		m_ScrollerFrames.SetDestinationItem( fLast );

		fTime = max( fTime, BACKGROUNDS_SCROLL_SECONDS_PER_ITEM*(fLast-fFirst) );
	}
	
	CString sTextsTransformFunction = ssprintf(
		"function(self,offset,itemIndex,numItems) "
		"	self:x(%f*offset); "
		"	self:y(%f*offset); "
		"end",
		(float)TEXTS_SPACING_X, 
		(float)TEXTS_SPACING_Y );

	m_ScrollerTexts.SetName( "Texts" );
	m_ScrollerTexts.Load3(
		TEXTS_SCROLL_SECONDS_PER_ITEM,
		40,
		false,
		sTextsTransformFunction,
		false );
	SET_XY( m_ScrollerTexts );
	this->AddChild( &m_ScrollerTexts );
	
	{
		for( unsigned i=0; i<ARRAYLEN(CREDIT_LINES); i++ )
		{
			BitmapText* pText = new BitmapText;
			pText->LoadFromFont( THEME->GetPathF("ScreenCredits","titles") );
			pText->SetText( CREDIT_LINES[i].text );
			switch( CREDIT_LINES[i].colorIndex )
			{
			case 1:	pText->SetDiffuse( TEXTS_COLOR_INTRO );		break;
			case 2:	pText->SetDiffuse( TEXTS_COLOR_HEADER );	break;
			case 0:	pText->SetDiffuse( TEXTS_COLOR_NORMAL );	break;
			default:	ASSERT(0);
			}
			pText->SetZoom( TEXTS_ZOOM );
			m_ScrollerTexts.AddChild( pText );
		}

		float fFirst = -10;
		float fLast = ARRAYLEN(CREDIT_LINES)+10;
		m_ScrollerTexts.SetCurrentAndDestinationItem( fFirst );
		m_ScrollerTexts.SetDestinationItem( fLast );
		fTime = max( fTime, TEXTS_SCROLL_SECONDS_PER_ITEM*(fLast-fFirst) );
	}

	this->SortByDrawOrder();

	this->ClearMessageQueue( SM_BeginFadingOut );	// ignore ScreenAttract's SecsToShow
	this->PostScreenMessage( SM_BeginFadingOut, fTime );
//	this->PostScreenMessage( SM_BeginFadingOut, m_Background.GetLengthSeconds() );
	SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("credits") );
}