Files
itgmania212121/stepmania/src/MusicWheel.cpp
T

1325 lines
35 KiB
C++
Raw Normal View History

2002-01-16 10:01:32 +00:00
#include "stdafx.h"
/*
-----------------------------------------------------------------------------
2002-05-01 19:14:55 +00:00
Class: MusicWheel
2002-01-16 10:01:32 +00:00
2002-05-01 19:14:55 +00:00
Desc: See header.
2002-01-16 10:01:32 +00:00
2002-05-19 01:59:48 +00:00
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
2002-05-01 19:14:55 +00:00
Chris Danford
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"
#include "GameManager.h"
2002-07-23 01:41:40 +00:00
#include "PrefsManager.h"
2003-01-02 07:54:28 +00:00
#include "RageSoundManager.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"
#include <math.h>
#include "ThemeManager.h"
2002-09-03 06:33:08 +00:00
// WheelItem stuff
#define ICON_X THEME->GetMetricF("WheelItemDisplay","IconX")
#define SONG_NAME_X THEME->GetMetricF("WheelItemDisplay","SongNameX")
#define SECTION_NAME_X THEME->GetMetricF("WheelItemDisplay","SectionNameX")
#define SECTION_ZOOM THEME->GetMetricF("WheelItemDisplay","SectionZoom")
#define ROULETTE_X THEME->GetMetricF("WheelItemDisplay","RouletteX")
#define ROULETTE_ZOOM THEME->GetMetricF("WheelItemDisplay","RouletteZoom")
#define COURSE_X THEME->GetMetricF("WheelItemDisplay","CourseX")
#define COURSE_ZOOM THEME->GetMetricF("WheelItemDisplay","CourseZoom")
2002-09-03 06:33:08 +00:00
#define GRADE_X( p ) THEME->GetMetricF("WheelItemDisplay",ssprintf("GradeP%dX",p+1))
#define DEFAULT_SCROLL_DIRECTION THEME->GetMetricI("Notes","DefaultScrollDirection")
// MusicWheel stuff
#define FADE_SECONDS THEME->GetMetricF("MusicWheel","FadeSeconds")
#define SWITCH_SECONDS THEME->GetMetricF("MusicWheel","SwitchSeconds")
#define ROULETTE_SWITCH_SECONDS THEME->GetMetricF("MusicWheel","RouletteSwitchSeconds")
2003-01-02 02:59:25 +00:00
#define FAST_SPIN_SWITCH_SECONDS 0.05 // THEME->GetMetricF("MusicWheel","RouletteSwitchSeconds")
#define ROULETTE_SLOW_DOWN_SWITCHES THEME->GetMetricI("MusicWheel","RouletteSlowDownSwitches")
#define LOCKED_INITIAL_VELOCITY THEME->GetMetricF("MusicWheel","LockedInitialVelocity")
#define SCROLL_BAR_X THEME->GetMetricF("MusicWheel","ScrollBarX")
#define SCROLL_BAR_HEIGHT THEME->GetMetricI("MusicWheel","ScrollBarHeight")
2002-09-03 06:33:08 +00:00
#define ITEM_SPACING_Y THEME->GetMetricF("MusicWheel","ItemSpacingY")
#define NUM_SECTION_COLORS THEME->GetMetricI("MusicWheel","NumSectionColors")
#define SECTION_COLORS( i ) THEME->GetMetricC("MusicWheel",ssprintf("SectionColor%d",i+1))
float g_fItemSpacingY; // cache
inline RageColor GetNextSectionColor() {
2002-05-19 01:59:48 +00:00
static int i=0;
i = i % NUM_SECTION_COLORS;
return SECTION_COLORS(i++);
2002-02-05 05:33:33 +00:00
}
2002-01-16 10:01:32 +00:00
2002-02-05 05:33:33 +00:00
WheelItemData::WheelItemData( WheelItemType wit, Song* pSong, const CString &sSectionName, Course* pCourse, const RageColor color )
2002-01-16 10:01:32 +00:00
{
2002-05-19 01:59:48 +00:00
m_WheelItemType = wit;
2002-02-05 05:33:33 +00:00
m_pSong = pSong;
2002-05-19 01:59:48 +00:00
m_sSectionName = sSectionName;
2002-06-14 22:25:22 +00:00
m_pCourse = pCourse;
2002-05-19 01:59:48 +00:00
m_color = color;
2002-08-20 21:00:56 +00:00
m_IconType = MusicStatusDisplay::none;
}
WheelItemDisplay::WheelItemDisplay()
{
2002-06-30 23:19:33 +00:00
m_fPercentGray = 0;
m_MusicStatusDisplay.SetXY( ICON_X, 0 );
2002-01-16 10:01:32 +00:00
2002-05-19 01:59:48 +00:00
m_TextBanner.SetHorizAlign( align_left );
m_TextBanner.SetXY( SONG_NAME_X, 0 );
2002-04-16 17:31:00 +00:00
m_sprSongBar.Load( THEME->GetPathTo("Graphics","select music song bar") );
2002-04-16 17:31:00 +00:00
m_sprSongBar.SetXY( 0, 0 );
2002-01-16 10:01:32 +00:00
m_sprSectionBar.Load( THEME->GetPathTo("Graphics","select music section bar") );
2002-05-19 01:59:48 +00:00
m_sprSectionBar.SetXY( 0, 0 );
2002-01-16 10:01:32 +00:00
m_textSectionName.LoadFromFont( THEME->GetPathTo("Fonts","musicwheel section") );
2002-01-16 10:01:32 +00:00
m_textSectionName.TurnShadowOff();
2002-03-06 08:25:09 +00:00
m_textSectionName.SetVertAlign( align_middle );
m_textSectionName.SetXY( SECTION_NAME_X, 0 );
m_textSectionName.SetZoom( SECTION_ZOOM );
2002-05-19 01:59:48 +00:00
m_textRoulette.LoadFromFont( THEME->GetPathTo("Fonts","musicwheel roulette") );
2002-05-19 01:59:48 +00:00
m_textRoulette.TurnShadowOff();
m_textRoulette.SetText( "ROULETTE" );
m_textRoulette.TurnRainbowOn();
m_textRoulette.SetZoom( ROULETTE_ZOOM );
m_textRoulette.SetXY( ROULETTE_X, 0 );
2002-04-16 17:31:00 +00:00
for( int p=0; p<NUM_PLAYERS; p++ )
{
2002-08-22 09:31:32 +00:00
m_GradeDisplay[p].Load( THEME->GetPathTo("Graphics","select music small grades 2x8") );
2002-05-01 19:14:55 +00:00
m_GradeDisplay[p].SetZoom( 1.0f );
2002-09-03 06:33:08 +00:00
m_GradeDisplay[p].SetXY( GRADE_X(p), 0 );
2002-04-16 17:31:00 +00:00
}
2002-06-14 22:25:22 +00:00
m_textCourse.LoadFromFont( THEME->GetPathTo("Fonts","musicwheel course") );
2002-06-14 22:25:22 +00:00
m_textCourse.TurnShadowOff();
m_textCourse.SetZoom( COURSE_ZOOM );
2002-06-14 22:25:22 +00:00
m_textCourse.SetHorizAlign( align_left );
m_textCourse.SetXY( COURSE_X, 0 );
2002-02-05 05:33:33 +00:00
}
2002-01-16 10:01:32 +00:00
void WheelItemDisplay::LoadFromWheelItemData( WheelItemData* pWID )
2002-01-16 10:01:32 +00:00
{
ASSERT( pWID != NULL );
// copy all data items
2002-06-14 22:25:22 +00:00
this->m_WheelItemType = pWID->m_WheelItemType;
this->m_sSectionName = pWID->m_sSectionName;
this->m_pCourse = pWID->m_pCourse;
this->m_pSong = pWID->m_pSong;
this->m_color = pWID->m_color;
2002-08-20 21:00:56 +00:00
this->m_IconType = pWID->m_IconType;
// init type specific stuff
switch( pWID->m_WheelItemType )
{
case TYPE_SECTION:
2003-01-02 02:59:25 +00:00
case TYPE_COURSE:
2002-03-06 08:25:09 +00:00
{
2003-01-02 02:59:25 +00:00
CString sDisplayName;
BitmapText *bt;
if(pWID->m_WheelItemType == TYPE_SECTION)
{
sDisplayName = SONGMAN->ShortenGroupName(m_sSectionName);
bt = &m_textSectionName;
}
else
{
sDisplayName = m_pCourse->m_sName;
bt = &m_textCourse;
}
bt->SetZoom( 1 );
bt->SetText( sDisplayName );
bt->SetDiffuse( m_color );
bt->TurnRainbowOff();
2002-06-14 22:25:22 +00:00
2003-01-02 02:59:25 +00:00
float fSourcePixelWidth = (float)bt->GetWidestLineWidthInSourcePixels();
2002-06-14 22:25:22 +00:00
float fMaxTextWidth = 200;
if( fSourcePixelWidth > fMaxTextWidth )
2003-01-02 02:59:25 +00:00
bt->SetZoomX( fMaxTextWidth / fSourcePixelWidth );
2002-04-16 17:31:00 +00:00
}
break;
2002-04-16 17:31:00 +00:00
case TYPE_SONG:
{
2002-05-29 09:47:24 +00:00
m_TextBanner.LoadFromSong( m_pSong );
2003-01-02 02:59:25 +00:00
m_TextBanner.SetDiffuse( m_color );
2002-08-20 21:00:56 +00:00
m_MusicStatusDisplay.SetType( m_IconType );
2002-05-29 09:47:24 +00:00
RefreshGrades();
2002-04-16 17:31:00 +00:00
}
break;
2002-05-19 01:59:48 +00:00
case TYPE_ROULETTE:
2002-06-14 22:25:22 +00:00
break;
default:
2002-02-11 04:46:31 +00:00
ASSERT( false ); // invalid type
}
}
2002-04-28 20:42:32 +00:00
void WheelItemDisplay::RefreshGrades()
{
2002-05-29 09:47:24 +00:00
// Refresh Grades
2002-04-28 20:42:32 +00:00
for( int p=0; p<NUM_PLAYERS; p++ )
{
2002-07-23 01:41:40 +00:00
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) )
2002-05-19 01:59:48 +00:00
{
m_GradeDisplay[p].SetDiffuse( RageColor(1,1,1,0) );
2002-05-19 01:59:48 +00:00
continue;
}
if( m_pSong ) // this is a song display
2002-04-28 20:42:32 +00:00
{
if( m_pSong == GAMESTATE->m_pCurSong )
{
Notes* pNotes = GAMESTATE->m_pCurNotes[p];
2002-10-07 07:16:40 +00:00
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, pNotes ? pNotes->m_TopGrade : GRADE_NO_DATA );
}
else
{
const Difficulty dc = GAMESTATE->m_PreferredDifficulty[p];
const Grade grade = m_pSong->GetGradeForDifficulty( GAMESTATE->GetCurrentStyleDef(), p, dc );
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade );
}
2002-04-28 20:42:32 +00:00
}
2002-05-19 01:59:48 +00:00
else // this is a section display
2002-04-28 20:42:32 +00:00
{
2002-08-22 09:31:32 +00:00
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, GRADE_NO_DATA );
2002-04-28 20:42:32 +00:00
}
}
2002-05-29 09:47:24 +00:00
2002-04-28 20:42:32 +00:00
}
2002-05-29 09:47:24 +00:00
void WheelItemDisplay::Update( float fDeltaTime )
2002-02-05 05:33:33 +00:00
{
2002-05-28 20:01:22 +00:00
Actor::Update( fDeltaTime );
2002-02-05 05:33:33 +00:00
switch( m_WheelItemType )
{
case TYPE_SECTION:
2002-04-16 17:31:00 +00:00
m_sprSectionBar.Update( fDeltaTime );
2002-02-05 05:33:33 +00:00
m_textSectionName.Update( fDeltaTime );
break;
2002-05-19 01:59:48 +00:00
case TYPE_ROULETTE:
m_sprSectionBar.Update( fDeltaTime );
m_textRoulette.Update( fDeltaTime );
break;
2002-04-16 17:31:00 +00:00
case TYPE_SONG:
2002-06-14 22:25:22 +00:00
{
m_sprSongBar.Update( fDeltaTime );
m_MusicStatusDisplay.Update( fDeltaTime );
m_TextBanner.Update( fDeltaTime );
for( int p=0; p<NUM_PLAYERS; p++ )
m_GradeDisplay[p].Update( fDeltaTime );
}
break;
case TYPE_COURSE:
2002-04-16 17:31:00 +00:00
m_sprSongBar.Update( fDeltaTime );
2002-06-14 22:25:22 +00:00
m_textCourse.Update( fDeltaTime );
2002-02-05 05:33:33 +00:00
break;
2002-06-14 22:25:22 +00:00
default:
ASSERT(0);
2002-02-05 05:33:33 +00:00
}
}
2002-05-19 01:59:48 +00:00
void WheelItemDisplay::DrawPrimitives()
2002-02-05 05:33:33 +00:00
{
switch( m_WheelItemType )
{
case TYPE_SECTION:
2002-04-16 17:31:00 +00:00
m_sprSectionBar.Draw();
2002-08-20 21:00:56 +00:00
m_textSectionName.Draw();
2002-02-05 05:33:33 +00:00
break;
2002-05-19 01:59:48 +00:00
case TYPE_ROULETTE:
m_sprSectionBar.Draw();
2002-08-20 21:00:56 +00:00
m_textRoulette.Draw();
2002-08-19 20:02:30 +00:00
break;
case TYPE_SONG:
m_sprSongBar.Draw();
m_TextBanner.Draw();
m_MusicStatusDisplay.Draw();
int p;
for( p=0; p<NUM_PLAYERS; p++ )
m_GradeDisplay[p].Draw();
if( m_fPercentGray > 0 )
2002-06-14 22:25:22 +00:00
{
m_sprSongBar.SetGlow( RageColor(0,0,0,m_fPercentGray) );
m_sprSongBar.SetDiffuse( RageColor(0,0,0,0) );
2002-06-14 22:25:22 +00:00
m_sprSongBar.Draw();
m_sprSongBar.SetDiffuse( RageColor(0,0,0,1) );
m_sprSongBar.SetGlow( RageColor(0,0,0,0) );
2002-06-14 22:25:22 +00:00
}
break;
case TYPE_COURSE:
2002-08-20 21:00:56 +00:00
m_sprSongBar.Draw();
m_textCourse.Draw();
2002-02-05 05:33:33 +00:00
break;
2002-06-14 22:25:22 +00:00
default:
ASSERT(0);
2002-02-05 05:33:33 +00:00
}
2002-08-19 20:02:30 +00:00
}
2002-01-16 10:01:32 +00:00
MusicWheel::MusicWheel()
{
LOG->Trace( "MusicWheel::MusicWheel()" );
2002-01-16 10:01:32 +00:00
2002-09-03 06:33:08 +00:00
if(DEFAULT_SCROLL_DIRECTION && GAMESTATE->m_pCurSong == NULL) /* check the song is null... incase they have just come back from a song and changed their PlayerOptions */
{
for(int i=0; i<NUM_PLAYERS; i++)
GAMESTATE->m_PlayerOptions[i].m_bReverseScroll = true;
}
2002-09-03 06:33:08 +00:00
// update theme metric cache
g_fItemSpacingY = ITEM_SPACING_Y;
2002-05-28 20:01:22 +00:00
// for debugging
2002-07-23 01:41:40 +00:00
if( GAMESTATE->m_CurStyle == STYLE_NONE )
GAMESTATE->m_CurStyle = STYLE_DANCE_SINGLE;
2002-05-28 20:01:22 +00:00
m_sprSelectionOverlay.Load( THEME->GetPathTo("Graphics","select music song highlight") );
2002-01-16 10:01:32 +00:00
m_sprSelectionOverlay.SetXY( 0, 0 );
m_sprSelectionOverlay.SetDiffuse( RageColor(1,1,1,1) );
m_sprSelectionOverlay.SetEffectGlowing( 1.0f, RageColor(1,1,1,0.4f), RageColor(1,1,1,1) );
AddChild( &m_sprSelectionOverlay );
2002-05-29 09:47:24 +00:00
m_ScrollBar.SetX( SCROLL_BAR_X );
m_ScrollBar.SetBarHeight( SCROLL_BAR_HEIGHT );
this->AddChild( &m_ScrollBar );
2002-05-01 19:14:55 +00:00
2003-01-02 22:10:51 +00:00
m_soundChangeMusic.Load( THEME->GetPathTo("Sounds","select music change music") );
m_soundChangeSort.Load( THEME->GetPathTo("Sounds","select music change sort") );
m_soundExpand.Load( THEME->GetPathTo("Sounds","select music section expand") );
m_soundStart.Load( THEME->GetPathTo("Sounds","menu start") );
m_soundLocked.Load( THEME->GetPathTo("Sounds","select music wheel locked") );
2002-06-24 22:04:31 +00:00
2002-01-16 10:01:32 +00:00
// init m_mapGroupNameToBannerColor
CArray<Song*, Song*> arraySongs = SONGMAN->m_pSongs;
2002-01-16 10:01:32 +00:00
SortSongPointerArrayByGroup( arraySongs );
m_iSelection = 0;
2002-06-24 22:04:31 +00:00
m_WheelState = STATE_SELECTING_MUSIC;
m_fTimeLeftInState = 0;
m_fPositionOffsetFromSelection = 0;
2002-01-16 10:01:32 +00:00
2002-06-24 22:04:31 +00:00
m_iSwitchesLeftInSpinDown = 0;
2003-01-02 02:59:25 +00:00
2002-08-01 13:42:56 +00:00
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
{
2002-08-01 13:42:56 +00:00
// make the preferred group the group of the last song played.
if( GAMESTATE->m_sPreferredGroup == "ALL MUSIC" )
GAMESTATE->m_sPreferredGroup = GAMESTATE->m_pCurSong->m_sGroupName;
Song* pSong;
Notes* pNotes;
PlayerOptions po;
SongOptions so;
SONGMAN->GetExtraStageInfo(
GAMESTATE->IsExtraStage2(),
GAMESTATE->m_sPreferredGroup,
GAMESTATE->GetCurrentStyleDef(),
2002-08-01 13:42:56 +00:00
pSong,
pNotes,
po,
so );
GAMESTATE->m_pCurSong = pSong;
for( int p=0; p<NUM_PLAYERS; p++ )
{
2002-08-01 13:42:56 +00:00
if( GAMESTATE->IsPlayerEnabled(p) )
{
2002-08-01 13:42:56 +00:00
GAMESTATE->m_pCurNotes[p] = pNotes;
GAMESTATE->m_PlayerOptions[p] = po;
}
}
2002-08-01 13:42:56 +00:00
GAMESTATE->m_SongOptions = so;
}
2002-08-30 21:51:40 +00:00
/* Build all of the wheel item data. Do tihs after selecting
* the extra stage, so it knows to always display it. */
for( int so=0; so<NUM_SORT_ORDERS; so++ )
BuildWheelItemDatas( m_WheelItemDatas[so], SongSortOrder(so) );
2002-08-01 13:42:56 +00:00
// If there is no currently selected song, select one.
if( GAMESTATE->m_pCurSong == NULL )
2002-02-24 01:43:11 +00:00
{
2002-08-01 13:42:56 +00:00
CStringArray asGroupNames;
SONGMAN->GetGroupNames( asGroupNames );
if( !asGroupNames.empty() )
2002-08-01 13:42:56 +00:00
{
2002-08-30 21:51:40 +00:00
/* XXX: Do groups get added if they're empty?
* This will select songs we can't use; we want the first song
2002-09-06 10:13:46 +00:00
* that's actually visible. Should we select out of wheel data?
2002-08-30 21:51:40 +00:00
* -glenn */
2002-08-01 13:42:56 +00:00
CArray<Song*, Song*> arraySongs;
SONGMAN->GetSongsInGroup( asGroupNames[0], arraySongs );
if( !arraySongs.empty() ) // still nothing selected
2002-08-01 13:42:56 +00:00
GAMESTATE->m_pCurSong = arraySongs[0]; // select the first song
}
2002-02-24 01:43:11 +00:00
}
2002-08-01 05:11:11 +00:00
// Select the the previously selected song (if any)
2003-01-02 02:59:25 +00:00
bool selected = SelectSong(GAMESTATE->m_pCurSong);
// Select the the previously selected course (if any)
if(!selected) selected = SelectCourse(GAMESTATE->m_pCurCourse);
if(!selected) SetOpenGroup("");
// rebuild the WheelItems that appear on screen
RebuildWheelItemDisplays();
}
MusicWheel::~MusicWheel()
{
}
bool MusicWheel::SelectSong( const Song *p )
{
if(p == NULL)
return false;
unsigned i;
vector<WheelItemData> &from = m_WheelItemDatas[GAMESTATE->m_SongSortOrder];
for( i=0; i<from.size(); i++ )
{
2003-01-02 02:59:25 +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
SetOpenGroup(from[i].m_sSectionName);
break;
2002-02-09 18:53:47 +00:00
}
}
2003-01-02 02:59:25 +00:00
if(i == from.size())
return false;
for( i=0; i<m_CurWheelItemData.size(); i++ )
2002-08-01 05:11:11 +00:00
{
2003-01-02 02:59:25 +00:00
if( m_CurWheelItemData[i]->m_pSong == p )
m_iSelection = i; // select it
}
return true;
}
bool MusicWheel::SelectCourse( const Course *p )
{
if(p == NULL)
return false;
unsigned i;
vector<WheelItemData> &from = m_WheelItemDatas[GAMESTATE->m_SongSortOrder];
for( i=0; i<from.size(); i++ )
{
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
SetOpenGroup(from[i].m_sSectionName);
break;
2002-08-01 05:11:11 +00:00
}
}
2003-01-02 02:59:25 +00:00
if(i == from.size())
return false;
2003-01-02 02:59:25 +00:00
for( i=0; i<m_CurWheelItemData.size(); i++ )
{
if( m_CurWheelItemData[i]->m_pCourse == p )
m_iSelection = i; // select it
}
2003-01-02 02:59:25 +00:00
return true;
2002-01-16 10:01:32 +00:00
}
2003-01-02 02:59:25 +00:00
void MusicWheel::BuildWheelItemDatas( vector<WheelItemData> &arrayWheelItemDatas, SongSortOrder so, bool bRoulette )
2002-01-16 10:01:32 +00:00
{
unsigned i;
2002-07-23 01:41:40 +00:00
switch( GAMESTATE->m_PlayMode )
2002-02-09 18:53:47 +00:00
{
2002-06-14 22:25:22 +00:00
case PLAY_MODE_ARCADE:
{
///////////////////////////////////
// Make an array of Song*, then sort them
///////////////////////////////////
CArray<Song*, Song*> arraySongs;
2002-08-30 21:51:40 +00:00
// copy only songs that have at least one Notes for the current GameMode
for( i=0; i<SONGMAN->m_pSongs.size(); i++ )
2002-06-14 22:25:22 +00:00
{
Song* pSong = SONGMAN->m_pSongs[i];
2002-02-09 18:53:47 +00:00
2002-08-30 21:51:40 +00:00
/* If we're on an extra stage, and this song is selected, ignore
* #SELECTABLE. */
if( pSong != GAMESTATE->m_pCurSong ||
(!GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2()) ) {
/* Hide songs that asked to be hidden via #SELECTABLE. */
if( !bRoulette && !pSong->NormallyDisplayed() )
continue;
if( bRoulette && !pSong->RouletteDisplayed() )
continue;
}
2002-08-30 04:28:12 +00:00
2002-06-14 22:25:22 +00:00
CArray<Notes*, Notes*> arraySteps;
pSong->GetNotesThatMatch( GAMESTATE->GetCurrentStyleDef()->m_NotesType, arraySteps );
2002-02-09 18:53:47 +00:00
if( !arraySteps.empty() )
2002-10-31 04:23:39 +00:00
arraySongs.push_back( pSong );
2002-06-14 22:25:22 +00:00
}
2002-02-09 18:53:47 +00:00
2002-07-27 19:29:51 +00:00
// sort the songs
2002-06-14 22:25:22 +00:00
switch( so )
{
case SORT_GROUP:
SortSongPointerArrayByGroup( arraySongs );
break;
case SORT_TITLE:
SortSongPointerArrayByTitle( arraySongs );
break;
case SORT_BPM:
SortSongPointerArrayByBPM( arraySongs );
break;
// case SORT_ARTIST:
// SortSongPointerArrayByArtist( arraySongs );
// break;
case SORT_MOST_PLAYED:
SortSongPointerArrayByMostPlayed( arraySongs );
if( arraySongs.size() > 30 )
2002-10-24 20:16:46 +00:00
arraySongs.erase(arraySongs.begin()+30, arraySongs.end());
2002-06-14 22:25:22 +00:00
break;
default:
2002-08-20 21:00:56 +00:00
ASSERT(0); // unhandled SortOrder
2002-06-14 22:25:22 +00:00
}
2002-01-16 10:01:32 +00:00
2002-06-14 22:25:22 +00:00
///////////////////////////////////
2002-10-24 20:16:46 +00:00
// Build an array of WheelItemDatas from the sorted list of Song*'s
2002-06-14 22:25:22 +00:00
///////////////////////////////////
2002-10-24 20:16:46 +00:00
arrayWheelItemDatas.clear(); // clear out the previous wheel items
2002-04-16 17:31:00 +00:00
2002-09-07 10:15:27 +00:00
bool bUseSections = false;
2002-06-14 22:25:22 +00:00
switch( so )
{
case SORT_MOST_PLAYED: bUseSections = false; break;
case SORT_BPM: bUseSections = false; break;
case SORT_GROUP: bUseSections = GAMESTATE->m_sPreferredGroup == "ALL MUSIC"; break;
2002-06-14 22:25:22 +00:00
case SORT_TITLE: bUseSections = true; break;
default: ASSERT( false );
}
2002-06-30 23:19:33 +00:00
if( bRoulette )
bUseSections = false;
2002-12-30 21:42:14 +00:00
if( !PREFSMAN->m_bMusicWheelUsesSections )
bUseSections = false;
2002-01-16 10:01:32 +00:00
2002-06-14 22:25:22 +00:00
if( bUseSections )
{
// make WheelItemDatas with sections
CString sLastSection = "";
RageColor colorSection;
for( unsigned i=0; i< arraySongs.size(); i++ )
2002-06-14 22:25:22 +00:00
{
Song* pSong = arraySongs[i];
CString sThisSection = GetSectionNameFromSongAndSort( pSong, so );
int iSectionColorIndex = 0;
if( GAMESTATE->m_sPreferredGroup != "ALL MUSIC" && pSong->m_sGroupName != GAMESTATE->m_sPreferredGroup )
continue;
if( sThisSection != sLastSection) // new section, make a section item
2002-06-14 22:25:22 +00:00
{
colorSection = (so==SORT_GROUP) ? SONGMAN->GetGroupColor(pSong->m_sGroupName) : SECTION_COLORS(iSectionColorIndex);
2002-06-14 22:25:22 +00:00
iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS;
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData(TYPE_SECTION, NULL, sThisSection, NULL, colorSection) );
2002-06-14 22:25:22 +00:00
sLastSection = sThisSection;
}
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData( TYPE_SONG, pSong, sThisSection, NULL, SONGMAN->GetSongColor(pSong)) );
2002-06-14 22:25:22 +00:00
}
}
else
2002-01-16 10:01:32 +00:00
{
for( unsigned i=0; i<arraySongs.size(); i++ )
2002-06-14 22:25:22 +00:00
{
2002-07-27 19:29:51 +00:00
Song* pSong = arraySongs[i];
if( GAMESTATE->m_sPreferredGroup != "ALL MUSIC" && pSong->m_sGroupName != GAMESTATE->m_sPreferredGroup )
2002-07-27 19:29:51 +00:00
continue; // skip
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData(TYPE_SONG, pSong, "", NULL, SONGMAN->GetSongColor(pSong)) );
2002-06-14 22:25:22 +00:00
}
2002-01-16 10:01:32 +00:00
}
}
if( !bRoulette )
{
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData(TYPE_ROULETTE, NULL, "", NULL, RageColor(1,0,0,1)) );
}
// HACK: Add extra stage item if it isn't already present on the music wheel
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
{
Song* pSong;
Notes* pNotes;
PlayerOptions po;
SongOptions so;
SONGMAN->GetExtraStageInfo( GAMESTATE->IsExtraStage2(), GAMESTATE->m_pCurSong->m_sGroupName, GAMESTATE->GetCurrentStyleDef(), pSong, pNotes, po, so );
bool bFoundExtraSong = false;
for( unsigned i=0; i<arrayWheelItemDatas.size(); i++ )
{
if( arrayWheelItemDatas[i].m_pSong == pSong )
{
bFoundExtraSong = true;
break;
}
}
if( !bFoundExtraSong )
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData(TYPE_SONG, pSong, "", NULL, GAMESTATE->GetStageColor()) );
}
2002-06-14 22:25:22 +00:00
break;
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
2002-04-16 17:31:00 +00:00
{
unsigned i;
2002-08-02 09:31:06 +00:00
2002-07-27 19:29:51 +00:00
CArray<Course*,Course*> apCourses;
switch( GAMESTATE->m_PlayMode )
2002-04-16 17:31:00 +00:00
{
case PLAY_MODE_ONI:
for( i=0; i<SONGMAN->m_aOniCourses.size(); i++ )
2002-10-31 04:23:39 +00:00
apCourses.push_back( &SONGMAN->m_aOniCourses[i] );
SortCoursePointerArrayByDifficulty( apCourses );
break;
case PLAY_MODE_ENDLESS:
for( i=0; i<SONGMAN->m_aEndlessCourses.size(); i++ )
2002-10-31 04:23:39 +00:00
apCourses.push_back( &SONGMAN->m_aEndlessCourses[i] );
break;
2002-04-16 17:31:00 +00:00
}
2002-07-29 03:06:55 +00:00
for( unsigned c=0; c<apCourses.size(); c++ ) // foreach course
2002-07-29 03:06:55 +00:00
{
Course* pCourse = apCourses[c];
// check that this course has at least one song playable in the current style
CArray<Song*,Song*> apSongs;
CArray<Notes*,Notes*> apNotes;
CStringArray asModifiers;
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, false );
if( !apNotes.empty() )
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData(TYPE_COURSE, NULL, "", pCourse, pCourse->GetColor()) );
2002-07-29 03:06:55 +00:00
}
}
break;
2002-06-14 22:25:22 +00:00
default:
ASSERT(0); // invalid PlayMode
2002-01-16 10:01:32 +00:00
}
2002-02-10 06:25:12 +00:00
// init crowns
for( i=0; i<arrayWheelItemDatas.size(); i++ )
2002-02-10 06:25:12 +00:00
{
Song* pSong = arrayWheelItemDatas[i].m_pSong;
2002-08-20 21:00:56 +00:00
if( pSong == NULL )
continue;
bool bIsEasy = pSong->IsEasy( GAMESTATE->GetCurrentStyleDef()->m_NotesType );
2002-09-06 10:13:46 +00:00
WheelItemData& WID = arrayWheelItemDatas[i];
2002-08-20 21:00:56 +00:00
WID.m_IconType = bIsEasy ? MusicStatusDisplay::easy : MusicStatusDisplay::none;
2002-02-10 06:25:12 +00:00
}
2002-01-16 10:01:32 +00:00
if( so == SORT_MOST_PLAYED )
2002-01-16 10:01:32 +00:00
{
// init crown icons
for( i=0; i< min(3u,arrayWheelItemDatas.size()); i++ )
2002-01-16 10:01:32 +00:00
{
2002-08-20 21:00:56 +00:00
WheelItemData& WID = arrayWheelItemDatas[i];
WID.m_IconType = MusicStatusDisplay::IconType(MusicStatusDisplay::crown1 + i);
2002-01-16 10:01:32 +00:00
}
}
if( arrayWheelItemDatas.empty() )
2002-01-16 10:01:32 +00:00
{
2002-10-31 04:23:39 +00:00
arrayWheelItemDatas.push_back( WheelItemData(TYPE_SECTION, NULL, "- EMPTY -", NULL, RageColor(1,0,0,1)) );
2002-05-19 01:59:48 +00:00
}
2002-01-16 10:01:32 +00:00
}
float MusicWheel::GetBannerY( float fPosOffsetsFromMiddle )
{
2002-09-09 02:59:48 +00:00
return roundf( fPosOffsetsFromMiddle*g_fItemSpacingY );
2002-01-16 10:01:32 +00:00
}
float MusicWheel::GetBannerX( float fPosOffsetsFromMiddle )
{
2002-02-24 01:43:11 +00:00
float fX = (1-cosf((fPosOffsetsFromMiddle)/3))*95.0f;
2002-04-16 17:31:00 +00:00
2002-09-09 02:59:48 +00:00
return roundf( fX );
2002-01-16 10:01:32 +00:00
}
void MusicWheel::RebuildWheelItemDisplays()
2002-01-16 10:01:32 +00:00
{
// rewind to first index that will be displayed;
2002-01-16 10:01:32 +00:00
int iIndex = m_iSelection;
2003-01-02 02:59:25 +00:00
if( m_iSelection > int(m_CurWheelItemData.size()-1) )
2002-02-10 06:25:12 +00:00
m_iSelection = 0;
2002-11-16 08:55:46 +00:00
2003-01-02 02:59:25 +00:00
iIndex -= NUM_WHEEL_ITEMS_TO_DRAW/2;
while(iIndex < 0)
iIndex += m_CurWheelItemData.size();
// iIndex is now the index of the lowest WheelItem to draw
2003-01-02 02:59:25 +00:00
for( int i=0; i<NUM_WHEEL_ITEMS_TO_DRAW; i++ )
{
2003-01-02 02:59:25 +00:00
WheelItemData *data = m_CurWheelItemData[iIndex];
WheelItemDisplay& display = m_WheelItemDisplays[i];
2003-01-02 02:59:25 +00:00
display.LoadFromWheelItemData( data );
// increment iIndex
2003-01-02 02:59:25 +00:00
iIndex++;
if( iIndex > int(m_CurWheelItemData.size()-1) )
iIndex = 0;
2002-01-16 10:01:32 +00:00
}
}
2002-04-28 20:42:32 +00:00
void MusicWheel::NotesChanged( PlayerNumber pn ) // update grade graphics and top score
{
for( int i=0; i<NUM_WHEEL_ITEMS_TO_DRAW; i++ )
{
WheelItemDisplay& display = m_WheelItemDisplays[i];
display.RefreshGrades();
}
}
2002-05-19 01:59:48 +00:00
void MusicWheel::DrawPrimitives()
{
for( int i=0; i<NUM_WHEEL_ITEMS_TO_DRAW; i++ )
2002-01-16 10:01:32 +00:00
{
WheelItemDisplay& display = m_WheelItemDisplays[i];
2002-01-16 10:01:32 +00:00
2002-05-28 20:01:22 +00:00
switch( m_WheelState )
{
2002-06-24 22:04:31 +00:00
case STATE_SELECTING_MUSIC:
case STATE_ROULETTE_SPINNING:
case STATE_ROULETTE_SLOWING_DOWN:
case STATE_LOCKED:
2002-05-28 20:01:22 +00:00
{
float fThisBannerPositionOffsetFromSelection = i - NUM_WHEEL_ITEMS_TO_DRAW/2 + m_fPositionOffsetFromSelection;
2002-05-01 19:14:55 +00:00
2002-05-28 20:01:22 +00:00
float fY = GetBannerY( fThisBannerPositionOffsetFromSelection );
if( fY < -SCREEN_HEIGHT/2 || fY > SCREEN_HEIGHT/2 )
continue; // skip
2002-01-16 10:01:32 +00:00
2002-05-28 20:01:22 +00:00
float fX = GetBannerX( fThisBannerPositionOffsetFromSelection );
display.SetXY( fX, fY );
}
break;
2003-01-02 02:59:25 +00:00
}
2002-01-16 10:01:32 +00:00
2002-06-30 23:19:33 +00:00
if( m_WheelState == STATE_LOCKED && i != NUM_WHEEL_ITEMS_TO_DRAW/2 )
display.m_fPercentGray = 0.5f;
else
display.m_fPercentGray = 0;
display.Draw();
2002-01-16 10:01:32 +00:00
}
2002-05-19 01:59:48 +00:00
ActorFrame::DrawPrimitives();
2002-01-16 10:01:32 +00:00
}
2003-01-02 02:59:25 +00:00
void MusicWheel::UpdateScrollbar()
{
int total_num_items = m_CurWheelItemData.size();
float item_at=m_iSelection - m_fPositionOffsetFromSelection;
if(NUM_WHEEL_ITEMS_TO_DRAW > total_num_items) {
m_ScrollBar.SetPercentage( 0, 1 );
} else {
float size = float(NUM_WHEEL_ITEMS_TO_DRAW) / total_num_items;
float center = item_at / total_num_items;
size *= 0.5f;
m_ScrollBar.SetPercentage( center - size, center + size );
}
}
2002-01-16 10:01:32 +00:00
void MusicWheel::Update( float fDeltaTime )
{
ActorFrame::Update( fDeltaTime );
unsigned i;
2002-11-16 08:55:46 +00:00
for( i=0; i<int(NUM_WHEEL_ITEMS_TO_DRAW); i++ )
2002-01-16 10:01:32 +00:00
{
WheelItemDisplay& display = m_WheelItemDisplays[i];
display.Update( fDeltaTime );
2002-01-16 10:01:32 +00:00
}
2003-01-02 02:59:25 +00:00
UpdateScrollbar();
2002-01-16 10:01:32 +00:00
2003-01-02 02:59:25 +00:00
if( m_Moving )
2002-06-14 22:25:22 +00:00
{
2003-01-02 02:59:25 +00:00
m_TimeBeforeMovingBegins -= fDeltaTime;
m_TimeBeforeMovingBegins = max(m_TimeBeforeMovingBegins, 0);
if(m_TimeBeforeMovingBegins == 0 && m_WheelState != STATE_LOCKED)
{
// spin as fast as possible
if(m_Moving == 1) NextMusic();
else PrevMusic();
}
2002-06-24 22:04:31 +00:00
}
2002-01-16 10:01:32 +00:00
// update wheel state
m_fTimeLeftInState -= fDeltaTime;
if( m_fTimeLeftInState <= 0 ) // time to go to a new state
{
switch( m_WheelState )
{
case STATE_FLYING_OFF_BEFORE_NEXT_SORT:
2002-01-16 10:01:32 +00:00
{
2002-06-14 22:25:22 +00:00
m_WheelState = STATE_FLYING_ON_AFTER_NEXT_SORT;
m_fTimeLeftInState = FADE_SECONDS;
2002-01-16 10:01:32 +00:00
2003-01-02 02:59:25 +00:00
Song* pPrevSelectedSong = m_CurWheelItemData[m_iSelection]->m_pSong;
CString sPrevSelectedSection = m_CurWheelItemData[m_iSelection]->m_sSectionName;
2002-01-16 10:01:32 +00:00
2002-06-14 22:25:22 +00:00
// change the sort order
GAMESTATE->m_SongSortOrder = SongSortOrder( (GAMESTATE->m_SongSortOrder+1) % NUM_SORT_ORDERS );
2002-08-20 21:00:56 +00:00
SCREENMAN->SendMessageToTopScreen( SM_SortOrderChanged, 0 );
2003-01-02 02:59:25 +00:00
SetOpenGroup(GetSectionNameFromSongAndSort( pPrevSelectedSong, GAMESTATE->m_SongSortOrder ));
2002-06-14 22:25:22 +00:00
//RebuildWheelItems();
2002-01-16 10:01:32 +00:00
2002-06-14 22:25:22 +00:00
m_iSelection = 0;
2002-02-24 01:43:11 +00:00
2002-06-14 22:25:22 +00:00
if( pPrevSelectedSong != NULL ) // the previous selected item was a song
2003-01-02 02:59:25 +00:00
SelectSong(pPrevSelectedSong);
2002-06-14 22:25:22 +00:00
else // the previously selected item was a section
2002-02-24 01:43:11 +00:00
{
2002-06-14 22:25:22 +00:00
// find the previously selected song, and select it
2003-01-02 02:59:25 +00:00
for( i=0; i<m_CurWheelItemData.size(); i++ )
2002-02-24 01:43:11 +00:00
{
2003-01-02 02:59:25 +00:00
if( m_CurWheelItemData[i]->m_sSectionName == sPrevSelectedSection )
2002-06-14 22:25:22 +00:00
{
m_iSelection = i;
break;
}
2002-02-24 01:43:11 +00:00
}
}
2002-08-28 22:42:40 +00:00
// If changed sort to "BEST", put selection on most popular song
if( GAMESTATE->m_SongSortOrder == SORT_MOST_PLAYED )
{
2003-01-02 02:59:25 +00:00
for( i=0; i<m_CurWheelItemData.size(); i++ )
2002-08-28 22:42:40 +00:00
{
2003-01-02 02:59:25 +00:00
if( m_CurWheelItemData[i]->m_pSong != NULL )
2002-08-28 22:42:40 +00:00
{
m_iSelection = i;
break;
}
}
}
SCREENMAN->SendMessageToTopScreen( SM_SongChanged, 0 );
2002-06-14 22:25:22 +00:00
RebuildWheelItemDisplays();
2002-05-28 20:01:22 +00:00
2003-01-02 02:59:25 +00:00
TweenOnScreen(true);
2002-01-16 10:01:32 +00:00
}
break;
case STATE_FLYING_ON_AFTER_NEXT_SORT:
2002-06-24 22:04:31 +00:00
m_WheelState = STATE_SELECTING_MUSIC; // now, wait for input
2002-01-16 10:01:32 +00:00
break;
case STATE_TWEENING_ON_SCREEN:
m_fTimeLeftInState = 0;
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
{
2002-08-01 13:42:56 +00:00
// if ( m_bUseRandomExtra )
// {
2003-01-02 07:45:05 +00:00
// SOUNDMAN->music->StopPlaying();
2002-08-01 13:42:56 +00:00
// m_soundExpand.Play();
// m_WheelState = STATE_ROULETTE_SPINNING;
// m_SortOrder = SORT_GROUP;
// m_MusicSortDisplay.SetDiffuse( RageColor(1,1,1,0) );
2002-08-01 13:42:56 +00:00
// m_MusicSortDisplay.SetEffectNone();
// BuildWheelItemDatas( m_WheelItemDatas[SORT_GROUP], SORT_GROUP, true );
// }
// else
{
m_WheelState = STATE_LOCKED;
m_soundStart.Play();
m_fLockedWheelVelocity = 0;
}
}
else
{
m_WheelState = STATE_SELECTING_MUSIC;
}
break;
case STATE_TWEENING_OFF_SCREEN:
m_WheelState = STATE_WAITING_OFF_SCREEN;
m_fTimeLeftInState = 0;
break;
2002-06-24 22:04:31 +00:00
case STATE_SELECTING_MUSIC:
2002-01-16 10:01:32 +00:00
m_fTimeLeftInState = 0;
break;
2002-06-24 22:04:31 +00:00
case STATE_ROULETTE_SPINNING:
break;
case STATE_WAITING_OFF_SCREEN:
break;
case STATE_LOCKED:
break;
2002-06-14 22:25:22 +00:00
case STATE_ROULETTE_SLOWING_DOWN:
2002-06-24 22:04:31 +00:00
if( m_iSwitchesLeftInSpinDown == 0 )
{
m_WheelState = STATE_LOCKED;
m_fTimeLeftInState = 0;
m_soundStart.Play();
m_fLockedWheelVelocity = 0;
2003-01-02 02:59:25 +00:00
/* Send this again so the screen starts sample music. */
SCREENMAN->SendMessageToTopScreen( SM_SongChanged, 0 );
2002-06-24 22:04:31 +00:00
}
else
{
m_iSwitchesLeftInSpinDown--;
2002-09-10 02:37:17 +00:00
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];
LOG->Trace( "m_iSwitchesLeftInSpinDown id %d, m_fTimeLeftInState is %f", m_iSwitchesLeftInSpinDown, m_fTimeLeftInState );
2002-06-24 22:04:31 +00:00
if( m_iSwitchesLeftInSpinDown < 2 )
randomf(0,1) >= 0.5f ? NextMusic() : PrevMusic();
else
NextMusic();
}
break;
default:
ASSERT(0); // all state changes should be handled explitily
2002-06-14 22:25:22 +00:00
break;
2002-01-16 10:01:32 +00:00
}
}
2002-06-24 22:04:31 +00:00
if( m_WheelState == STATE_LOCKED )
{
m_fPositionOffsetFromSelection = clamp( m_fPositionOffsetFromSelection, -0.3f, +0.3f );
float fSpringForce = - m_fPositionOffsetFromSelection * LOCKED_INITIAL_VELOCITY;
2002-06-24 22:04:31 +00:00
m_fLockedWheelVelocity += fSpringForce;
float fDrag = -m_fLockedWheelVelocity * fDeltaTime*4;
m_fLockedWheelVelocity += fDrag;
m_fPositionOffsetFromSelection += m_fLockedWheelVelocity*fDeltaTime;
if( fabsf(m_fPositionOffsetFromSelection) < 0.01f && fabsf(m_fLockedWheelVelocity) < 0.01f )
{
m_fPositionOffsetFromSelection = 0;
m_fLockedWheelVelocity = 0;
}
}
else
{
2002-06-24 22:04:31 +00:00
// "rotate" wheel toward selected song
float fSpinSpeed;
2003-01-02 02:59:25 +00:00
if( m_Moving && m_TimeBeforeMovingBegins == 0 )
fSpinSpeed = m_SpinSpeed;
2002-06-24 22:04:31 +00:00
else
fSpinSpeed = 0.2f + fabsf(m_fPositionOffsetFromSelection)/SWITCH_SECONDS;
2002-06-24 22:04:31 +00:00
if( m_fPositionOffsetFromSelection > 0 )
2002-06-29 11:59:09 +00:00
{
m_fPositionOffsetFromSelection -= fSpinSpeed*fDeltaTime;
if( m_fPositionOffsetFromSelection < 0 )
m_fPositionOffsetFromSelection = 0;
}
2002-06-24 22:04:31 +00:00
else if( m_fPositionOffsetFromSelection < 0 )
2002-06-29 11:59:09 +00:00
{
m_fPositionOffsetFromSelection += fSpinSpeed*fDeltaTime;
if( m_fPositionOffsetFromSelection > 0 )
m_fPositionOffsetFromSelection = 0;
}
}
2002-01-16 10:01:32 +00:00
}
2003-01-02 02:59:25 +00:00
void MusicWheel::PrevMusic()
2002-01-16 10:01:32 +00:00
{
2002-06-24 22:04:31 +00:00
if( m_WheelState == STATE_LOCKED )
{
m_fLockedWheelVelocity = LOCKED_INITIAL_VELOCITY;
2002-06-24 22:04:31 +00:00
m_soundLocked.Play();
return;
}
if( fabsf(m_fPositionOffsetFromSelection) > 0.5f ) // wheel is busy spinning
return;
2002-01-20 07:51:09 +00:00
switch( m_WheelState )
{
2002-06-24 22:04:31 +00:00
case STATE_SELECTING_MUSIC:
2002-06-14 22:25:22 +00:00
case STATE_ROULETTE_SPINNING:
case STATE_ROULETTE_SLOWING_DOWN:
2002-01-20 07:51:09 +00:00
break; // fall through
default:
return; // don't fall through
}
2002-01-16 10:01:32 +00:00
// decrement m_iSelection
2003-01-02 02:59:25 +00:00
m_iSelection--;
if( m_iSelection < 0 )
m_iSelection = m_CurWheelItemData.size()-1;
RebuildWheelItemDisplays();
2002-01-16 10:01:32 +00:00
m_fPositionOffsetFromSelection -= 1;
2002-04-28 20:42:32 +00:00
m_soundChangeMusic.Play();
2002-06-30 23:19:33 +00:00
2003-01-02 02:59:25 +00:00
SCREENMAN->SendMessageToTopScreen( SM_SongChanged, 0 );
2002-01-16 10:01:32 +00:00
}
2003-01-02 02:59:25 +00:00
void MusicWheel::NextMusic()
2002-01-16 10:01:32 +00:00
{
2002-06-24 22:04:31 +00:00
if( m_WheelState == STATE_LOCKED )
{
m_fLockedWheelVelocity = -LOCKED_INITIAL_VELOCITY;
2002-06-24 22:04:31 +00:00
m_soundLocked.Play();
return;
}
2002-07-11 19:02:26 +00:00
if( fabsf(m_fPositionOffsetFromSelection) > 0.5f ) // wheel is very busy spinning
2002-06-24 22:04:31 +00:00
return;
2002-01-18 22:18:41 +00:00
switch( m_WheelState )
{
2002-06-24 22:04:31 +00:00
case STATE_SELECTING_MUSIC:
2002-06-14 22:25:22 +00:00
case STATE_ROULETTE_SPINNING:
case STATE_ROULETTE_SLOWING_DOWN:
2002-09-06 21:25:07 +00:00
break;
2002-01-18 22:18:41 +00:00
default:
LOG->Trace( "NextMusic() ignored" );
2002-01-18 22:18:41 +00:00
return; // don't continue
}
2002-01-16 10:01:32 +00:00
// increment m_iSelection
2003-01-02 02:59:25 +00:00
m_iSelection++;
if( m_iSelection > int(m_CurWheelItemData.size()-1) )
m_iSelection = 0;
RebuildWheelItemDisplays();
2002-01-16 10:01:32 +00:00
m_fPositionOffsetFromSelection += 1;
2003-01-02 02:59:25 +00:00
2002-04-28 20:42:32 +00:00
m_soundChangeMusic.Play();
2002-06-30 23:19:33 +00:00
2003-01-02 02:59:25 +00:00
SCREENMAN->SendMessageToTopScreen( SM_SongChanged, 0 );
2002-01-16 10:01:32 +00:00
}
2002-08-20 21:00:56 +00:00
bool MusicWheel::PrevSort()
2002-05-19 01:59:48 +00:00
{
2002-08-20 21:00:56 +00:00
return NextSort();
2002-05-19 01:59:48 +00:00
}
2002-08-20 21:00:56 +00:00
bool MusicWheel::NextSort()
2002-01-16 10:01:32 +00:00
{
2002-01-18 22:18:41 +00:00
switch( m_WheelState )
{
2002-06-24 22:04:31 +00:00
case STATE_SELECTING_MUSIC:
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
2002-04-28 20:42:32 +00:00
m_soundChangeSort.Play();
2002-01-16 10:01:32 +00:00
2003-01-02 02:59:25 +00:00
TweenOffScreen(true);
2002-05-28 20:01:22 +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
}
2002-06-14 22:25:22 +00:00
bool MusicWheel::Select() // return true of a playable item was chosen
2002-01-16 10:01:32 +00:00
{
LOG->Trace( "MusicWheel::Select()" );
2002-06-24 22:04:31 +00:00
2002-06-14 22:25:22 +00:00
if( m_WheelState == STATE_ROULETTE_SPINNING )
{
m_WheelState = STATE_ROULETTE_SLOWING_DOWN;
2003-01-02 02:59:25 +00:00
m_Moving = 0;
m_iSwitchesLeftInSpinDown = ROULETTE_SLOW_DOWN_SWITCHES/2+1 + rand()%(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-02 02:59:25 +00:00
switch( m_CurWheelItemData[m_iSelection]->m_WheelItemType )
2002-01-16 10:01:32 +00:00
{
case TYPE_SECTION:
2002-01-16 10:01:32 +00:00
{
2003-01-02 02:59:25 +00:00
CString sThisItemSectionName = m_CurWheelItemData[m_iSelection]->m_sSectionName;
2002-01-16 10:01:32 +00:00
if( m_sExpandedSectionName == sThisItemSectionName ) // already expanded
m_sExpandedSectionName = ""; // collapse it
else // already collapsed
m_sExpandedSectionName = sThisItemSectionName; // expand it
2003-01-02 02:59:25 +00:00
SetOpenGroup(m_sExpandedSectionName);
RebuildWheelItemDisplays();
2002-01-16 10:01:32 +00:00
2002-04-28 20:42:32 +00:00
m_soundExpand.Play();
2002-01-16 10:01:32 +00:00
m_iSelection = 0; // reset in case we can't find the last selected song
// find the section header and select it
2003-01-02 02:59:25 +00:00
for( unsigned i=0; i<m_CurWheelItemData.size(); i++ )
2002-01-16 10:01:32 +00:00
{
2003-01-02 02:59:25 +00:00
if( m_CurWheelItemData[i]->m_WheelItemType == TYPE_SECTION
&& m_CurWheelItemData[i]->m_sSectionName == sThisItemSectionName )
2002-01-16 10:01:32 +00:00
{
m_iSelection = i;
break;
}
}
}
return false;
2002-05-19 01:59:48 +00:00
case TYPE_ROULETTE:
2002-08-20 21:00:56 +00:00
StartRoulette();
2002-05-19 01:59:48 +00:00
return false;
2002-01-16 10:01:32 +00:00
2002-04-16 17:31:00 +00:00
case TYPE_SONG:
2002-01-16 10:01:32 +00:00
default:
return true;
}
}
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;
2002-08-20 21:00:56 +00:00
GAMESTATE->m_SongSortOrder = SORT_GROUP;
BuildWheelItemDatas( m_WheelItemDatas[SORT_GROUP], SORT_GROUP, true );
2003-01-02 02:59:25 +00:00
SetOpenGroup("");
}
void MusicWheel::SetOpenGroup(CString group)
{
m_sExpandedSectionName = group;
WheelItemData *old = NULL;
if(!m_CurWheelItemData.empty())
old = m_CurWheelItemData[m_iSelection];
m_CurWheelItemData.clear();
vector<WheelItemData> &from = m_WheelItemDatas[GAMESTATE->m_SongSortOrder];
unsigned i;
for(i = 0; i < from.size(); ++i)
{
if((from[i].m_WheelItemType == TYPE_SONG ||
from[i].m_WheelItemType == TYPE_COURSE) &&
!from[i].m_sSectionName.empty() &&
from[i].m_sSectionName != group)
continue;
m_CurWheelItemData.push_back(&from[i]);
}
m_iSelection = 0;
for(i = 0; i < m_CurWheelItemData.size(); ++i)
{
if(m_CurWheelItemData[i] == old)
m_iSelection=i;
}
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-02 02:59:25 +00:00
return m_WheelState == STATE_ROULETTE_SPINNING || m_WheelState == STATE_ROULETTE_SLOWING_DOWN;
2002-08-20 21:00:56 +00:00
}
2003-01-02 02:59:25 +00:00
int MusicWheel::IsMoving() const
{
2003-01-02 02:59:25 +00:00
if(!m_Moving) return false;
return m_TimeBeforeMovingBegins == 0;
}
2002-05-28 20:01:22 +00:00
2003-01-02 02:59:25 +00:00
void MusicWheel::TweenOnScreen(bool changing_sort)
{
float factor = 1.0f;
if(changing_sort) factor = 0.25;
2002-05-28 20:01:22 +00:00
2003-01-02 02:59:25 +00:00
m_WheelState = STATE_TWEENING_ON_SCREEN;
float fX = GetBannerX(0), fY = GetBannerY(0);
2002-05-29 09:47:24 +00:00
m_sprSelectionOverlay.SetXY( fX+320, fY );
2003-01-02 02:59:25 +00:00
if(changing_sort) {
m_sprSelectionOverlay.BeginTweening( 0.04f * NUM_WHEEL_ITEMS_TO_DRAW/2 * factor ); // sleep
m_sprSelectionOverlay.BeginTweening( 0.2f * factor, Actor::TWEEN_BIAS_BEGIN );
} else {
m_sprSelectionOverlay.BeginTweening( 0.05f * factor ); // sleep
m_sprSelectionOverlay.BeginTweening( 0.4f * factor, Actor::TWEEN_BIAS_BEGIN );
}
m_sprSelectionOverlay.SetTweenX( fX );
2002-05-29 09:47:24 +00:00
m_ScrollBar.SetX( SCROLL_BAR_X+30 );
2003-01-02 02:59:25 +00:00
if(changing_sort)
m_ScrollBar.BeginTweening( 0.2f * factor ); // sleep
else
m_ScrollBar.BeginTweening( 0.7f * factor ); // sleep
m_ScrollBar.BeginTweening( 0.2f * factor , Actor::TWEEN_BIAS_BEGIN );
m_ScrollBar.SetTweenX( SCROLL_BAR_X );
2002-05-28 20:01:22 +00:00
for( int i=0; i<NUM_WHEEL_ITEMS_TO_DRAW; i++ )
{
WheelItemDisplay& display = m_WheelItemDisplays[i];
float fThisBannerPositionOffsetFromSelection = i - NUM_WHEEL_ITEMS_TO_DRAW/2 + m_fPositionOffsetFromSelection;
float fX = GetBannerX(fThisBannerPositionOffsetFromSelection);
float fY = GetBannerY(fThisBannerPositionOffsetFromSelection);
display.SetXY( fX+320, fY );
2003-01-02 02:59:25 +00:00
display.BeginTweening( 0.04f*i * factor ); // sleep
display.BeginTweening( 0.2f * factor, Actor::TWEEN_BIAS_BEGIN );
2002-05-28 20:01:22 +00:00
display.SetTweenX( fX );
}
2003-01-02 02:59:25 +00:00
m_fTimeLeftInState = TweenTime() + 0.100f;
2002-02-07 02:16:14 +00:00
}
2003-01-02 02:59:25 +00:00
void MusicWheel::TweenOffScreen(bool changing_sort)
{
2003-01-02 02:59:25 +00:00
float factor = 1.0f;
if(changing_sort) factor = 0.25;
2002-05-28 20:01:22 +00:00
2003-01-02 02:59:25 +00:00
m_WheelState = STATE_TWEENING_OFF_SCREEN;
2002-05-28 20:01:22 +00:00
2002-05-29 09:47:24 +00:00
float fX, fY;
fX = GetBannerX(0);
fY = GetBannerY(0);
m_sprSelectionOverlay.SetXY( fX, fY );
2003-01-02 02:59:25 +00:00
if(changing_sort) {
/* When changing sort, tween the overlay with the item in the center;
* having it separate looks messy when we're moving fast. */
m_sprSelectionOverlay.BeginTweening( 0.04f * NUM_WHEEL_ITEMS_TO_DRAW/2 * factor ); // sleep
m_sprSelectionOverlay.BeginTweening( 0.2f * factor, Actor::TWEEN_BIAS_END );
} else {
m_sprSelectionOverlay.BeginTweening( 0 ); // sleep
m_sprSelectionOverlay.BeginTweening( 0.2f * factor, Actor::TWEEN_BIAS_END );
}
m_sprSelectionOverlay.SetTweenX( fX+320 );
2002-05-29 09:47:24 +00:00
m_ScrollBar.BeginTweening( 0 );
2003-01-02 02:59:25 +00:00
m_ScrollBar.BeginTweening( 0.2f * factor, Actor::TWEEN_BIAS_BEGIN );
m_ScrollBar.SetTweenX( SCROLL_BAR_X+30 );
2002-05-28 20:01:22 +00:00
for( int i=0; i<NUM_WHEEL_ITEMS_TO_DRAW; i++ )
{
WheelItemDisplay& display = m_WheelItemDisplays[i];
float fThisBannerPositionOffsetFromSelection = i - NUM_WHEEL_ITEMS_TO_DRAW/2 + m_fPositionOffsetFromSelection;
float fX = GetBannerX(fThisBannerPositionOffsetFromSelection);
float fY = GetBannerY(fThisBannerPositionOffsetFromSelection);
display.SetXY( fX, fY );
2003-01-02 02:59:25 +00:00
display.BeginTweening( 0.04f*i * factor ); // sleep
display.BeginTweening( 0.2f * factor, Actor::TWEEN_BIAS_END );
2002-05-28 20:01:22 +00:00
display.SetTweenX( fX+320 );
}
2003-01-02 02:59:25 +00:00
m_fTimeLeftInState = TweenTime() + 0.100f;
2002-06-24 22:04:31 +00:00
}
2002-12-30 21:57:54 +00:00
CString MusicWheel::GetSectionNameFromSongAndSort( Song* pSong, SongSortOrder so )
{
if( pSong == NULL )
return "";
CString sTemp;
switch( so )
{
case SORT_GROUP:
sTemp = pSong->m_sGroupName;
return sTemp;
// case SORT_ARTIST:
// sTemp = pSong->m_sArtist;
// sTemp.MakeUpper();
// sTemp = (sTemp.GetLength() > 0) ? sTemp.Left(1) : "";
// if( IsAnInt(sTemp) )
// sTemp = "NUM";
// return sTemp;
case SORT_TITLE:
sTemp = pSong->GetSortTitle();
sTemp.MakeUpper();
sTemp = (sTemp.GetLength() > 0) ? sTemp.Left(1) : "";
if( IsAnInt(sTemp) )
sTemp = "NUM";
return sTemp;
case SORT_BPM:
case SORT_MOST_PLAYED:
default:
return "";
}
}
2002-12-30 22:40:34 +00:00
2003-01-02 02:59:25 +00:00
void MusicWheel::Move(int n)
2002-12-30 22:40:34 +00:00
{
2003-01-02 02:59:25 +00:00
if(n == m_Moving)
return;
2002-12-30 22:40:34 +00:00
2003-01-02 02:59:25 +00:00
/* Give us one last chance to move. This will ensure that we're at least
* 0.5f from the selection, so we have a chance to spin down smoothly. */
Update(0);
2002-12-30 22:40:34 +00:00
2003-01-02 02:59:25 +00:00
bool Stopping = (m_Moving != 0 && n == 0 && m_TimeBeforeMovingBegins == 0);
m_TimeBeforeMovingBegins = TIME_BEFORE_SLOW_REPEATS;
m_SpinSpeed = 1.0f/FAST_SPIN_SWITCH_SECONDS;
m_Moving = n;
if(Stopping)
{
/* Make sure the user always gets an SM_SongChanged when
* Moving() is 0, so the final banner, etc. always get set. */
SCREENMAN->SendMessageToTopScreen( SM_SongChanged, 0 );
} else {
if(n == 1)
NextMusic();
else if(n == -1)
PrevMusic();
}
2002-12-30 22:40:34 +00:00
}