#include "global.h" #include "ScreenHighScores.h" #include "ScreenManager.h" #include "SongManager.h" #include "Song.h" #include "RageLog.h" #include "UnlockManager.h" static const char *HighScoresTypeNames[] = { "AllSteps", "NonstopCourses", "OniCourses", "SurvivalCourses", "AllCourses", }; XToString( HighScoresType ); LuaXType( HighScoresType ); REGISTER_SCREEN_CLASS( ScreenHighScores ); static void GetAllSongsToShow( vector &vpOut, int iNumMostRecentScoresToShow ) { vpOut.clear(); FOREACH_CONST( Song*, SONGMAN->GetAllSongs(), s ) { if( !(*s)->NormallyDisplayed() ) continue; // skip if( !(*s)->ShowInDemonstrationAndRanking() ) continue; // skip vpOut.push_back( *s ); } if( (int)vpOut.size() > iNumMostRecentScoresToShow ) { SongUtil::SortSongPointerArrayByTitle( vpOut ); SongUtil::SortByMostRecentlyPlayedForMachine( vpOut ); if( (int) vpOut.size() > iNumMostRecentScoresToShow ) vpOut.erase( vpOut.begin()+iNumMostRecentScoresToShow, vpOut.end() ); } } static void GetAllCoursesToShow( vector &vpOut, CourseType ct, int iNumMostRecentScoresToShow ) { vpOut.clear(); vector vpCourses; if( ct == CourseType_Invalid ) SONGMAN->GetAllCourses( vpCourses, false ); else SONGMAN->GetCourses( ct, vpCourses, false ); FOREACH_CONST( Course*, vpCourses, c) { if( UNLOCKMAN->CourseIsLocked(*c) ) continue; // skip if( !(*c)->ShowInDemonstrationAndRanking() ) continue; // skip vpOut.push_back( *c ); } if( (int)vpOut.size() > iNumMostRecentScoresToShow ) { CourseUtil::SortCoursePointerArrayByTitle( vpOut ); CourseUtil::SortByMostRecentlyPlayedForMachine( vpOut ); if( (int) vpOut.size() > iNumMostRecentScoresToShow ) vpOut.erase( vpOut.begin()+iNumMostRecentScoresToShow, vpOut.end() ); } } ///////////////////////////////////////////// ScoreScroller::ScoreScroller() { this->DeleteChildrenWhenDone(); } void ScoreScroller::SetDisplay( const vector &DifficultiesToShow ) { m_DifficultiesToShow = DifficultiesToShow; ShiftSubActors( INT_MAX ); } bool ScoreScroller::Scroll( int iDir ) { if( (int)m_vScoreRowItemData.size() <= SCROLLER_ITEMS_TO_DRAW ) return false; float fDest = GetDestinationItem(); float fOldDest = fDest; fDest += iDir; float fLowClamp = (SCROLLER_ITEMS_TO_DRAW-1)/2.0f; float fHighClamp = m_vScoreRowItemData.size()-(SCROLLER_ITEMS_TO_DRAW-1)/2.0f-1; CLAMP( fDest, fLowClamp, fHighClamp ); if( fOldDest != fDest ) { SetDestinationItem( fDest ); return true; } else { return false; } } void ScoreScroller::ScrollTop() { SetCurrentAndDestinationItem( (SCROLLER_ITEMS_TO_DRAW-1)/2.0f ); } void ScoreScroller::ConfigureActor( Actor *pActor, int iItem ) { LOG->Trace("ScoreScroller::ConfigureActor"); Actor &item = *dynamic_cast(pActor); const ScoreRowItemData &data = m_vScoreRowItemData[iItem]; Message msg("Set"); if( data.m_pSong != NULL ) msg.SetParam( "Song", data.m_pSong ); if( data.m_pCourse != NULL ) msg.SetParam( "Course", data.m_pCourse ); Lua *L = LUA->Get(); lua_newtable( L ); lua_pushvalue( L, -1 ); msg.SetParamFromStack( L, "Entries" ); FOREACH( DifficultyAndStepsType, m_DifficultiesToShow, iter ) { int i = iter-m_DifficultiesToShow.begin(); Difficulty dc = iter->first; StepsType st = iter->second; if( data.m_pSong != NULL ) { const Song* pSong = data.m_pSong; Steps *pSteps = SongUtil::GetStepsByDifficulty( pSong, st, dc, false ); if( pSteps && UNLOCKMAN->StepsIsLocked(pSong, pSteps) ) pSteps = NULL; LuaHelpers::Push( L, pSteps ); } else if( data.m_pCourse != NULL ) { const Course* pCourse = data.m_pCourse; Trail *pTrail = pCourse->GetTrail( st, dc ); LuaHelpers::Push( L, pTrail ); } // Because pSteps or pTrail can be NULL, what we're creating in Lua is not an array. // It must be iterated using pairs(), not ipairs(). lua_setfield( L, -2, ssprintf("%d",i+1) ); } lua_pop( L, 1 ); LUA->Release( L ); item.HandleMessage( msg ); LOG->Trace("end ScoreScroller::ConfigureActor"); } void ScoreScroller::LoadSongs( int iNumRecentScores ) { vector vpSongs; GetAllSongsToShow( vpSongs, iNumRecentScores ); m_vScoreRowItemData.resize( vpSongs.size() ); for( unsigned i=0; i vpCourses; GetAllCoursesToShow( vpCourses, ct, iNumRecentScores ); m_vScoreRowItemData.resize( vpCourses.size() ); for( unsigned i=0; iGetPathG(sMetricsGroup,"ScrollerItem") ); this->AddChild( pActor ); } DynamicActorScroller::SetTransformFromReference( THEME->GetMetricR(sMetricsGroup,"ScrollerItemTransformFunction") ); DynamicActorScroller::SetNumItemsToDraw( (float) SCROLLER_ITEMS_TO_DRAW ); DynamicActorScroller::SetSecondsPerItem( SCROLLER_SECONDS_PER_ITEM ); DynamicActorScroller::Load2(); m_iNumItems = m_vScoreRowItemData.size(); } ///////////////////////////////////////////// RString COLUMN_DIFFICULTY_NAME( size_t i ) { return ssprintf("ColumnDifficulty%d",int(i+1)); } RString COLUMN_STEPS_TYPE_NAME( size_t i ) { return ssprintf("ColumnStepsType%d",int(i+1)); } void ScreenHighScores::Init() { ScreenAttract::Init(); MANUAL_SCROLLING.Load( m_sName,"ManualScrolling"); HIGH_SCORES_TYPE.Load( m_sName,"HighScoresType"); NUM_COLUMNS.Load( m_sName, "NumColumns" ); COLUMN_DIFFICULTY.Load( m_sName, COLUMN_DIFFICULTY_NAME, NUM_COLUMNS ); COLUMN_STEPS_TYPE.Load( m_sName, COLUMN_STEPS_TYPE_NAME, NUM_COLUMNS ); MAX_ITEMS_TO_SHOW.Load( m_sName, "MaxItemsToShow" ); m_Scroller.SetName( "Scroller" ); LOAD_ALL_COMMANDS( m_Scroller ); switch( HIGH_SCORES_TYPE ) { DEFAULT_FAIL( HIGH_SCORES_TYPE.GetValue() ); case HighScoresType_AllSteps: m_Scroller.LoadSongs( MAX_ITEMS_TO_SHOW ); break; case HighScoresType_NonstopCourses: case HighScoresType_OniCourses: case HighScoresType_SurvivalCourses: case HighScoresType_AllCourses: { CourseType ct; switch( HIGH_SCORES_TYPE ) { default: ASSERT(0); case HighScoresType_NonstopCourses: ct = COURSE_TYPE_NONSTOP; break; case HighScoresType_OniCourses: ct = COURSE_TYPE_ONI; break; case HighScoresType_SurvivalCourses: ct = COURSE_TYPE_SURVIVAL; break; case HighScoresType_AllCourses: ct = CourseType_Invalid; break; } m_Scroller.LoadCourses( ct, MAX_ITEMS_TO_SHOW ); } break; } m_Scroller.Load( m_sName ); this->AddChild( &m_Scroller ); } void ScreenHighScores::BeginScreen() { ScreenAttract::BeginScreen(); vector vdast; for( int i=0; iPostScreenMessage( SM_BeginFadingOut, fSecs ); } void ScreenHighScores::Input( const InputEventPlus &input ) { //LOG->Trace( "ScreenRanking::Input()" ); if( IsTransitioning() ) return; // If manually scrolling, then pass the input to Scree::Input so it will call Menu* if( (bool)MANUAL_SCROLLING ) Screen::Input( input ); else ScreenAttract::Input( input ); } void ScreenHighScores::HandleScreenMessage( const ScreenMessage SM ) { if( SM == SM_BeginFadingOut ) /* Screen is starting to tween out. */ { StartTransitioningScreen( SM_GoToNextScreen ); } ScreenAttract::HandleScreenMessage( SM ); } void ScreenHighScores::MenuStart( const InputEventPlus &input ) { if( !MANUAL_SCROLLING ) return; if( !IsTransitioning() ) StartTransitioningScreen( SM_GoToNextScreen ); SCREENMAN->PlayStartSound(); } void ScreenHighScores::MenuBack( const InputEventPlus &input ) { if( !MANUAL_SCROLLING ) return; if( !IsTransitioning() ) StartTransitioningScreen( SM_GoToNextScreen ); SCREENMAN->PlayStartSound(); } void ScreenHighScores::DoScroll( int iDir ) { if( !m_Scroller.Scroll(iDir) ) iDir = 0; Message msg("Scrolled"); msg.SetParam( "Dir", iDir ); this->HandleMessage( msg ); } /* * (c) 2001-2007 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. */