2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2002-01-16 10:01:32 +00:00
|
|
|
#include "MusicWheel.h"
|
|
|
|
|
#include "RageUtil.h"
|
2002-02-28 19:40:40 +00:00
|
|
|
#include "SongManager.h"
|
2002-03-19 07:09:49 +00:00
|
|
|
#include "GameManager.h"
|
2002-07-23 01:41:40 +00:00
|
|
|
#include "PrefsManager.h"
|
2002-05-19 01:59:48 +00:00
|
|
|
#include "ScreenManager.h" // for sending SM_PlayMusicSample
|
2002-05-01 19:14:55 +00:00
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "GameConstantsAndTypes.h"
|
2002-07-23 01:41:40 +00:00
|
|
|
#include "GameState.h"
|
2002-11-11 04:53:31 +00:00
|
|
|
#include "ThemeManager.h"
|
2003-04-03 21:29:14 +00:00
|
|
|
#include "song.h"
|
2003-03-31 23:06:15 +00:00
|
|
|
#include "Course.h"
|
2003-08-03 00:13:55 +00:00
|
|
|
#include "Steps.h"
|
2005-02-21 06:22:46 +00:00
|
|
|
#include "UnlockManager.h"
|
2004-12-02 06:29:20 +00:00
|
|
|
#include "GameCommand.h"
|
2003-11-18 18:07:37 +00:00
|
|
|
#include "ActorUtil.h"
|
2004-04-18 07:34:37 +00:00
|
|
|
#include "SongUtil.h"
|
2004-04-18 08:36:04 +00:00
|
|
|
#include "CourseUtil.h"
|
2004-06-02 05:49:38 +00:00
|
|
|
#include "Foreach.h"
|
2004-07-25 04:27:20 +00:00
|
|
|
#include "Style.h"
|
2004-11-06 20:36:04 +00:00
|
|
|
#include "ThemeMetric.h"
|
2004-12-20 06:25:59 +00:00
|
|
|
#include "PlayerState.h"
|
2002-01-20 08:59:38 +00:00
|
|
|
|
2006-04-06 09:39:29 +00:00
|
|
|
static Preference<bool> g_bMoveRandomToEnd( "MoveRandomToEnd", false );
|
|
|
|
|
|
2005-03-13 18:17:09 +00:00
|
|
|
#define NUM_WHEEL_ITEMS ((int)ceil(NUM_WHEEL_ITEMS_TO_DRAW+2))
|
2006-01-08 18:40:20 +00:00
|
|
|
#define WHEEL_TEXT(s) THEME->GetString( "MusicWheel", ssprintf("%sText",s.c_str()) );
|
2005-03-17 09:34:05 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
static RString SECTION_COLORS_NAME( size_t i ) { return ssprintf("SectionColor%d",int(i+1)); }
|
|
|
|
|
static RString CHOICE_NAME( RString s ) { return ssprintf("Choice%s",s.c_str()); }
|
2005-03-23 09:57:04 +00:00
|
|
|
|
2005-03-28 08:01:36 +00:00
|
|
|
AutoScreenMessage( SM_SongChanged ) // TODO: Replace this with a Message and MESSAGEMAN
|
|
|
|
|
AutoScreenMessage( SM_SortOrderChanging );
|
|
|
|
|
AutoScreenMessage( SM_SortOrderChanged );
|
2005-03-23 09:57:04 +00:00
|
|
|
|
2005-03-02 01:48:38 +00:00
|
|
|
static const SortOrder g_SongSortOrders[] =
|
2003-06-30 07:09:13 +00:00
|
|
|
{
|
|
|
|
|
SORT_GROUP,
|
|
|
|
|
SORT_TITLE,
|
|
|
|
|
SORT_BPM,
|
2005-04-15 07:18:40 +00:00
|
|
|
SORT_POPULARITY,
|
2003-06-30 07:09:13 +00:00
|
|
|
SORT_ARTIST,
|
2005-03-02 01:48:38 +00:00
|
|
|
SORT_GENRE,
|
2003-06-30 07:09:13 +00:00
|
|
|
};
|
2006-07-18 05:51:37 +00:00
|
|
|
const vector<SortOrder> SONG_SORT_ORDERS( g_SongSortOrders, g_SongSortOrders + ARRAYSIZE(g_SongSortOrders) );
|
2005-03-02 01:48:38 +00:00
|
|
|
|
2005-09-03 04:34:04 +00:00
|
|
|
static SortOrder ForceAppropriateSort( PlayMode pm, SortOrder so )
|
2005-01-29 20:46:08 +00:00
|
|
|
{
|
|
|
|
|
switch( pm )
|
|
|
|
|
{
|
|
|
|
|
// in course modes, force a particular sort
|
|
|
|
|
case PLAY_MODE_ONI: return SORT_ONI_COURSES;
|
|
|
|
|
case PLAY_MODE_NONSTOP: return SORT_NONSTOP_COURSES;
|
|
|
|
|
case PLAY_MODE_ENDLESS: return SORT_ENDLESS_COURSES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we're not in a course mode, don't start in a course sort. */
|
|
|
|
|
switch( so )
|
|
|
|
|
{
|
|
|
|
|
case SORT_ONI_COURSES:
|
|
|
|
|
case SORT_NONSTOP_COURSES:
|
|
|
|
|
case SORT_ENDLESS_COURSES:
|
|
|
|
|
so = SORT_INVALID;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return so;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelItemBase *MusicWheel::MakeItem()
|
|
|
|
|
{
|
|
|
|
|
return new MusicWheelItem;
|
|
|
|
|
}
|
2005-01-29 20:46:08 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void MusicWheel::Load( RString sType )
|
2005-03-17 09:34:05 +00:00
|
|
|
{
|
2006-08-10 06:27:47 +00:00
|
|
|
ROULETTE_SWITCH_SECONDS .Load(sType,"RouletteSwitchSeconds");
|
|
|
|
|
ROULETTE_SLOW_DOWN_SWITCHES .Load(sType,"RouletteSlowDownSwitches");
|
|
|
|
|
NUM_SECTION_COLORS .Load(sType,"NumSectionColors");
|
|
|
|
|
SONG_REAL_EXTRA_COLOR .Load(sType,"SongRealExtraColor");
|
|
|
|
|
SORT_MENU_COLOR .Load(sType,"SortMenuColor");
|
|
|
|
|
SHOW_ROULETTE .Load(sType,"ShowRoulette");
|
|
|
|
|
SHOW_RANDOM .Load(sType,"ShowRandom");
|
|
|
|
|
SHOW_PORTAL .Load(sType,"ShowPortal");
|
|
|
|
|
RANDOM_PICKS_LOCKED_SONGS .Load(sType,"RandomPicksLockedSongs");
|
|
|
|
|
MOST_PLAYED_SONGS_TO_SHOW .Load(sType,"MostPlayedSongsToShow");
|
|
|
|
|
MODE_MENU_CHOICE_NAMES .Load(sType,"ModeMenuChoiceNames");
|
|
|
|
|
vector<RString> vsModeChoiceNames;
|
|
|
|
|
split( MODE_MENU_CHOICE_NAMES, ",", vsModeChoiceNames );
|
|
|
|
|
CHOICE .Load(sType,CHOICE_NAME,vsModeChoiceNames);
|
|
|
|
|
SECTION_COLORS .Load(sType,SECTION_COLORS_NAME,NUM_SECTION_COLORS);
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelBase::Load( sType );
|
2002-09-03 06:33:08 +00:00
|
|
|
|
2003-09-29 02:23:44 +00:00
|
|
|
SONGMAN->UpdateRankingCourses();
|
|
|
|
|
|
2006-04-04 21:39:03 +00:00
|
|
|
m_soundChangeSort.Load( THEME->GetPathS(sType,"sort") );
|
|
|
|
|
m_soundExpand.Load( THEME->GetPathS(sType,"expand"), true );
|
2003-02-25 21:10:07 +00:00
|
|
|
|
2003-07-21 21:47:50 +00:00
|
|
|
/* Update for SORT_MOST_PLAYED. */
|
2006-03-20 01:04:46 +00:00
|
|
|
SONGMAN->UpdatePopular();
|
2004-02-27 21:29:31 +00:00
|
|
|
|
|
|
|
|
/* Sort SONGMAN's songs by CompareSongPointersByTitle, so we can do other sorts (with
|
|
|
|
|
* stable_sort) from its output, and title will be the secondary sort, without having
|
|
|
|
|
* to re-sort by title each time. */
|
|
|
|
|
SONGMAN->SortSongs();
|
2003-07-21 21:47:50 +00:00
|
|
|
|
2003-12-12 04:46:46 +00:00
|
|
|
RageTimer timer;
|
2006-01-22 01:00:06 +00:00
|
|
|
RString times;
|
2003-12-12 04:46:46 +00:00
|
|
|
/* Build all of the wheel item data. Do this after selecting
|
2002-08-30 21:51:40 +00:00
|
|
|
* the extra stage, so it knows to always display it. */
|
2005-06-12 23:43:39 +00:00
|
|
|
FOREACH_SortOrder( so )
|
2003-12-12 04:46:46 +00:00
|
|
|
{
|
2005-06-12 23:43:39 +00:00
|
|
|
BuildWheelItemDatas( m_WheelItemDatas[so], so );
|
2003-12-12 04:46:46 +00:00
|
|
|
times += ssprintf( "%i:%.3f ", so, timer.GetDeltaTime() );
|
|
|
|
|
}
|
|
|
|
|
LOG->Trace( "took: %s", times.c_str() );
|
2002-08-30 21:51:40 +00:00
|
|
|
|
2005-01-29 20:46:08 +00:00
|
|
|
/* Set m_LastModeMenuItem to the first item that matches the current mode. (Do this
|
|
|
|
|
* after building wheel item data.) */
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
const vector<WheelItemData *> &from = m_WheelItemDatas[SORT_MODE_MENU];
|
2005-01-29 20:46:08 +00:00
|
|
|
for( unsigned i=0; i<from.size(); i++ )
|
2006-04-04 21:39:03 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( from[i]->m_Action.DescribesCurrentModeForAllPlayers() )
|
2005-01-29 20:46:08 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
m_sLastModeMenuItem = from[i]->m_Action.m_sName;
|
2005-01-29 20:46:08 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2006-04-04 21:39:03 +00:00
|
|
|
}
|
2005-01-29 20:46:08 +00:00
|
|
|
}
|
2006-04-04 21:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MusicWheel::BeginScreen()
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelBase::BeginScreen();
|
2006-04-04 21:39:03 +00:00
|
|
|
|
|
|
|
|
GAMESTATE->m_SortOrder.Set( GAMESTATE->m_PreferredSortOrder );
|
|
|
|
|
|
|
|
|
|
/* Never start in the mode menu; some elements may not initialize correctly. */
|
|
|
|
|
if( GAMESTATE->m_SortOrder == SORT_MODE_MENU )
|
|
|
|
|
GAMESTATE->m_SortOrder.Set( SORT_INVALID );
|
|
|
|
|
|
|
|
|
|
GAMESTATE->m_SortOrder.Set( ForceAppropriateSort(GAMESTATE->m_PlayMode, GAMESTATE->m_SortOrder) );
|
2005-01-29 20:46:08 +00:00
|
|
|
|
2006-04-04 21:39:03 +00:00
|
|
|
/* Only save the sort order if the player didn't already have one. If he did, don't
|
|
|
|
|
* overwrite it. */
|
|
|
|
|
if( GAMESTATE->m_PreferredSortOrder == SORT_INVALID )
|
|
|
|
|
GAMESTATE->m_PreferredSortOrder = GAMESTATE->m_SortOrder;
|
2005-01-29 20:46:08 +00:00
|
|
|
|
2003-08-07 02:35:08 +00:00
|
|
|
// HACK: invalidate currently selected song in the case that it
|
|
|
|
|
// cannot be played due to lack of stages remaining
|
2003-08-08 20:37:17 +00:00
|
|
|
// checking for event mode shouldn't be necessary here
|
|
|
|
|
// but someone mentioned it does it sometimes.
|
2003-08-07 07:19:45 +00:00
|
|
|
if( GAMESTATE->m_pCurSong != NULL &&
|
2005-04-28 08:27:40 +00:00
|
|
|
SongManager::GetNumStagesForSong( GAMESTATE->m_pCurSong ) + GAMESTATE->m_iCurrentStageIndex > PREFSMAN->m_iSongsPerPlay
|
2005-04-05 08:30:57 +00:00
|
|
|
&& !GAMESTATE->IsEventMode()
|
2006-08-06 23:34:33 +00:00
|
|
|
&& !GAMESTATE->IsAnExtraStage() )
|
2004-10-07 22:16:04 +00:00
|
|
|
{
|
2005-02-24 12:27:30 +00:00
|
|
|
GAMESTATE->m_pCurSong.Set( NULL );
|
2004-10-07 22:16:04 +00:00
|
|
|
}
|
2003-08-07 02:35:08 +00:00
|
|
|
|
2002-08-01 05:11:11 +00:00
|
|
|
// Select the the previously selected song (if any)
|
2004-02-18 23:53:43 +00:00
|
|
|
if( !SelectSongOrCourse() )
|
|
|
|
|
SetOpenGroup("");
|
2003-01-02 02:59:25 +00:00
|
|
|
|
|
|
|
|
// rebuild the WheelItems that appear on screen
|
2006-08-10 04:27:46 +00:00
|
|
|
RebuildWheelItems();
|
2003-01-02 02:59:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MusicWheel::~MusicWheel()
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
FOREACH_SortOrder( so )
|
|
|
|
|
FOREACH( WheelItemData*, m_WheelItemDatas[so], i )
|
|
|
|
|
delete *i;
|
2003-01-02 02:59:25 +00:00
|
|
|
}
|
|
|
|
|
|
2005-02-25 00:29:09 +00:00
|
|
|
/* If a song or course is set in GAMESTATE and available, select it. Otherwise, choose the
|
2004-02-18 23:53:43 +00:00
|
|
|
* first available song or course. Return true if an item was set, false if no items are
|
|
|
|
|
* available. */
|
|
|
|
|
bool MusicWheel::SelectSongOrCourse()
|
|
|
|
|
{
|
2005-02-25 00:29:09 +00:00
|
|
|
if( GAMESTATE->m_pPreferredSong && SelectSong( GAMESTATE->m_pPreferredSong ) )
|
|
|
|
|
return true;
|
2004-02-18 23:53:43 +00:00
|
|
|
if( GAMESTATE->m_pCurSong && SelectSong( GAMESTATE->m_pCurSong ) )
|
|
|
|
|
return true;
|
2005-02-25 00:29:09 +00:00
|
|
|
if( GAMESTATE->m_pPreferredCourse && SelectCourse( GAMESTATE->m_pPreferredCourse ) )
|
|
|
|
|
return true;
|
2004-02-18 23:53:43 +00:00
|
|
|
if( GAMESTATE->m_pCurCourse && SelectCourse( GAMESTATE->m_pCurCourse ) )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// Select the first selectable song based on the sort order...
|
2006-08-10 04:27:46 +00:00
|
|
|
vector<WheelItemData *> &wiWheelItems = m_WheelItemDatas[GAMESTATE->m_SortOrder];
|
2004-02-18 23:53:43 +00:00
|
|
|
for( unsigned i = 0; i < wiWheelItems.size(); i++ )
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( wiWheelItems[i]->m_pSong )
|
|
|
|
|
return SelectSong( wiWheelItems[i]->m_pSong );
|
|
|
|
|
else if ( wiWheelItems[i]->m_pCourse )
|
|
|
|
|
return SelectCourse( wiWheelItems[i]->m_pCourse );
|
2004-02-18 23:53:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG->Trace( "MusicWheel::MusicWheel() - No selectable songs or courses found in WheelData" );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
bool MusicWheel::SelectSection( const RString & SectionName )
|
2005-01-22 05:31:35 +00:00
|
|
|
{
|
2006-08-01 21:55:32 +00:00
|
|
|
for( unsigned int i = 0; i < m_CurWheelItemData.size(); ++i )
|
2006-08-10 04:27:46 +00:00
|
|
|
{
|
2005-04-30 17:30:18 +00:00
|
|
|
if( m_CurWheelItemData[i]->m_sText == SectionName )
|
2005-01-22 05:31:35 +00:00
|
|
|
{
|
|
|
|
|
m_iSelection = i; // select it
|
2006-08-01 21:55:32 +00:00
|
|
|
return true;
|
2005-01-22 05:31:35 +00:00
|
|
|
}
|
2006-08-10 04:27:46 +00:00
|
|
|
}
|
2006-08-01 21:55:32 +00:00
|
|
|
|
|
|
|
|
return false;
|
2005-01-22 05:31:35 +00:00
|
|
|
}
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
bool MusicWheel::SelectSong( const Song *p )
|
2003-01-02 02:59:25 +00:00
|
|
|
{
|
|
|
|
|
if(p == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
unsigned i;
|
2006-08-10 04:27:46 +00:00
|
|
|
vector<WheelItemData *> &from = m_WheelItemDatas[GAMESTATE->m_SortOrder];
|
2003-01-02 02:59:25 +00:00
|
|
|
for( i=0; i<from.size(); i++ )
|
2002-01-20 09:03:37 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( from[i]->m_pSong == p )
|
2002-02-09 18:53:47 +00:00
|
|
|
{
|
2003-01-02 02:59:25 +00:00
|
|
|
// make its group the currently expanded group
|
2006-08-10 04:27:46 +00:00
|
|
|
SetOpenGroup( from[i]->m_sText );
|
2003-01-02 02:59:25 +00:00
|
|
|
break;
|
2002-02-09 18:53:47 +00:00
|
|
|
}
|
2002-01-20 09:03:37 +00:00
|
|
|
}
|
2002-02-06 05:13:39 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
if( i == from.size() )
|
2003-01-02 02:59:25 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
for( i=0; i<m_CurWheelItemData.size(); i++ )
|
2002-08-01 05:11:11 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( GetCurWheelItemData(i)->m_pSong == p )
|
2003-01-02 02:59:25 +00:00
|
|
|
m_iSelection = i; // select it
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
bool MusicWheel::SelectCourse( const Course *p )
|
2003-01-02 02:59:25 +00:00
|
|
|
{
|
|
|
|
|
if(p == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
unsigned i;
|
2006-08-10 04:27:46 +00:00
|
|
|
vector<WheelItemData *> &from = m_WheelItemDatas[GAMESTATE->m_SortOrder];
|
2003-01-02 02:59:25 +00:00
|
|
|
for( i=0; i<from.size(); i++ )
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( from[i]->m_pCourse == p )
|
2002-08-01 05:11:11 +00:00
|
|
|
{
|
2003-01-02 02:59:25 +00:00
|
|
|
// make its group the currently expanded group
|
2006-08-10 04:27:46 +00:00
|
|
|
SetOpenGroup( from[i]->m_sText );
|
2003-01-02 02:59:25 +00:00
|
|
|
break;
|
2002-08-01 05:11:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
if( i == from.size() )
|
2003-01-02 02:59:25 +00:00
|
|
|
return false;
|
2002-02-06 05:13:39 +00:00
|
|
|
|
2003-01-02 02:59:25 +00:00
|
|
|
for( i=0; i<m_CurWheelItemData.size(); i++ )
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( GetCurWheelItemData(i)->m_pCourse == p )
|
2003-01-02 02:59:25 +00:00
|
|
|
m_iSelection = i; // select it
|
|
|
|
|
}
|
2002-08-13 23:26:46 +00:00
|
|
|
|
2003-01-02 02:59:25 +00:00
|
|
|
return true;
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-29 20:46:08 +00:00
|
|
|
bool MusicWheel::SelectModeMenuItem()
|
2003-06-16 17:28:58 +00:00
|
|
|
{
|
2005-01-29 20:46:08 +00:00
|
|
|
/* Select the last-chosen option. */
|
2006-08-10 04:27:46 +00:00
|
|
|
const vector<WheelItemData *> &from = m_WheelItemDatas[GAMESTATE->m_SortOrder];
|
2003-06-16 17:28:58 +00:00
|
|
|
unsigned i;
|
|
|
|
|
for( i=0; i<from.size(); i++ )
|
2005-01-29 20:46:08 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
const GameCommand &gc = from[i]->m_Action;
|
2005-01-29 20:46:08 +00:00
|
|
|
if( gc.m_sName == m_sLastModeMenuItem )
|
2005-01-20 03:15:01 +00:00
|
|
|
break;
|
2005-01-29 20:46:08 +00:00
|
|
|
}
|
2005-01-20 03:15:01 +00:00
|
|
|
if( i == from.size() )
|
2003-06-16 17:28:58 +00:00
|
|
|
return false;
|
|
|
|
|
|
2005-01-20 03:15:01 +00:00
|
|
|
// make its group the currently expanded group
|
2006-08-10 04:27:46 +00:00
|
|
|
SetOpenGroup( from[i]->m_sText );
|
2005-01-20 03:15:01 +00:00
|
|
|
|
2003-06-16 17:28:58 +00:00
|
|
|
for( i=0; i<m_CurWheelItemData.size(); i++ )
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( GetCurWheelItemData(i)->m_Action.m_sName != m_sLastModeMenuItem )
|
2003-07-20 08:54:31 +00:00
|
|
|
continue;
|
|
|
|
|
m_iSelection = i; // select it
|
|
|
|
|
break;
|
2003-06-16 17:28:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-20 01:04:46 +00:00
|
|
|
void MusicWheel::GetSongList(vector<Song*> &arraySongs, SortOrder so, const RString &sPreferredGroup )
|
2003-01-03 03:24:00 +00:00
|
|
|
{
|
2003-02-03 05:53:59 +00:00
|
|
|
vector<Song*> apAllSongs;
|
2006-03-20 01:04:46 +00:00
|
|
|
switch( so )
|
|
|
|
|
{
|
|
|
|
|
case SORT_PREFERRED:
|
|
|
|
|
SONGMAN->GetPreferredSortSongs( apAllSongs, GAMESTATE->GetNumStagesLeft() );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_POPULARITY:
|
|
|
|
|
SONGMAN->GetPopularSongs( apAllSongs, GAMESTATE->m_sPreferredSongGroup, GAMESTATE->GetNumStagesLeft() );
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
SONGMAN->GetSongs( apAllSongs, GAMESTATE->m_sPreferredSongGroup, GAMESTATE->GetNumStagesLeft() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2003-02-03 05:53:59 +00:00
|
|
|
|
2003-08-03 00:13:55 +00:00
|
|
|
// copy only songs that have at least one Steps for the current GameMode
|
2003-02-03 05:53:59 +00:00
|
|
|
for( unsigned i=0; i<apAllSongs.size(); i++ )
|
2003-01-03 03:24:00 +00:00
|
|
|
{
|
2003-02-03 05:53:59 +00:00
|
|
|
Song* pSong = apAllSongs[i];
|
2003-01-03 03:24:00 +00:00
|
|
|
|
2004-01-25 16:24:34 +00:00
|
|
|
/* If we're on an extra stage, and this song is selected, ignore #SELECTABLE. */
|
2003-01-03 03:24:00 +00:00
|
|
|
if( pSong != GAMESTATE->m_pCurSong ||
|
2004-02-26 20:35:46 +00:00
|
|
|
(!GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2()) )
|
|
|
|
|
{
|
2003-01-03 03:24:00 +00:00
|
|
|
/* Hide songs that asked to be hidden via #SELECTABLE. */
|
2003-04-19 18:51:13 +00:00
|
|
|
if( so!=SORT_ROULETTE && !pSong->NormallyDisplayed() )
|
2003-01-03 03:24:00 +00:00
|
|
|
continue;
|
2004-02-26 20:35:46 +00:00
|
|
|
if( so!=SORT_ROULETTE && UNLOCKMAN->SongIsRouletteOnly( pSong ) )
|
|
|
|
|
continue;
|
|
|
|
|
/* Don't show in roulette if #SELECTABLE:NO. */
|
|
|
|
|
if( so==SORT_ROULETTE && !pSong->RouletteDisplayed() )
|
2003-07-07 10:22:53 +00:00
|
|
|
continue;
|
2003-01-03 03:24:00 +00:00
|
|
|
}
|
|
|
|
|
|
2005-05-09 01:26:30 +00:00
|
|
|
/* Hide locked songs. If RANDOM_PICKS_LOCKED_SONGS, hide in Roulette and Random,
|
|
|
|
|
* too. */
|
|
|
|
|
if( (so!=SORT_ROULETTE || !RANDOM_PICKS_LOCKED_SONGS) && UNLOCKMAN->SongIsLocked(pSong) )
|
2003-07-18 08:04:47 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-11-24 16:25:47 +00:00
|
|
|
// If the song has at least one steps, add it.
|
|
|
|
|
if( pSong->HasStepsType(GAMESTATE->GetCurrentStyle()->m_StepsType) )
|
2003-01-03 03:24:00 +00:00
|
|
|
arraySongs.push_back( pSong );
|
|
|
|
|
}
|
2004-09-05 02:47:30 +00:00
|
|
|
|
|
|
|
|
/* Hack: Add extra stage item if it was eliminated for any reason (eg. it's a long
|
|
|
|
|
* song). */
|
2006-08-06 02:37:42 +00:00
|
|
|
if( GAMESTATE->IsAnExtraStage() )
|
2004-09-05 02:47:30 +00:00
|
|
|
{
|
|
|
|
|
Song* pSong;
|
|
|
|
|
Steps* pSteps;
|
2005-09-03 03:52:22 +00:00
|
|
|
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(), pSong, pSteps, NULL, NULL );
|
2004-09-05 02:47:30 +00:00
|
|
|
|
|
|
|
|
if( find( arraySongs.begin(), arraySongs.end(), pSong ) == arraySongs.end() )
|
|
|
|
|
arraySongs.push_back( pSong );
|
|
|
|
|
}
|
2003-01-03 03:24:00 +00:00
|
|
|
}
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
void MusicWheel::BuildWheelItemDatas( vector<WheelItemData *> &arrayWheelItemDatas, SortOrder so )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2003-07-20 05:13:45 +00:00
|
|
|
switch( so )
|
2002-02-09 18:53:47 +00:00
|
|
|
{
|
2004-01-11 08:15:44 +00:00
|
|
|
case SORT_MODE_MENU:
|
2002-06-14 22:25:22 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
arrayWheelItemDatas.clear(); // clear out the previous wheel items
|
2006-01-22 01:00:06 +00:00
|
|
|
vector<RString> vsNames;
|
2005-06-03 01:57:10 +00:00
|
|
|
split( MODE_MENU_CHOICE_NAMES, ",", vsNames );
|
|
|
|
|
for( unsigned i=0; i<vsNames.size(); ++i )
|
2003-07-20 09:15:46 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
switch( so )
|
|
|
|
|
{
|
|
|
|
|
case SORT_ALL_COURSES:
|
|
|
|
|
case SORT_NONSTOP_COURSES:
|
|
|
|
|
case SORT_ONI_COURSES:
|
|
|
|
|
case SORT_ENDLESS_COURSES:
|
|
|
|
|
/* Don't display course modes after the first stage. */
|
|
|
|
|
if( !GAMESTATE->IsEventMode() && GAMESTATE->m_iCurrentStageIndex )
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2004-03-20 18:11:58 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelItemData wid( TYPE_SORT, NULL, "", NULL, SORT_MENU_COLOR );
|
|
|
|
|
wid.m_Action.m_sName = vsNames[i];
|
|
|
|
|
wid.m_Action.Load( i, ParseCommands(CHOICE.GetValue(vsNames[i])) );
|
|
|
|
|
wid.m_sLabel = WHEEL_TEXT(vsNames[i]);
|
|
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
if( !wid.m_Action.IsPlayable() )
|
|
|
|
|
continue;
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(wid) );
|
|
|
|
|
}
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2003-07-20 05:13:45 +00:00
|
|
|
case SORT_PREFERRED:
|
|
|
|
|
case SORT_ROULETTE:
|
|
|
|
|
case SORT_GROUP:
|
|
|
|
|
case SORT_TITLE:
|
|
|
|
|
case SORT_BPM:
|
2005-04-15 07:18:40 +00:00
|
|
|
case SORT_POPULARITY:
|
|
|
|
|
case SORT_TOP_GRADES:
|
2003-07-20 05:13:45 +00:00
|
|
|
case SORT_ARTIST:
|
2005-03-02 01:48:38 +00:00
|
|
|
case SORT_GENRE:
|
2003-07-20 05:13:45 +00:00
|
|
|
case SORT_EASY_METER:
|
|
|
|
|
case SORT_MEDIUM_METER:
|
|
|
|
|
case SORT_HARD_METER:
|
2004-01-27 05:37:43 +00:00
|
|
|
case SORT_CHALLENGE_METER:
|
2005-06-03 01:57:10 +00:00
|
|
|
{
|
|
|
|
|
///////////////////////////////////
|
|
|
|
|
// Make an array of Song*, then sort them
|
|
|
|
|
///////////////////////////////////
|
|
|
|
|
vector<Song*> arraySongs;
|
|
|
|
|
|
|
|
|
|
GetSongList(arraySongs, so, GAMESTATE->m_sPreferredSongGroup );
|
2002-02-09 18:53:47 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
bool bUseSections = true;
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
// sort the songs
|
|
|
|
|
switch( so )
|
|
|
|
|
{
|
|
|
|
|
case SORT_PREFERRED:
|
2006-03-20 01:04:46 +00:00
|
|
|
// obey order specified by the preferred sort list
|
|
|
|
|
break;
|
2005-06-03 01:57:10 +00:00
|
|
|
case SORT_ROULETTE:
|
|
|
|
|
SongUtil::SortSongPointerArrayByMeter( arraySongs, DIFFICULTY_EASY );
|
|
|
|
|
if( (bool)PREFSMAN->m_bPreferredSortUsesGroups )
|
|
|
|
|
stable_sort( arraySongs.begin(), arraySongs.end(), SongUtil::CompareSongPointersByGroup );
|
|
|
|
|
bUseSections = false;
|
|
|
|
|
break;
|
|
|
|
|
case SORT_GROUP:
|
|
|
|
|
SongUtil::SortSongPointerArrayByGroupAndTitle( arraySongs );
|
2005-06-24 06:06:16 +00:00
|
|
|
bUseSections = GAMESTATE->m_sPreferredSongGroup == GROUP_ALL;
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
|
|
|
|
case SORT_TITLE:
|
|
|
|
|
SongUtil::SortSongPointerArrayByTitle( arraySongs );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_BPM:
|
|
|
|
|
SongUtil::SortSongPointerArrayByBPM( arraySongs );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_POPULARITY:
|
|
|
|
|
if( (int) arraySongs.size() > MOST_PLAYED_SONGS_TO_SHOW )
|
|
|
|
|
arraySongs.erase( arraySongs.begin()+MOST_PLAYED_SONGS_TO_SHOW, arraySongs.end() );
|
|
|
|
|
bUseSections = false;
|
|
|
|
|
break;
|
|
|
|
|
case SORT_TOP_GRADES:
|
2005-06-28 08:11:30 +00:00
|
|
|
SongUtil::SortSongPointerArrayByGrades( arraySongs, true );
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
|
|
|
|
case SORT_ARTIST:
|
|
|
|
|
SongUtil::SortSongPointerArrayByArtist( arraySongs );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_GENRE:
|
|
|
|
|
SongUtil::SortSongPointerArrayByGenre( arraySongs );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_EASY_METER:
|
|
|
|
|
SongUtil::SortSongPointerArrayByMeter( arraySongs, DIFFICULTY_EASY );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_MEDIUM_METER:
|
|
|
|
|
SongUtil::SortSongPointerArrayByMeter( arraySongs, DIFFICULTY_MEDIUM );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_HARD_METER:
|
|
|
|
|
SongUtil::SortSongPointerArrayByMeter( arraySongs, DIFFICULTY_HARD );
|
|
|
|
|
break;
|
|
|
|
|
case SORT_CHALLENGE_METER:
|
|
|
|
|
SongUtil::SortSongPointerArrayByMeter( arraySongs, DIFFICULTY_CHALLENGE );
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0); // unhandled SortOrder
|
|
|
|
|
}
|
2002-02-09 04:30:27 +00:00
|
|
|
|
2002-04-16 17:31:00 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
///////////////////////////////////
|
|
|
|
|
// Build an array of WheelItemDatas from the sorted list of Song*'s
|
|
|
|
|
///////////////////////////////////
|
|
|
|
|
arrayWheelItemDatas.clear(); // clear out the previous wheel items
|
|
|
|
|
arrayWheelItemDatas.reserve( arraySongs.size() );
|
2002-06-30 23:19:33 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
switch( PREFSMAN->m_MusicWheelUsesSections )
|
|
|
|
|
{
|
|
|
|
|
case PrefsManager::NEVER:
|
2005-03-02 06:09:00 +00:00
|
|
|
bUseSections = false;
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
|
|
|
|
case PrefsManager::ABC_ONLY:
|
|
|
|
|
if( so != SORT_TITLE && so != SORT_GROUP )
|
|
|
|
|
bUseSections = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
if( bUseSections )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
// Sorting twice isn't necessary. Instead, modify the compatator functions
|
|
|
|
|
// in Song.cpp to have the desired effect. -Chris
|
|
|
|
|
/* Keeping groups together with the sorts is tricky and brittle; we
|
2005-09-03 04:16:48 +00:00
|
|
|
* keep getting OTHER split up without this. However, it puts the
|
|
|
|
|
* Grade and BPM sorts in the wrong order, and they're already correct,
|
|
|
|
|
* so don't re-sort for them. */
|
|
|
|
|
/* We're using sections, so use the section name as the top-level sort. */
|
2005-06-03 01:57:10 +00:00
|
|
|
if( so != SORT_TOP_GRADES && so != SORT_BPM )
|
|
|
|
|
SongUtil::SortSongPointerArrayBySectionName(arraySongs, so);
|
2005-12-09 20:05:04 +00:00
|
|
|
}
|
2005-06-03 01:57:10 +00:00
|
|
|
|
2005-12-09 20:05:04 +00:00
|
|
|
// make WheelItemDatas with sections
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sLastSection = "";
|
2005-12-09 20:05:04 +00:00
|
|
|
int iSectionColorIndex = 0;
|
|
|
|
|
for( unsigned i=0; i< arraySongs.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
Song* pSong = arraySongs[i];
|
|
|
|
|
if( bUseSections )
|
2002-06-14 22:25:22 +00:00
|
|
|
{
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sThisSection = SongUtil::GetSectionNameFromSongAndSort( pSong, so );
|
2005-06-03 01:57:10 +00:00
|
|
|
|
2005-09-03 04:16:48 +00:00
|
|
|
if( sThisSection != sLastSection )
|
2005-06-03 01:57:10 +00:00
|
|
|
{
|
2005-09-03 04:16:48 +00:00
|
|
|
// new section, make a section item
|
2005-06-03 01:57:10 +00:00
|
|
|
RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex);
|
|
|
|
|
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_SECTION, NULL, sThisSection, NULL, colorSection) );
|
2005-06-03 01:57:10 +00:00
|
|
|
sLastSection = sThisSection;
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_SONG, pSong, sLastSection, NULL, SONGMAN->GetSongColor(pSong)) );
|
2003-02-25 00:33:42 +00:00
|
|
|
}
|
2002-10-10 04:11:30 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
if( so != SORT_ROULETTE )
|
|
|
|
|
{
|
|
|
|
|
if( SHOW_ROULETTE )
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_ROULETTE, NULL, "", NULL, RageColor(1,0,0,1)) );
|
2005-06-03 01:57:10 +00:00
|
|
|
/* Only add TYPE_PORTAL if there's at least one song on the list. */
|
|
|
|
|
bool bFoundAnySong = false;
|
|
|
|
|
for( unsigned i=0; !bFoundAnySong && i < arrayWheelItemDatas.size(); i++ )
|
2006-08-10 04:27:46 +00:00
|
|
|
if( arrayWheelItemDatas[i]->m_Type == TYPE_SONG )
|
2005-06-03 01:57:10 +00:00
|
|
|
bFoundAnySong = true;
|
|
|
|
|
|
|
|
|
|
if( SHOW_RANDOM && bFoundAnySong )
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_RANDOM, NULL, "", NULL, RageColor(1,0,0,1)) );
|
2005-06-03 01:57:10 +00:00
|
|
|
|
|
|
|
|
if( SHOW_PORTAL && bFoundAnySong )
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_PORTAL, NULL, "", NULL, RageColor(1,0,0,1)) );
|
2005-06-03 01:57:10 +00:00
|
|
|
}
|
2003-02-25 00:33:42 +00:00
|
|
|
|
2006-08-06 02:37:42 +00:00
|
|
|
if( GAMESTATE->IsAnExtraStage() )
|
2003-07-20 05:13:45 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
Song* pSong;
|
|
|
|
|
Steps* pSteps;
|
2005-09-03 03:52:22 +00:00
|
|
|
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->GetCurrentStyle(), pSong, pSteps, NULL, NULL );
|
2005-06-03 01:57:10 +00:00
|
|
|
|
|
|
|
|
for( unsigned i=0; i<arrayWheelItemDatas.size(); i++ )
|
2002-10-10 04:11:30 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
if( arrayWheelItemDatas[i]->m_pSong == pSong )
|
2005-06-03 01:57:10 +00:00
|
|
|
{
|
|
|
|
|
/* Change the song color. */
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas[i]->m_color = SONG_REAL_EXTRA_COLOR;
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2002-10-10 04:11:30 +00:00
|
|
|
}
|
2003-02-25 00:33:42 +00:00
|
|
|
}
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
2002-10-09 06:57:37 +00:00
|
|
|
}
|
2003-07-20 08:54:31 +00:00
|
|
|
case SORT_ALL_COURSES:
|
|
|
|
|
case SORT_NONSTOP_COURSES:
|
|
|
|
|
case SORT_ONI_COURSES:
|
|
|
|
|
case SORT_ENDLESS_COURSES:
|
2002-04-16 17:31:00 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
vector<Course*> apCourses;
|
|
|
|
|
switch( so )
|
2005-05-16 09:36:32 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
case SORT_NONSTOP_COURSES:
|
2006-05-01 21:49:59 +00:00
|
|
|
SONGMAN->GetPreferredSortCourses( COURSE_TYPE_NONSTOP, apCourses, PREFSMAN->m_bAutogenGroupCourses );
|
2005-06-03 01:57:10 +00:00
|
|
|
break;
|
|
|
|
|
case SORT_ONI_COURSES:
|
2006-05-01 21:49:59 +00:00
|
|
|
SONGMAN->GetPreferredSortCourses( COURSE_TYPE_ONI, apCourses, PREFSMAN->m_bAutogenGroupCourses );
|
|
|
|
|
SONGMAN->GetPreferredSortCourses( COURSE_TYPE_SURVIVAL, apCourses, PREFSMAN->m_bAutogenGroupCourses );
|
2005-05-16 09:36:32 +00:00
|
|
|
break;
|
2005-06-03 01:57:10 +00:00
|
|
|
case SORT_ENDLESS_COURSES:
|
2006-05-01 21:49:59 +00:00
|
|
|
SONGMAN->GetPreferredSortCourses( COURSE_TYPE_ENDLESS, apCourses, PREFSMAN->m_bAutogenGroupCourses );
|
2005-05-16 09:36:32 +00:00
|
|
|
break;
|
2005-06-03 01:57:10 +00:00
|
|
|
case SORT_ALL_COURSES:
|
|
|
|
|
SONGMAN->GetAllCourses( apCourses, PREFSMAN->m_bAutogenGroupCourses );
|
2005-05-16 09:36:32 +00:00
|
|
|
break;
|
2005-06-03 01:57:10 +00:00
|
|
|
default: ASSERT(0); break;
|
2005-05-16 09:36:32 +00:00
|
|
|
}
|
2003-08-12 23:18:19 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
if( PREFSMAN->m_CourseSortOrder == PrefsManager::COURSE_SORT_SONGS )
|
|
|
|
|
{
|
|
|
|
|
CourseUtil::SortCoursePointerArrayByDifficulty( apCourses );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch( PREFSMAN->m_CourseSortOrder )
|
|
|
|
|
{
|
2006-05-16 10:06:04 +00:00
|
|
|
case PrefsManager::COURSE_SORT_PREFERRED:
|
2006-05-01 21:49:59 +00:00
|
|
|
break;
|
2005-06-03 01:57:10 +00:00
|
|
|
case PrefsManager::COURSE_SORT_METER:
|
|
|
|
|
CourseUtil::SortCoursePointerArrayByAvgDifficulty( apCourses );
|
|
|
|
|
break;
|
|
|
|
|
case PrefsManager::COURSE_SORT_METER_SUM:
|
|
|
|
|
CourseUtil::SortCoursePointerArrayByTotalDifficulty( apCourses );
|
|
|
|
|
break;
|
|
|
|
|
case PrefsManager::COURSE_SORT_RANK:
|
|
|
|
|
CourseUtil::SortCoursePointerArrayByRanking( apCourses );
|
|
|
|
|
break;
|
|
|
|
|
default: ASSERT(0);
|
|
|
|
|
}
|
2003-07-20 08:54:31 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
// since we can't agree, make it an option
|
2006-04-06 09:39:29 +00:00
|
|
|
if( g_bMoveRandomToEnd )
|
2005-06-03 01:57:10 +00:00
|
|
|
CourseUtil::MoveRandomToEnd( apCourses );
|
|
|
|
|
}
|
2003-07-20 08:54:31 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
if( so == SORT_ALL_COURSES )
|
|
|
|
|
CourseUtil::SortCoursePointerArrayByType( apCourses );
|
2002-08-01 20:30:40 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
arrayWheelItemDatas.clear(); // clear out the previous wheel items
|
2003-07-10 11:24:16 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sLastSection = "";
|
2005-06-03 01:57:10 +00:00
|
|
|
int iSectionColorIndex = 0;
|
2005-06-08 01:45:21 +00:00
|
|
|
for( unsigned i=0; i<apCourses.size(); i++ ) // foreach course
|
2003-07-20 08:54:31 +00:00
|
|
|
{
|
2005-06-08 01:45:21 +00:00
|
|
|
Course* pCourse = apCourses[i];
|
2005-06-03 01:57:10 +00:00
|
|
|
|
|
|
|
|
// if unlocks are on, make sure it is unlocked
|
|
|
|
|
if ( UNLOCKMAN->CourseIsLocked(pCourse) )
|
|
|
|
|
continue;
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sThisSection = "";
|
2005-06-03 01:57:10 +00:00
|
|
|
if( so == SORT_ALL_COURSES )
|
2004-10-07 22:16:04 +00:00
|
|
|
{
|
2005-06-03 01:57:10 +00:00
|
|
|
switch( pCourse->GetPlayMode() )
|
|
|
|
|
{
|
2006-05-01 21:49:59 +00:00
|
|
|
case PLAY_MODE_ONI: sThisSection = "Oni"; break;
|
2005-06-03 01:57:10 +00:00
|
|
|
case PLAY_MODE_NONSTOP: sThisSection = "Nonstop"; break;
|
|
|
|
|
case PLAY_MODE_ENDLESS: sThisSection = "Endless"; break;
|
|
|
|
|
}
|
2004-10-07 22:16:04 +00:00
|
|
|
}
|
2003-07-20 08:54:31 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
// check that this course has at least one song playable in the current style
|
|
|
|
|
if( !pCourse->IsPlayableIn(GAMESTATE->GetCurrentStyle()->m_StepsType) )
|
|
|
|
|
continue;
|
2003-07-20 08:54:31 +00:00
|
|
|
|
2005-06-03 01:57:10 +00:00
|
|
|
if( sThisSection != sLastSection ) // new section, make a section item
|
|
|
|
|
{
|
|
|
|
|
RageColor c = SECTION_COLORS.GetValue(iSectionColorIndex);
|
|
|
|
|
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_SECTION, NULL, sThisSection, NULL, c) );
|
2005-06-03 01:57:10 +00:00
|
|
|
sLastSection = sThisSection;
|
|
|
|
|
}
|
2003-07-20 08:54:31 +00:00
|
|
|
|
2006-05-01 21:49:59 +00:00
|
|
|
RageColor c = ( pCourse->m_sGroupName.size() == 0 ) ? pCourse->GetColor() : SONGMAN->GetCourseColor(pCourse);
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_COURSE, NULL, sThisSection, pCourse, c) );
|
2005-06-03 01:57:10 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2002-07-29 03:06:55 +00:00
|
|
|
}
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-10 05:30:12 +00:00
|
|
|
// init music status icons
|
2004-09-21 07:53:39 +00:00
|
|
|
for( unsigned i=0; i<arrayWheelItemDatas.size(); i++ )
|
2002-02-10 06:25:12 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelItemData& WID = *arrayWheelItemDatas[i];
|
2006-06-14 04:12:20 +00:00
|
|
|
if( WID.m_pSong != NULL )
|
|
|
|
|
{
|
|
|
|
|
WID.m_Flags.bHasBeginnerOr1Meter = WID.m_pSong->IsEasy( GAMESTATE->GetCurrentStyle()->m_StepsType );
|
|
|
|
|
WID.m_Flags.bEdits = WID.m_pSong->HasEdits( GAMESTATE->GetCurrentStyle()->m_StepsType );
|
|
|
|
|
WID.m_Flags.iStagesForSong = SongManager::GetNumStagesForSong( WID.m_pSong );
|
|
|
|
|
}
|
|
|
|
|
else if( WID.m_pCourse != NULL )
|
|
|
|
|
{
|
|
|
|
|
WID.m_Flags.bHasBeginnerOr1Meter = false;
|
|
|
|
|
WID.m_Flags.bEdits = WID.m_pCourse->IsAnEdit();
|
|
|
|
|
WID.m_Flags.iStagesForSong = 1;
|
|
|
|
|
}
|
2002-02-10 06:25:12 +00:00
|
|
|
}
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2003-02-10 05:30:12 +00:00
|
|
|
// init crowns
|
2005-04-15 07:18:40 +00:00
|
|
|
if( so == SORT_POPULARITY )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
|
|
|
|
// init crown icons
|
2004-09-21 07:53:39 +00:00
|
|
|
for( unsigned i=0; i< min(3u,arrayWheelItemDatas.size()); i++ )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelItemData& WID = *arrayWheelItemDatas[i];
|
2003-02-10 05:30:12 +00:00
|
|
|
WID.m_Flags.iPlayersBestNumber = i+1;
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-31 02:46:42 +00:00
|
|
|
if( arrayWheelItemDatas.empty() )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
arrayWheelItemDatas.push_back( new WheelItemData(TYPE_SECTION, NULL, "- EMPTY -", NULL, RageColor(1,0,0,1)) );
|
2005-03-13 17:40:00 +00:00
|
|
|
}
|
2002-02-09 04:30:27 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-03 08:22:02 +00:00
|
|
|
void MusicWheel::NotesOrTrailChanged( PlayerNumber pn ) // update grade graphics and top score
|
2002-04-28 20:42:32 +00:00
|
|
|
{
|
2003-03-26 19:15:38 +00:00
|
|
|
for( int i=0; i<NUM_WHEEL_ITEMS; i++ )
|
2002-04-28 20:42:32 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
MusicWheelItem *display = (MusicWheelItem *) m_WheelBaseItems[i]; // XXX: ugly cast
|
2005-01-08 08:34:31 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
display->RefreshGrades();
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
2005-04-30 17:30:18 +00:00
|
|
|
}
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
void MusicWheel::UpdateSwitch()
|
|
|
|
|
{
|
|
|
|
|
switch( m_WheelState )
|
|
|
|
|
{
|
|
|
|
|
case STATE_FLYING_OFF_BEFORE_NEXT_SORT:
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
const Song* pPrevSelectedSong = GetCurWheelItemData(m_iSelection)->m_pSong;
|
2002-08-28 22:42:40 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_SortOrderChanged, 0 );
|
|
|
|
|
|
2005-10-30 20:09:32 +00:00
|
|
|
SetOpenGroup( SongUtil::GetSectionNameFromSongAndSort(pPrevSelectedSong, GAMESTATE->m_SortOrder) );
|
2004-02-06 04:01:08 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
m_iSelection = 0;
|
2005-04-10 04:45:25 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
//
|
|
|
|
|
// Select the previously selected item
|
|
|
|
|
//
|
|
|
|
|
switch( GAMESTATE->m_SortOrder )
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
// Look for the last selected song or course
|
|
|
|
|
SelectSongOrCourse();
|
|
|
|
|
break;
|
|
|
|
|
case SORT_MODE_MENU:
|
|
|
|
|
SelectModeMenuItem();
|
|
|
|
|
break;
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
2003-01-03 03:24:00 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
//
|
|
|
|
|
// Change difficulty for sorts by meter - XXX: do this with GameCommand?
|
|
|
|
|
//
|
|
|
|
|
Difficulty dc = DIFFICULTY_INVALID;
|
|
|
|
|
switch( GAMESTATE->m_SortOrder )
|
2002-07-31 04:06:34 +00:00
|
|
|
{
|
2005-06-12 23:43:39 +00:00
|
|
|
case SORT_EASY_METER: dc = DIFFICULTY_EASY; break;
|
|
|
|
|
case SORT_MEDIUM_METER: dc = DIFFICULTY_MEDIUM; break;
|
|
|
|
|
case SORT_HARD_METER: dc = DIFFICULTY_HARD; break;
|
|
|
|
|
case SORT_CHALLENGE_METER: dc = DIFFICULTY_CHALLENGE; break;
|
2002-07-31 04:06:34 +00:00
|
|
|
}
|
2005-06-12 23:43:39 +00:00
|
|
|
if( dc != DIFFICULTY_INVALID )
|
2002-07-31 04:06:34 +00:00
|
|
|
{
|
2005-06-12 23:43:39 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
if( GAMESTATE->IsPlayerEnabled(p) )
|
|
|
|
|
GAMESTATE->m_PreferredDifficulty[p].Set( dc );
|
2002-07-31 04:06:34 +00:00
|
|
|
}
|
2005-06-12 23:43:39 +00:00
|
|
|
|
|
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_SongChanged, 0 );
|
2006-08-10 04:27:46 +00:00
|
|
|
RebuildWheelItems();
|
2006-08-10 06:27:47 +00:00
|
|
|
TweenOnScreenForSort();
|
2005-06-12 23:43:39 +00:00
|
|
|
m_WheelState = STATE_FLYING_ON_AFTER_NEXT_SORT;
|
|
|
|
|
|
|
|
|
|
SCREENMAN->ZeroNextUpdate();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STATE_FLYING_ON_AFTER_NEXT_SORT:
|
2005-09-19 09:27:43 +00:00
|
|
|
m_WheelState = STATE_SELECTING; // now, wait for input
|
2005-06-12 23:43:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case STATE_TWEENING_ON_SCREEN:
|
|
|
|
|
m_fTimeLeftInState = 0;
|
|
|
|
|
if( (GAMESTATE->IsExtraStage() && !PREFSMAN->m_bPickExtraStage) || GAMESTATE->IsExtraStage2() )
|
|
|
|
|
{
|
|
|
|
|
m_WheelState = STATE_LOCKED;
|
|
|
|
|
SCREENMAN->PlayStartSound();
|
|
|
|
|
m_fLockedWheelVelocity = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-09-19 09:27:43 +00:00
|
|
|
m_WheelState = STATE_SELECTING;
|
2005-06-12 23:43:39 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case STATE_TWEENING_OFF_SCREEN:
|
|
|
|
|
m_WheelState = STATE_WAITING_OFF_SCREEN;
|
|
|
|
|
m_fTimeLeftInState = 0;
|
|
|
|
|
break;
|
2005-09-19 09:27:43 +00:00
|
|
|
case STATE_SELECTING:
|
2005-06-12 23:43:39 +00:00
|
|
|
m_fTimeLeftInState = 0;
|
|
|
|
|
break;
|
|
|
|
|
case STATE_ROULETTE_SPINNING:
|
|
|
|
|
case STATE_RANDOM_SPINNING:
|
|
|
|
|
break;
|
|
|
|
|
case STATE_WAITING_OFF_SCREEN:
|
|
|
|
|
break;
|
|
|
|
|
case STATE_LOCKED:
|
|
|
|
|
break;
|
|
|
|
|
case STATE_ROULETTE_SLOWING_DOWN:
|
|
|
|
|
if( m_iSwitchesLeftInSpinDown == 0 )
|
|
|
|
|
{
|
|
|
|
|
m_WheelState = STATE_LOCKED;
|
2002-01-16 10:01:32 +00:00
|
|
|
m_fTimeLeftInState = 0;
|
2005-06-12 23:43:39 +00:00
|
|
|
SCREENMAN->PlayStartSound();
|
|
|
|
|
m_fLockedWheelVelocity = 0;
|
2003-01-02 02:59:25 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
/* Send this again so the screen starts sample music. */
|
|
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_SongChanged, 0 );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_iSwitchesLeftInSpinDown--;
|
|
|
|
|
const float SwitchTimes[] = { 0.5f, 1.3f, 0.8f, 0.4f, 0.2f };
|
|
|
|
|
ASSERT(m_iSwitchesLeftInSpinDown >= 0 && m_iSwitchesLeftInSpinDown <= 4);
|
|
|
|
|
m_fTimeLeftInState = SwitchTimes[m_iSwitchesLeftInSpinDown];
|
2002-09-10 02:37:17 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
LOG->Trace( "m_iSwitchesLeftInSpinDown id %d, m_fTimeLeftInState is %f", m_iSwitchesLeftInSpinDown, m_fTimeLeftInState );
|
2002-06-24 22:04:31 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
if( m_iSwitchesLeftInSpinDown < 2 )
|
|
|
|
|
ChangeMusic(randomf(0,1) >= 0.5f? 1:-1);
|
|
|
|
|
else
|
|
|
|
|
ChangeMusic(1);
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
2005-06-12 23:43:39 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0); // all state changes should be handled explicitly
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-19 09:33:05 +00:00
|
|
|
void MusicWheel::ChangeMusic( int iDist )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2005-09-19 09:33:05 +00:00
|
|
|
m_iSelection += iDist;
|
2004-06-02 05:12:45 +00:00
|
|
|
wrap( m_iSelection, m_CurWheelItemData.size() );
|
2002-02-06 05:13:39 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
RebuildWheelItems( iDist );
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2005-09-19 09:33:05 +00:00
|
|
|
m_fPositionOffsetFromSelection += iDist;
|
2002-06-30 23:19:33 +00:00
|
|
|
|
2003-03-25 21:17:29 +00:00
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_SongChanged, 0 );
|
2002-06-24 22:04:31 +00:00
|
|
|
|
2005-09-19 09:33:05 +00:00
|
|
|
/* If we're moving automatically, don't play this; it'll be called in Update. */
|
2003-01-21 07:04:53 +00:00
|
|
|
if(!IsMoving())
|
2003-01-19 00:47:06 +00:00
|
|
|
m_soundChangeMusic.Play();
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-30 17:30:18 +00:00
|
|
|
|
2004-03-12 08:31:40 +00:00
|
|
|
bool MusicWheel::ChangeSort( SortOrder new_so ) // return true if change successful
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2003-07-20 08:54:31 +00:00
|
|
|
ASSERT( new_so < NUM_SORT_ORDERS );
|
2005-04-29 08:18:44 +00:00
|
|
|
if( GAMESTATE->m_SortOrder == new_so )
|
2003-06-19 19:31:46 +00:00
|
|
|
return false;
|
|
|
|
|
|
2005-01-29 20:46:08 +00:00
|
|
|
/* Don't change to SORT_MODE_MENU if it doesn't have at least two choices. */
|
|
|
|
|
if( new_so == SORT_MODE_MENU && m_WheelItemDatas[new_so].size() < 2 )
|
|
|
|
|
return false;
|
2004-03-20 18:19:36 +00:00
|
|
|
|
2002-01-18 22:18:41 +00:00
|
|
|
switch( m_WheelState )
|
|
|
|
|
{
|
2005-09-19 09:27:43 +00:00
|
|
|
case STATE_SELECTING:
|
2002-01-24 08:01:24 +00:00
|
|
|
case STATE_FLYING_ON_AFTER_NEXT_SORT:
|
2002-01-18 22:18:41 +00:00
|
|
|
break; // fall through
|
|
|
|
|
default:
|
2002-08-20 21:00:56 +00:00
|
|
|
return false; // don't continue
|
2002-01-18 22:18:41 +00:00
|
|
|
}
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2003-07-20 08:54:31 +00:00
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_SortOrderChanging, 0 );
|
|
|
|
|
|
2002-04-28 20:42:32 +00:00
|
|
|
m_soundChangeSort.Play();
|
2002-01-16 10:01:32 +00:00
|
|
|
|
2006-08-10 06:27:47 +00:00
|
|
|
TweenOffScreenForSort();
|
2002-05-28 20:01:22 +00:00
|
|
|
|
2005-01-29 20:46:08 +00:00
|
|
|
/* Save the new preference. */
|
|
|
|
|
if( IsSongSort(new_so) )
|
|
|
|
|
GAMESTATE->m_PreferredSortOrder = new_so;
|
2005-08-24 20:42:14 +00:00
|
|
|
GAMESTATE->m_SortOrder.Set( new_so );
|
2004-03-12 08:31:40 +00:00
|
|
|
|
2002-01-18 21:19:05 +00:00
|
|
|
m_WheelState = STATE_FLYING_OFF_BEFORE_NEXT_SORT;
|
2002-08-20 21:00:56 +00:00
|
|
|
return true;
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
2003-06-16 17:28:58 +00:00
|
|
|
|
|
|
|
|
bool MusicWheel::NextSort() // return true if change successful
|
|
|
|
|
{
|
2004-01-11 08:15:44 +00:00
|
|
|
// don't allow NextSort when on the sort menu or mode menu
|
2005-04-29 08:18:44 +00:00
|
|
|
if( GAMESTATE->m_SortOrder == SORT_MODE_MENU )
|
2004-01-11 08:15:44 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// find the index of the current sort
|
2003-06-30 06:53:21 +00:00
|
|
|
int cur = 0;
|
2005-04-29 08:18:44 +00:00
|
|
|
while( cur < int(SONG_SORT_ORDERS.size()) && SONG_SORT_ORDERS[cur] != GAMESTATE->m_SortOrder )
|
2003-06-30 06:53:21 +00:00
|
|
|
++cur;
|
2003-06-16 17:28:58 +00:00
|
|
|
|
2004-01-11 08:15:44 +00:00
|
|
|
// move to the next sort with wrapping
|
|
|
|
|
++cur;
|
2005-03-02 01:48:38 +00:00
|
|
|
wrap( cur, SONG_SORT_ORDERS.size() );
|
2003-06-16 17:28:58 +00:00
|
|
|
|
2004-01-11 08:15:44 +00:00
|
|
|
// apply new sort
|
2005-03-02 01:48:38 +00:00
|
|
|
SortOrder soNew = SONG_SORT_ORDERS[cur];
|
2004-01-11 08:15:44 +00:00
|
|
|
return ChangeSort( soNew );
|
2003-06-16 17:28:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MusicWheel::Select() // return true if this selection ends the screen
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2002-07-31 19:40:40 +00:00
|
|
|
LOG->Trace( "MusicWheel::Select()" );
|
2002-06-24 22:04:31 +00:00
|
|
|
|
2005-04-26 06:15:45 +00:00
|
|
|
switch( m_WheelState )
|
|
|
|
|
{
|
|
|
|
|
case STATE_FLYING_OFF_BEFORE_NEXT_SORT:
|
|
|
|
|
case STATE_ROULETTE_SLOWING_DOWN:
|
2003-01-03 03:24:00 +00:00
|
|
|
return false;
|
2005-04-26 06:15:45 +00:00
|
|
|
}
|
2003-01-03 03:24:00 +00:00
|
|
|
|
2002-06-14 22:25:22 +00:00
|
|
|
if( m_WheelState == STATE_ROULETTE_SPINNING )
|
|
|
|
|
{
|
|
|
|
|
m_WheelState = STATE_ROULETTE_SLOWING_DOWN;
|
2006-06-26 12:14:30 +00:00
|
|
|
m_iSwitchesLeftInSpinDown = ROULETTE_SLOW_DOWN_SWITCHES/2+1 + RandomInt( ROULETTE_SLOW_DOWN_SWITCHES/2 );
|
2002-06-24 22:04:31 +00:00
|
|
|
m_fTimeLeftInState = 0.1f;
|
2002-06-14 22:25:22 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-22 01:30:07 +00:00
|
|
|
|
2003-01-19 00:47:06 +00:00
|
|
|
if( m_WheelState == STATE_RANDOM_SPINNING )
|
|
|
|
|
{
|
|
|
|
|
m_fPositionOffsetFromSelection = max(m_fPositionOffsetFromSelection, 0.3f);
|
|
|
|
|
m_WheelState = STATE_LOCKED;
|
2004-05-01 23:28:53 +00:00
|
|
|
SCREENMAN->PlayStartSound();
|
2003-01-19 00:47:06 +00:00
|
|
|
m_fLockedWheelVelocity = 0;
|
2003-03-25 21:17:29 +00:00
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_SongChanged, 0 );
|
2003-01-19 00:47:06 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-10 06:27:47 +00:00
|
|
|
if( !WheelBase::Select() )
|
|
|
|
|
return false;
|
|
|
|
|
|
2003-03-31 23:06:15 +00:00
|
|
|
switch( m_CurWheelItemData[m_iSelection]->m_Type )
|
2002-01-16 10:01:32 +00:00
|
|
|
{
|
2003-07-09 11:38:50 +00:00
|
|
|
case TYPE_ROULETTE:
|
2002-08-20 21:00:56 +00:00
|
|
|
StartRoulette();
|
2006-08-10 04:27:46 +00:00
|
|
|
break;
|
2003-01-03 03:24:00 +00:00
|
|
|
case TYPE_RANDOM:
|
2003-01-19 00:47:06 +00:00
|
|
|
StartRandom();
|
2006-08-10 04:27:46 +00:00
|
|
|
break;
|
2002-04-16 17:31:00 +00:00
|
|
|
case TYPE_SONG:
|
2003-06-16 17:28:58 +00:00
|
|
|
case TYPE_COURSE:
|
2005-09-03 04:34:04 +00:00
|
|
|
case TYPE_PORTAL:
|
2006-08-10 04:27:46 +00:00
|
|
|
break;
|
2003-06-16 17:28:58 +00:00
|
|
|
case TYPE_SORT:
|
2004-12-27 02:06:38 +00:00
|
|
|
LOG->Trace("New sort order selected: %s - %s",
|
2006-08-10 04:27:46 +00:00
|
|
|
GetCurWheelItemData(m_iSelection)->m_sLabel.c_str(),
|
|
|
|
|
SortOrderToString(GetCurWheelItemData(m_iSelection)->m_Action.m_SortOrder).c_str() );
|
|
|
|
|
GetCurWheelItemData(m_iSelection)->m_Action.ApplyToAllPlayers();
|
2005-01-29 20:46:08 +00:00
|
|
|
ChangeSort( GAMESTATE->m_PreferredSortOrder );
|
2006-08-10 04:27:46 +00:00
|
|
|
m_sLastModeMenuItem = GetCurWheelItemData(m_iSelection)->m_Action.m_sName;
|
|
|
|
|
break;
|
2003-06-16 17:28:58 +00:00
|
|
|
default:
|
2006-08-10 06:27:47 +00:00
|
|
|
break;
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
2006-08-10 04:27:46 +00:00
|
|
|
return true;
|
2002-01-16 10:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
2002-08-20 21:00:56 +00:00
|
|
|
void MusicWheel::StartRoulette()
|
|
|
|
|
{
|
|
|
|
|
m_WheelState = STATE_ROULETTE_SPINNING;
|
2003-01-02 02:59:25 +00:00
|
|
|
m_Moving = 1;
|
|
|
|
|
m_TimeBeforeMovingBegins = 0;
|
|
|
|
|
m_SpinSpeed = 1.0f/ROULETTE_SWITCH_SECONDS;
|
2006-08-10 04:27:46 +00:00
|
|
|
GAMESTATE->m_SortOrder.Set( SORT_ROULETTE );
|
|
|
|
|
SetOpenGroup( "" );
|
2003-01-02 02:59:25 +00:00
|
|
|
}
|
|
|
|
|
|
2003-01-19 00:47:06 +00:00
|
|
|
void MusicWheel::StartRandom()
|
|
|
|
|
{
|
2005-05-09 01:26:30 +00:00
|
|
|
/* If RANDOM_PICKS_LOCKED_SONGS is disabled, pick a song from the active sort and
|
|
|
|
|
* section. If enabled, picking from the section makes it too easy to trick the
|
|
|
|
|
* game into picking a locked song, so pick from SORT_ROULETTE. */
|
|
|
|
|
if( RANDOM_PICKS_LOCKED_SONGS )
|
|
|
|
|
{
|
|
|
|
|
/* Shuffle and use the roulette wheel. */
|
|
|
|
|
RandomGen rnd;
|
|
|
|
|
random_shuffle( m_WheelItemDatas[SORT_ROULETTE].begin(), m_WheelItemDatas[SORT_ROULETTE].end(), rnd );
|
2006-08-10 04:27:46 +00:00
|
|
|
GAMESTATE->m_SortOrder.Set( SORT_ROULETTE );
|
2005-06-12 23:43:39 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
GAMESTATE->m_SortOrder.Set( GAMESTATE->m_PreferredSortOrder );
|
2005-05-09 01:26:30 +00:00
|
|
|
}
|
2006-08-10 04:27:46 +00:00
|
|
|
SetOpenGroup( "" );
|
2003-09-26 08:44:10 +00:00
|
|
|
|
2004-04-26 06:47:03 +00:00
|
|
|
m_Moving = -1;
|
|
|
|
|
m_TimeBeforeMovingBegins = 0;
|
|
|
|
|
m_SpinSpeed = 1.0f/ROULETTE_SWITCH_SECONDS;
|
|
|
|
|
m_SpinSpeed *= 20.0f; /* faster! */
|
|
|
|
|
m_WheelState = STATE_RANDOM_SPINNING;
|
2003-02-12 06:25:51 +00:00
|
|
|
|
2004-10-10 15:06:15 +00:00
|
|
|
SelectSong( GetPreferredSelectionForRandomOrPortal() );
|
2004-06-02 06:02:20 +00:00
|
|
|
|
2004-04-26 06:47:03 +00:00
|
|
|
this->Select();
|
2006-08-10 04:27:46 +00:00
|
|
|
RebuildWheelItems();
|
2004-04-26 06:47:03 +00:00
|
|
|
}
|
2004-03-26 21:36:14 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
void MusicWheel::SetOpenGroup( RString group )
|
2003-01-02 02:59:25 +00:00
|
|
|
{
|
2006-08-10 06:27:47 +00:00
|
|
|
LOG->Trace( "SetOpenGroup %s", group.c_str() );
|
2003-01-02 02:59:25 +00:00
|
|
|
m_sExpandedSectionName = group;
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
const WheelItemData *old = NULL;
|
|
|
|
|
if( !m_CurWheelItemData.empty() )
|
|
|
|
|
old = GetCurWheelItemData(m_iSelection);
|
2003-01-02 02:59:25 +00:00
|
|
|
|
|
|
|
|
m_CurWheelItemData.clear();
|
2006-08-10 04:27:46 +00:00
|
|
|
vector<WheelItemData *> &from = m_WheelItemDatas[GAMESTATE->m_SortOrder];
|
2004-06-10 08:43:53 +00:00
|
|
|
for( unsigned i = 0; i < from.size(); ++i )
|
2003-01-02 02:59:25 +00:00
|
|
|
{
|
2006-08-10 04:27:46 +00:00
|
|
|
WheelItemData &d = *from[i];
|
|
|
|
|
if( (d.m_Type == TYPE_SONG || d.m_Type == TYPE_COURSE) && !d.m_sText.empty() &&
|
2005-04-30 17:30:18 +00:00
|
|
|
d.m_sText != group )
|
2003-01-02 02:59:25 +00:00
|
|
|
continue;
|
2004-06-10 08:43:53 +00:00
|
|
|
|
|
|
|
|
/* Only show tutorial songs in arcade */
|
2004-06-11 06:05:35 +00:00
|
|
|
if( GAMESTATE->m_PlayMode!=PLAY_MODE_REGULAR &&
|
2004-06-10 08:43:53 +00:00
|
|
|
d.m_pSong &&
|
|
|
|
|
d.m_pSong->IsTutorial() )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
m_CurWheelItemData.push_back(&d);
|
2003-01-02 02:59:25 +00:00
|
|
|
}
|
|
|
|
|
|
2003-06-16 17:28:58 +00:00
|
|
|
|
|
|
|
|
//
|
2004-01-11 08:15:44 +00:00
|
|
|
// Try to select the item that was selected before changing groups
|
2003-06-16 17:28:58 +00:00
|
|
|
//
|
2003-01-02 02:59:25 +00:00
|
|
|
m_iSelection = 0;
|
2003-06-16 17:28:58 +00:00
|
|
|
|
2004-06-10 08:43:53 +00:00
|
|
|
for( unsigned i=0; i<m_CurWheelItemData.size(); i++ )
|
2003-01-02 02:59:25 +00:00
|
|
|
{
|
2003-06-16 17:28:58 +00:00
|
|
|
if( m_CurWheelItemData[i] == old )
|
|
|
|
|
{
|
2003-01-02 02:59:25 +00:00
|
|
|
m_iSelection=i;
|
2003-06-16 17:28:58 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2003-01-02 02:59:25 +00:00
|
|
|
}
|
2003-01-03 03:24:00 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
RebuildWheelItems();
|
2002-08-20 21:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
2003-01-02 02:59:25 +00:00
|
|
|
bool MusicWheel::IsRouletting() const
|
2002-08-20 21:00:56 +00:00
|
|
|
{
|
2003-01-03 03:24:00 +00:00
|
|
|
return m_WheelState == STATE_ROULETTE_SPINNING || m_WheelState == STATE_ROULETTE_SLOWING_DOWN ||
|
|
|
|
|
m_WheelState == STATE_RANDOM_SPINNING;
|
2002-08-20 21:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-02 05:12:45 +00:00
|
|
|
Song* MusicWheel::GetSelectedSong()
|
|
|
|
|
{
|
|
|
|
|
switch( m_CurWheelItemData[m_iSelection]->m_Type )
|
|
|
|
|
{
|
|
|
|
|
case TYPE_PORTAL:
|
2004-10-10 15:06:15 +00:00
|
|
|
return GetPreferredSelectionForRandomOrPortal();
|
2004-06-02 05:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
return GetCurWheelItemData(m_iSelection)->m_pSong;
|
2004-06-02 05:12:45 +00:00
|
|
|
}
|
2004-06-02 06:02:20 +00:00
|
|
|
|
2004-10-10 15:06:15 +00:00
|
|
|
/* Find a random song. If possible, find one that has the preferred difficulties of
|
|
|
|
|
* each player. Prefer songs in the active group, if any.
|
|
|
|
|
*
|
|
|
|
|
* Note that if this is called, we *must* find a song. We will only be called if
|
|
|
|
|
* the active sort has at least one song, but there may be no open group. This means
|
|
|
|
|
* that any filters and preferences applied here must be optional. */
|
|
|
|
|
Song *MusicWheel::GetPreferredSelectionForRandomOrPortal()
|
2004-06-02 06:02:20 +00:00
|
|
|
{
|
|
|
|
|
// probe to find a song that has the preferred
|
|
|
|
|
// difficulties of each player
|
|
|
|
|
vector<Difficulty> vDifficultiesToRequire;
|
|
|
|
|
FOREACH_HumanPlayer(p)
|
2004-08-31 08:37:47 +00:00
|
|
|
{
|
|
|
|
|
if( GAMESTATE->m_PreferredDifficulty[p] == DIFFICULTY_INVALID )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
|
|
|
|
// TRICKY: Don't require that edits be present if perferred
|
|
|
|
|
// difficulty is DIFFICULTY_EDIT. Otherwise, players could use this
|
|
|
|
|
// to set up a 100% chance of getting a particular locked song by
|
|
|
|
|
// having a single edit for a locked song.
|
|
|
|
|
if( GAMESTATE->m_PreferredDifficulty[p] == DIFFICULTY_EDIT )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
|
|
|
|
vDifficultiesToRequire.push_back( GAMESTATE->m_PreferredDifficulty[p] );
|
|
|
|
|
}
|
2004-06-02 06:02:20 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sPreferredGroup = m_sExpandedSectionName;
|
2006-08-10 04:27:46 +00:00
|
|
|
vector<WheelItemData *> &wid = m_WheelItemDatas[GAMESTATE->m_SortOrder];
|
2004-10-10 15:06:15 +00:00
|
|
|
|
2004-06-28 07:26:00 +00:00
|
|
|
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
|
2004-06-02 06:02:20 +00:00
|
|
|
|
|
|
|
|
#define NUM_PROBES 1000
|
|
|
|
|
for( int i=0; i<NUM_PROBES; i++ )
|
|
|
|
|
{
|
2004-10-10 15:06:15 +00:00
|
|
|
/* Maintaining difficulties is higher priority than maintaining the current
|
|
|
|
|
* group. */
|
|
|
|
|
if( i == NUM_PROBES/4 )
|
2004-10-12 04:42:45 +00:00
|
|
|
sPreferredGroup = "";
|
2004-06-02 06:02:20 +00:00
|
|
|
if( i == NUM_PROBES/2 )
|
|
|
|
|
vDifficultiesToRequire.clear();
|
|
|
|
|
|
2006-06-26 12:14:30 +00:00
|
|
|
int iSelection = RandomInt( wid.size() );
|
2006-08-10 04:27:46 +00:00
|
|
|
if( wid[iSelection]->m_Type != TYPE_SONG )
|
2004-10-10 15:06:15 +00:00
|
|
|
continue;
|
2004-06-02 06:02:20 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
const Song *pSong = wid[iSelection]->m_pSong;
|
2004-10-10 15:06:15 +00:00
|
|
|
|
2006-08-10 04:27:46 +00:00
|
|
|
if( !sPreferredGroup.empty() && wid[iSelection]->m_sText != sPreferredGroup )
|
2004-10-10 15:06:15 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-11-07 00:19:55 +00:00
|
|
|
// There's an off possibility that somebody might have only one song with only beginner steps.
|
2004-11-07 00:19:01 +00:00
|
|
|
if( i < 900 && pSong->IsTutorial() )
|
2004-10-10 15:06:15 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
FOREACH( Difficulty, vDifficultiesToRequire, d )
|
|
|
|
|
if( !pSong->HasStepsTypeAndDifficulty(st,*d) )
|
2005-04-13 08:13:45 +00:00
|
|
|
goto try_next;
|
2006-08-10 04:27:46 +00:00
|
|
|
return wid[iSelection]->m_pSong;
|
2005-04-13 08:13:45 +00:00
|
|
|
try_next:
|
|
|
|
|
;
|
2004-06-02 06:02:20 +00:00
|
|
|
}
|
2005-04-13 08:13:45 +00:00
|
|
|
LOG->Warn( "Couldn't find any songs" );
|
2006-08-10 04:27:46 +00:00
|
|
|
return wid[0]->m_pSong;
|
2004-06-02 06:02:20 +00:00
|
|
|
}
|
2004-06-07 21:14:03 +00:00
|
|
|
|
2005-06-12 23:43:39 +00:00
|
|
|
void MusicWheel::FinishChangingSorts()
|
|
|
|
|
{
|
|
|
|
|
FinishTweening();
|
2005-09-19 09:27:43 +00:00
|
|
|
m_WheelState = STATE_SELECTING;
|
2005-06-12 23:43:39 +00:00
|
|
|
m_fTimeLeftInState = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-07 21:14:03 +00:00
|
|
|
/*
|
|
|
|
|
* (c) 2001-2004 Chris Danford, Chris Gomez, 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.
|
|
|
|
|
*/
|