#include "global.h" #include "ScreenStatsOverlay.h" #include "ActorUtil.h" #include "PrefsManager.h" #include "RageDisplay.h" #include "RageLog.h" #include "ScreenDimensions.h" REGISTER_SCREEN_CLASS( ScreenStatsOverlay ); void ScreenStatsOverlay::Init() { Screen::Init(); m_textStats.LoadFromFont( THEME->GetPathF(m_sName,"stats") ); m_textStats.SetName( "Stats" ); LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_textStats ); this->AddChild( &m_textStats ); /* "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. */ m_LastSkip = 0; SHOW_SKIPS.Load( m_sName, "ShowSkips" ); if( SHOW_SKIPS ) { SKIP_X.Load( m_sName, "SkipX" ); SKIP_Y.Load( m_sName, "SkipY" ); SKIP_SPACING_Y.Load( m_sName, "SkipSpacingY" ); SKIP_WIDTH.Load( m_sName, "SkipWidth" ); RectF rectSkips = RectF( SKIP_X-SKIP_WIDTH/2, SKIP_Y-(SKIP_SPACING_Y*NUM_SKIPS_TO_SHOW)/2 - 10, SKIP_X+SKIP_WIDTH/2, SKIP_Y+(SKIP_SPACING_Y*NUM_SKIPS_TO_SHOW)/2 + 10 ); m_quadSkipBackground.StretchTo( rectSkips ); m_quadSkipBackground.SetDiffuse( RageColor(0,0,0,0.4f) ); this->AddChild(&m_quadSkipBackground); for( int i=0; iGetPathF("Common","normal") ); m_textSkips[i].SetX( SKIP_X ); m_textSkips[i].SetY( SCALE( i, 0, NUM_SKIPS_TO_SHOW-1, rectSkips.top + 10, rectSkips.bottom - 10 ) ); m_textSkips[i].SetDiffuse( RageColor(1,1,1,0) ); m_textSkips[i].SetShadowLength( 0 ); this->AddChild( &m_textSkips[i] ); } } this->SubscribeToMessage( "ShowStatsChanged" ); } void ScreenStatsOverlay::Update( float fDeltaTime ) { Screen::Update(fDeltaTime); static bool bShowStatsWasOn = false; if( PREFSMAN->m_bShowStats && !bShowStatsWasOn ) { // Reset skip timer when we toggle Stats on so we don't show a large skip // from the span when stats were turned off. m_timerSkip.Touch(); } bShowStatsWasOn = PREFSMAN->m_bShowStats.Get(); this->SetVisible( PREFSMAN->m_bShowStats ); if( PREFSMAN->m_bShowStats ) { m_textStats.SetText( DISPLAY->GetStats() ); if ( SHOW_SKIPS ) UpdateSkips(); } } void ScreenStatsOverlay::AddTimestampLine( const RString &txt, const RageColor &color ) { 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; } void ScreenStatsOverlay::UpdateSkips() { /* Use our own timer, so we ignore `/tab. */ const float UpdateTime = m_timerSkip.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. */ 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[] = { ExpectedUpdate * 2.0f, ExpectedUpdate * 4.0f, 0.1f, -1 }; int skip = 0; while( Thresholds[skip] != -1 && UpdateTime > Thresholds[skip] ) skip++; if( skip ) { RString sTime( MicrosecondsToMMSSMsMs(RageTimer::GetTimeSinceStartMicroseconds()) ); static const RageColor colors[] = { RageColor(0,0,0,0), /* unused */ RageColor(1.0f,1.0f,1.0f,1), /* white*/ RageColor(1.0f,1.0f,0.0f,1), /* yellow */ RageColor(1.0f,0.4f,0.4f,1) /* light red */ }; AddTimestampLine( ssprintf("%s: %.0fms (%.0f)", sTime.c_str(), 1000*UpdateTime, UpdateTime/ExpectedUpdate), colors[skip] ); if( PREFSMAN->m_bLogSkips ) LOG->Trace( "Frame skip: %.0fms (%.0f)", 1000*UpdateTime, UpdateTime/ExpectedUpdate ); } } /* * (c) 2001-2005 Chris Danford, Glenn Maynard * 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. */