Files
itgmania212121/stepmania/src/ScreenSystemLayer.cpp
T

344 lines
12 KiB
C++
Raw Normal View History

2004-11-25 19:16:46 +00:00
#include "global.h"
#include "ScreenSystemLayer.h"
#include "PrefsManager.h"
#include "ThemeManager.h"
#include "ActorUtil.h"
#include "GameState.h"
#include "MemoryCardManager.h"
#include "Profile.h"
#include "ProfileManager.h"
#include "RageDisplay.h"
#include "RageLog.h"
2005-01-26 11:21:43 +00:00
#include "Command.h"
2004-11-25 19:16:46 +00:00
REGISTER_SCREEN_CLASS( ScreenSystemLayer );
ScreenSystemLayer::ScreenSystemLayer( const CString &sName ) : Screen(sName)
2004-11-25 19:16:46 +00:00
{
MESSAGEMAN->Subscribe( this, "RefreshCreditText" );
2005-02-28 05:10:08 +00:00
MESSAGEMAN->Subscribe( this, "SystemMessage" );
MESSAGEMAN->Subscribe( this, "SystemMessageNoAnimate" );
2005-03-01 15:18:25 +00:00
CREDITS_PRESS_START.Load("ScreenSystemLayer","CreditsPressStart");
CREDITS_INSERT_CARD.Load("ScreenSystemLayer","CreditsInsertCard");
CREDITS_CARD_TOO_LATE.Load("ScreenSystemLayer","CreditsCardTooLate");
CREDITS_CARD_NO_NAME.Load("ScreenSystemLayer","CreditsCardNoName");
CREDITS_CARD_READY.Load("ScreenSystemLayer","CreditsCardReady");
CREDITS_CARD_CHECKING.Load("ScreenSystemLayer","CreditsCardChecking");
CREDITS_CARD_REMOVED.Load("ScreenSystemLayer","CreditsCardRemoved");
CREDITS_FREE_PLAY.Load("ScreenSystemLayer","CreditsFreePlay");
CREDITS_CREDITS.Load("ScreenSystemLayer","CreditsCredits");
CREDITS_NOT_PRESENT.Load("ScreenSystemLayer","CreditsNotPresent");
CREDITS_LOAD_FAILED.Load("ScreenSystemLayer","CreditsLoadFailed");
CREDITS_LOADED_FROM_LAST_GOOD_APPEND.Load("ScreenSystemLayer","CreditsLoadedFromLastGoodAppend");
CREDITS_JOIN_ONLY.Load( m_sName, "CreditsJoinOnly" );
}
ScreenSystemLayer::~ScreenSystemLayer()
{
MESSAGEMAN->Unsubscribe( this, "RefreshCreditText" );
2005-02-28 05:10:08 +00:00
MESSAGEMAN->Unsubscribe( this, "SystemMessage" );
MESSAGEMAN->Unsubscribe( this, "SystemMessageNoAnimate" );
}
void ScreenSystemLayer::Init()
{
Screen::Init();
2004-11-25 19:16:46 +00:00
this->AddChild(&m_textMessage);
this->AddChild(&m_textStats);
this->AddChild(&m_textTime);
FOREACH_PlayerNumber( p )
this->AddChild(&m_textCredits[p]);
/* "Was that a skip?" This displays a message when an update takes
* abnormally long, to quantify skips more precisely, verify them
* when they're subtle, and show the time it happened, so you can pinpoint
* the time in the log. Put a dim quad behind it to make it easier to
* read. */
m_LastSkip = 0;
const float SKIP_LEFT = 320.0f, SKIP_TOP = 60.0f,
SKIP_WIDTH = 160.0f, SKIP_Y_DIST = 16.0f;
m_SkipBackground.StretchTo(RectF(SKIP_LEFT-8, SKIP_TOP-8,
SKIP_LEFT+SKIP_WIDTH, SKIP_TOP+SKIP_Y_DIST*NUM_SKIPS_TO_SHOW));
m_SkipBackground.SetDiffuse( RageColor(0,0,0,0.4f) );
m_SkipBackground.SetHidden( !PREFSMAN->m_bTimestamping );
this->AddChild(&m_SkipBackground);
for( int i=0; i<NUM_SKIPS_TO_SHOW; i++ )
{
/* This is somewhat big. Let's put it on the right side, where it'll
* obscure the 2P side during gameplay; there's nowhere to put it that
* doesn't obscure something, and it's just a diagnostic. */
2005-02-06 03:32:53 +00:00
m_textSkips[i].LoadFromFont( THEME->GetPathF("Common","normal") );
2004-11-25 19:16:46 +00:00
m_textSkips[i].SetXY( SKIP_LEFT, SKIP_TOP + SKIP_Y_DIST*i );
m_textSkips[i].SetHorizAlign( Actor::align_left );
m_textSkips[i].SetVertAlign( Actor::align_top );
m_textSkips[i].SetZoom( 0.5f );
m_textSkips[i].SetDiffuse( RageColor(1,1,1,0) );
m_textSkips[i].SetShadowLength( 0 );
this->AddChild(&m_textSkips[i]);
}
ReloadCreditsText();
/* This will be done when we set up the first screen, after GAMESTATE->Reset has
* been called. */
// RefreshCreditsMessages();
}
void ScreenSystemLayer::ReloadCreditsText()
{
2005-02-06 03:32:53 +00:00
m_textMessage.LoadFromFont( THEME->GetPathF("ScreenSystemLayer","message") );
2004-11-25 19:16:46 +00:00
m_textMessage.SetName( "Message" );
2005-05-09 09:49:13 +00:00
SET_XY_AND_ON_COMMAND( m_textMessage );
m_textMessage.SetHidden( true );
2004-11-25 19:16:46 +00:00
2005-02-06 03:32:53 +00:00
m_textStats.LoadFromFont( THEME->GetPathF("ScreenSystemLayer","stats") );
2004-11-25 19:16:46 +00:00
m_textStats.SetName( "Stats" );
SET_XY_AND_ON_COMMAND( m_textStats );
2005-02-06 03:32:53 +00:00
m_textTime.LoadFromFont( THEME->GetPathF("ScreenSystemLayer","time") );
2004-11-25 19:16:46 +00:00
m_textTime.SetName( "Time" );
m_textTime.SetHidden( !PREFSMAN->m_bTimestamping );
SET_XY_AND_ON_COMMAND( m_textTime );
FOREACH_PlayerNumber( p )
{
2005-02-06 03:32:53 +00:00
m_textCredits[p].LoadFromFont( THEME->GetPathF("ScreenManager","credits") );
2004-11-25 19:16:46 +00:00
m_textCredits[p].SetName( ssprintf("CreditsP%d",p+1) );
SET_XY_AND_ON_COMMAND( &m_textCredits[p] );
}
}
CString ScreenSystemLayer::GetCreditsMessage( PlayerNumber pn ) const
2004-11-25 19:16:46 +00:00
{
2005-03-01 18:45:04 +00:00
if( (bool)CREDITS_JOIN_ONLY && !GAMESTATE->PlayersCanJoin() )
return "";
bool bShowCreditsMessage;
2005-05-19 23:29:39 +00:00
if( SCREENMAN && SCREENMAN->GetTopScreen() && SCREENMAN->GetTopScreen()->GetScreenType() == system_menu )
bShowCreditsMessage = true;
else if( MEMCARDMAN->GetCardsLocked() )
bShowCreditsMessage = !GAMESTATE->IsPlayerEnabled( pn );
else
bShowCreditsMessage = !GAMESTATE->m_bSideIsJoined[pn];
2004-11-25 19:16:46 +00:00
if( !bShowCreditsMessage )
{
MemoryCardState mcs = MEMCARDMAN->GetCardState( pn );
const Profile* pProfile = PROFILEMAN->GetProfile( pn );
switch( mcs )
2004-11-25 19:16:46 +00:00
{
case MEMORY_CARD_STATE_NO_CARD:
// this is a local machine profile
if( PROFILEMAN->LastLoadWasFromLastGood(pn) )
2005-03-01 15:18:25 +00:00
return pProfile->GetDisplayName() + CREDITS_LOADED_FROM_LAST_GOOD_APPEND.GetValue();
else if( PROFILEMAN->LastLoadWasTamperedOrCorrupt(pn) )
2005-03-01 15:18:25 +00:00
return CREDITS_LOAD_FAILED.GetValue();
// Prefer the name of the profile over the name of the card.
else if( PROFILEMAN->IsPersistentProfile(pn) )
return pProfile->GetDisplayName();
else if( GAMESTATE->PlayersCanJoin() )
2005-03-01 15:18:25 +00:00
return CREDITS_INSERT_CARD.GetValue();
else
return "";
case MEMORY_CARD_STATE_ERROR: return THEME->GetMetric( m_sName, "CreditsCard" + MEMCARDMAN->GetCardError(pn) );
2005-03-01 15:18:25 +00:00
case MEMORY_CARD_STATE_TOO_LATE: return CREDITS_CARD_TOO_LATE.GetValue();
case MEMORY_CARD_STATE_CHECKING: return CREDITS_CARD_CHECKING.GetValue();
case MEMORY_CARD_STATE_REMOVED: return CREDITS_CARD_REMOVED.GetValue();
case MEMORY_CARD_STATE_READY:
{
// If the profile failed to load and there was no usable backup...
if( PROFILEMAN->LastLoadWasTamperedOrCorrupt(pn) && !PROFILEMAN->LastLoadWasFromLastGood(pn) )
return CREDITS_LOAD_FAILED.GetValue();
// If there is a local profile loaded, prefer it over the name of the memory card.
if( PROFILEMAN->IsPersistentProfile(pn) )
{
CString s = pProfile->GetDisplayName();
if( s.empty() )
s = CREDITS_CARD_NO_NAME.GetValue();
if( PROFILEMAN->LastLoadWasFromLastGood(pn) )
s += CREDITS_LOADED_FROM_LAST_GOOD_APPEND.GetValue();
return s;
}
else if( !MEMCARDMAN->IsNameAvailable(pn) )
return CREDITS_CARD_READY.GetValue();
else if( !MEMCARDMAN->GetName(pn).empty() )
return MEMCARDMAN->GetName(pn);
else
return CREDITS_CARD_NO_NAME.GetValue();
}
default:
FAIL_M( ssprintf("%i",mcs) );
2004-11-25 19:16:46 +00:00
}
}
else // bShowCreditsMessage
{
switch( GAMESTATE->GetCoinMode() )
2004-11-25 19:16:46 +00:00
{
2005-05-20 17:45:44 +00:00
case COIN_MODE_HOME:
if( GAMESTATE->PlayersCanJoin() )
2005-03-01 15:18:25 +00:00
return CREDITS_PRESS_START.GetValue();
else
2005-03-01 15:18:25 +00:00
return CREDITS_NOT_PRESENT.GetValue();
2004-11-25 19:16:46 +00:00
2005-05-20 17:45:44 +00:00
case COIN_MODE_PAY:
{
int Credits = GAMESTATE->m_iCoins / PREFSMAN->m_iCoinsPerCredit;
int Coins = GAMESTATE->m_iCoins % PREFSMAN->m_iCoinsPerCredit;
CString sCredits = CREDITS_CREDITS;
if( Credits > 0 || PREFSMAN->m_iCoinsPerCredit == 1 )
sCredits += ssprintf(" %d", Credits);
if( PREFSMAN->m_iCoinsPerCredit > 1 )
2005-05-06 20:41:05 +00:00
sCredits += ssprintf(" %d/%d", Coins, PREFSMAN->m_iCoinsPerCredit.Get() );
return sCredits;
}
2005-05-20 17:45:44 +00:00
case COIN_MODE_FREE:
if( GAMESTATE->PlayersCanJoin() )
2005-03-01 15:18:25 +00:00
return CREDITS_FREE_PLAY.GetValue();
else
2005-03-01 15:18:25 +00:00
return CREDITS_NOT_PRESENT.GetValue();
default:
ASSERT(0);
}
2004-11-25 19:16:46 +00:00
}
}
void ScreenSystemLayer::HandleMessage( const CString &sMessage )
{
if( sMessage == "RefreshCreditText" )
{
// update joined
FOREACH_PlayerNumber( pn )
m_textCredits[pn].SetText( GetCreditsMessage(pn) );
}
2005-02-28 05:10:08 +00:00
else if( sMessage == "SystemMessage" )
{
2005-05-09 09:49:13 +00:00
m_textMessage.SetHidden( false );
2005-02-28 05:10:08 +00:00
m_textMessage.SetText( SCREENMAN->GetCurrentSystemMessage() );
2005-05-09 09:49:13 +00:00
m_textMessage.PlayCommand( "On" );
2005-05-12 21:55:48 +00:00
m_textMessage.PlayCommand( "Off" );
2005-02-28 05:10:08 +00:00
}
else if( sMessage == "SystemMessageNoAnimate" )
{
2005-05-09 09:49:13 +00:00
m_textMessage.SetHidden( false );
2005-02-28 05:10:08 +00:00
m_textMessage.SetText( SCREENMAN->GetCurrentSystemMessage() );
2005-05-09 09:49:13 +00:00
m_textMessage.PlayCommand( "On" );
m_textMessage.FinishTweening();
2005-05-12 21:55:48 +00:00
m_textMessage.PlayCommand( "Off" );
2005-02-28 05:10:08 +00:00
}
Screen::HandleMessage( sMessage );
}
2004-11-26 17:28:47 +00:00
void ScreenSystemLayer::AddTimestampLine( const CString &txt, const RageColor &color )
2004-11-25 19:16:46 +00:00
{
m_textSkips[m_LastSkip].SetText( txt );
m_textSkips[m_LastSkip].StopTweening();
m_textSkips[m_LastSkip].SetDiffuse( RageColor(1,1,1,1) );
m_textSkips[m_LastSkip].BeginTweening( 0.2f );
m_textSkips[m_LastSkip].SetDiffuse( color );
m_textSkips[m_LastSkip].BeginTweening( 3.0f );
m_textSkips[m_LastSkip].BeginTweening( 0.2f );
m_textSkips[m_LastSkip].SetDiffuse( RageColor(1,1,1,0) );
m_LastSkip++;
m_LastSkip %= NUM_SKIPS_TO_SHOW;
}
2005-03-01 15:22:15 +00:00
void ScreenSystemLayer::UpdateSkips()
2004-11-25 19:16:46 +00:00
{
2005-03-01 15:22:15 +00:00
if( !PREFSMAN->m_bTimestamping && !PREFSMAN->m_bLogSkips )
return;
2004-11-25 19:16:46 +00:00
/* Use our own timer, so we ignore `/tab. */
const float UpdateTime = SkipTimer.GetDeltaTime();
/* FPS is 0 for a little while after we load a screen; don't report
* during this time. Do clear the timer, though, so we don't report
* a big "skip" after this period passes. */
2005-03-01 15:22:15 +00:00
if( !DISPLAY->GetFPS() )
return;
/* We want to display skips. We expect to get updates of about 1.0/FPS ms. */
const float ExpectedUpdate = 1.0f / DISPLAY->GetFPS();
/* These are thresholds for severity of skips. The smallest
* is slightly above expected, to tolerate normal jitter. */
const float Thresholds[] =
2004-11-25 19:16:46 +00:00
{
2005-03-01 15:22:15 +00:00
ExpectedUpdate * 2.0f, ExpectedUpdate * 4.0f, 0.1f, -1
};
2004-11-25 19:16:46 +00:00
2005-03-01 15:22:15 +00:00
int skip = 0;
while( Thresholds[skip] != -1 && UpdateTime > Thresholds[skip] )
skip++;
2004-11-25 19:16:46 +00:00
2005-03-01 15:22:15 +00:00
if( skip )
{
CString time(SecondsToMMSSMsMs(RageTimer::GetTimeSinceStartFast()));
2005-03-01 15:22:15 +00:00
static const RageColor colors[] =
2004-11-25 19:16:46 +00:00
{
2005-03-01 15:22:15 +00:00
RageColor(0,0,0,0), /* unused */
RageColor(0.2f,0.2f,1,1), /* light blue */
RageColor(1,1,0,1), /* yellow */
RageColor(1,0.2f,0.2f,1) /* light red */
};
2004-11-25 19:16:46 +00:00
2005-03-01 15:22:15 +00:00
if( PREFSMAN->m_bTimestamping )
AddTimestampLine( ssprintf("%s: %.0fms (%.0f)", time.c_str(), 1000*UpdateTime, UpdateTime/ExpectedUpdate), colors[skip] );
if( PREFSMAN->m_bLogSkips )
LOG->Trace( "Frame skip: %.0fms (%.0f)", 1000*UpdateTime, UpdateTime/ExpectedUpdate );
}
2004-11-25 19:16:46 +00:00
}
void ScreenSystemLayer::Update( float fDeltaTime )
{
Screen::Update(fDeltaTime);
2004-12-04 07:15:22 +00:00
if( PREFSMAN && (bool)PREFSMAN->m_bShowStats )
2004-11-25 19:16:46 +00:00
{
m_textStats.SetDiffuse( RageColor(1,1,1,0.7f) );
m_textStats.SetText( DISPLAY->GetStats() );
2004-12-04 07:15:22 +00:00
}
else
{
2004-11-25 19:16:46 +00:00
m_textStats.SetDiffuse( RageColor(1,1,1,0) ); /* hide */
2004-12-04 07:15:22 +00:00
}
2004-11-25 19:16:46 +00:00
2005-03-01 15:22:15 +00:00
UpdateSkips();
if( PREFSMAN->m_bTimestamping )
m_textTime.SetText( SecondsToMMSSMsMs(RageTimer::GetTimeSinceStartFast()) );
2004-11-25 19:16:46 +00:00
}
/*
2005-03-01 15:18:25 +00:00
* (c) 2001-2005 Chris Danford, Glenn Maynard
2004-11-25 19:16:46 +00:00
* 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.
*/