2003-09-28 02:59:02 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
|
|
|
|
|
#include "ScreenOptionsMaster.h"
|
|
|
|
|
#include "RageException.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "RageLog.h"
|
|
|
|
|
#include "ThemeManager.h"
|
|
|
|
|
#include "GameState.h"
|
|
|
|
|
#include "ScreenManager.h"
|
|
|
|
|
#include "NoteSkinManager.h"
|
|
|
|
|
#include "Course.h"
|
|
|
|
|
#include "Steps.h"
|
|
|
|
|
#include "StyleDef.h"
|
|
|
|
|
#include "song.h"
|
|
|
|
|
#include "SongManager.h"
|
|
|
|
|
#include "Character.h"
|
2003-09-28 05:04:55 +00:00
|
|
|
#include "PrefsManager.h"
|
2003-09-28 02:59:02 +00:00
|
|
|
#include "ScreenOptionsMasterPrefs.h"
|
2003-09-28 05:19:37 +00:00
|
|
|
#include "RageSounds.h"
|
2003-09-28 07:14:07 +00:00
|
|
|
#include "StepMania.h"
|
2003-10-12 20:34:46 +00:00
|
|
|
#include "RageSoundManager.h"
|
2003-11-10 04:32:12 +00:00
|
|
|
#include "ProfileManager.h"
|
2003-09-28 02:59:02 +00:00
|
|
|
|
2003-09-28 04:07:53 +00:00
|
|
|
#define OPTION_MENU_FLAGS THEME->GetMetric (m_sName,"OptionMenuFlags")
|
2003-09-28 02:59:02 +00:00
|
|
|
#define ROW_LINE(i) THEME->GetMetric (m_sName,ssprintf("Line%i",(i+1)))
|
|
|
|
|
|
2003-09-28 04:13:40 +00:00
|
|
|
#define ENTRY(s) THEME->GetMetric ("ScreenOptionsMaster",s)
|
|
|
|
|
#define ENTRY_MODE(s,i) THEME->GetMetric ("ScreenOptionsMaster",ssprintf("%s,%i",(s).c_str(),(i+1)))
|
|
|
|
|
#define ENTRY_NAME(s,i) THEME->GetMetric ("ScreenOptionsMaster",ssprintf("%sName,%i",(s).c_str(),(i+1)))
|
|
|
|
|
#define ENTRY_DEFAULT(s) THEME->GetMetric ("ScreenOptionsMaster",(s) + "Default")
|
2003-09-28 02:59:02 +00:00
|
|
|
#define NEXT_SCREEN THEME->GetMetric (m_sName,"NextScreen")
|
2003-09-28 04:07:53 +00:00
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
// #define NEXT_SCREEN( play_mode ) THEME->GetMetric (m_sName,"NextScreen"+Capitalize(PlayModeToString(play_mode)))
|
|
|
|
|
#define PREV_SCREEN THEME->GetMetric (m_sName,"PrevScreen")
|
|
|
|
|
// #define PREV_SCREEN( play_mode ) THEME->GetMetric (m_sName,"PrevScreen"+Capitalize(PlayModeToString(play_mode)))
|
|
|
|
|
|
|
|
|
|
/* Add the list named "ListName" to the given row/handler. */
|
|
|
|
|
void ScreenOptionsMaster::SetList( OptionRow &row, OptionRowHandler &hand, CString ListName, CString &TitleOut )
|
|
|
|
|
{
|
|
|
|
|
hand.type = ROW_LIST;
|
|
|
|
|
|
|
|
|
|
TitleOut = ListName;
|
|
|
|
|
if( !ListName.CompareNoCase("noteskins") )
|
|
|
|
|
{
|
|
|
|
|
hand.Default.Init(); /* none */
|
|
|
|
|
row.bOneChoiceForAllPlayers = false;
|
|
|
|
|
|
|
|
|
|
CStringArray arraySkinNames;
|
|
|
|
|
NOTESKIN->GetNoteSkinNames( arraySkinNames );
|
|
|
|
|
for( unsigned skin=0; skin<arraySkinNames.size(); skin++ )
|
|
|
|
|
{
|
|
|
|
|
arraySkinNames[skin].MakeUpper();
|
|
|
|
|
|
|
|
|
|
ModeChoice mc;
|
|
|
|
|
mc.m_sModifiers = arraySkinNames[skin];
|
|
|
|
|
hand.ListEntries.push_back( mc );
|
|
|
|
|
row.choices.push_back( arraySkinNames[skin] );
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hand.Default.Load( -1, ENTRY_DEFAULT(ListName) );
|
|
|
|
|
|
|
|
|
|
/* Parse the basic configuration metric. */
|
|
|
|
|
CStringArray asParts;
|
|
|
|
|
split( ENTRY(ListName), ",", asParts );
|
|
|
|
|
if( asParts.size() < 1 )
|
|
|
|
|
RageException::Throw( "Parse error in ScreenOptionsMasterEntries::ListName%s", ListName.c_str() );
|
|
|
|
|
|
|
|
|
|
row.bOneChoiceForAllPlayers = false;
|
|
|
|
|
const int NumCols = atoi( asParts[0] );
|
|
|
|
|
if( asParts.size() > 1 )
|
|
|
|
|
row.bOneChoiceForAllPlayers = !asParts[1].CompareNoCase("together");
|
|
|
|
|
|
|
|
|
|
for( int col = 0; col < NumCols; ++col )
|
|
|
|
|
{
|
|
|
|
|
ModeChoice mc;
|
|
|
|
|
mc.Load( 0, ENTRY_MODE(ListName, col) );
|
|
|
|
|
|
|
|
|
|
if( !mc.IsPlayable() )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
hand.ListEntries.push_back( mc );
|
|
|
|
|
row.choices.push_back( ENTRY_NAME(ListName, col) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add a list of difficulties/edits to the given row/handler. */
|
|
|
|
|
void ScreenOptionsMaster::SetStep( OptionRow &row, OptionRowHandler &hand )
|
|
|
|
|
{
|
|
|
|
|
hand.type = ROW_STEP;
|
|
|
|
|
row.bOneChoiceForAllPlayers = false;
|
|
|
|
|
|
|
|
|
|
// fill in difficulty names
|
|
|
|
|
if( GAMESTATE->m_bEditing )
|
|
|
|
|
{
|
|
|
|
|
row.choices.push_back( "" );
|
|
|
|
|
}
|
|
|
|
|
else if( GAMESTATE->m_pCurCourse ) // playing a course
|
|
|
|
|
{
|
|
|
|
|
row.bOneChoiceForAllPlayers = true;
|
|
|
|
|
row.choices.push_back( "REGULAR" );
|
|
|
|
|
if( GAMESTATE->m_pCurCourse->HasDifficult( GAMESTATE->GetCurrentStyleDef()->m_StepsType ) )
|
|
|
|
|
row.choices.push_back( "DIFFICULT" );
|
|
|
|
|
}
|
|
|
|
|
else if( GAMESTATE->m_pCurSong ) // playing a song
|
|
|
|
|
{
|
2003-11-29 18:10:43 +00:00
|
|
|
vector<Steps*> vSteps;
|
|
|
|
|
GAMESTATE->m_pCurSong->GetSteps( vSteps, GAMESTATE->GetCurrentStyleDef()->m_StepsType );
|
|
|
|
|
SortNotesArrayByDifficulty( vSteps );
|
|
|
|
|
for( unsigned i=0; i<vSteps.size(); i++ )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
2003-11-29 18:10:43 +00:00
|
|
|
Steps* pSteps = vSteps[i];
|
2003-09-28 02:59:02 +00:00
|
|
|
|
2003-11-29 18:10:43 +00:00
|
|
|
CString s;
|
|
|
|
|
// convert to theme-defined difficulty name
|
|
|
|
|
s = SONGMAN->GetDifficultyThemeName( pSteps->GetDifficulty() );
|
|
|
|
|
s += ssprintf( " (%d)", pSteps->GetMeter() );
|
2003-09-28 02:59:02 +00:00
|
|
|
|
|
|
|
|
row.choices.push_back( s );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row.choices.push_back( "N/A" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Add the given configuration value to the given row/handler. */
|
|
|
|
|
void ScreenOptionsMaster::SetConf( OptionRow &row, OptionRowHandler &hand, CString param, CString &TitleOut )
|
|
|
|
|
{
|
|
|
|
|
/* Configuration values are never per-player. */
|
|
|
|
|
row.bOneChoiceForAllPlayers = true;
|
|
|
|
|
hand.type = ROW_CONFIG;
|
|
|
|
|
|
2003-09-29 02:24:53 +00:00
|
|
|
hand.opt = ConfOption::Find( param );
|
2003-09-28 02:59:02 +00:00
|
|
|
if( hand.opt == NULL )
|
|
|
|
|
RageException::Throw( "Invalid Conf type \"%s\"", param.c_str() );
|
|
|
|
|
|
2003-09-28 05:15:27 +00:00
|
|
|
hand.opt->MakeOptionsList( row.choices );
|
2003-09-28 02:59:02 +00:00
|
|
|
|
|
|
|
|
TitleOut = hand.opt->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add a list of available characters to the given row/handler. */
|
|
|
|
|
void ScreenOptionsMaster::SetCharacter( OptionRow &row, OptionRowHandler &hand )
|
|
|
|
|
{
|
2003-10-01 10:04:23 +00:00
|
|
|
hand.type = ROW_CHARACTER;
|
2003-09-28 02:59:02 +00:00
|
|
|
row.bOneChoiceForAllPlayers = false;
|
|
|
|
|
row.choices.push_back( "OFF" );
|
|
|
|
|
vector<Character*> apCharacters;
|
|
|
|
|
GAMESTATE->GetCharacters( apCharacters );
|
|
|
|
|
for( unsigned i=0; i<apCharacters.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
CString s = apCharacters[i]->m_sName;
|
|
|
|
|
s.MakeUpper();
|
|
|
|
|
row.choices.push_back( s );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-10 04:32:12 +00:00
|
|
|
/* Add a list of available characters to the given row/handler. */
|
|
|
|
|
void ScreenOptionsMaster::SetSaveToProfile( OptionRow &row, OptionRowHandler &hand )
|
|
|
|
|
{
|
|
|
|
|
hand.type = ROW_SAVE_TO_PROFILE;
|
|
|
|
|
row.bOneChoiceForAllPlayers = false;
|
|
|
|
|
row.choices.push_back( "DON'T SAVE" );
|
|
|
|
|
row.choices.push_back( "SAVE TO PROFILE" );
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
ScreenOptionsMaster::ScreenOptionsMaster( CString sClassName ):
|
|
|
|
|
ScreenOptions( sClassName )
|
|
|
|
|
{
|
2003-09-28 04:34:15 +00:00
|
|
|
LOG->Trace("ScreenOptionsMaster::ScreenOptionsMaster(%s)", m_sName.c_str() );
|
2003-09-28 04:07:53 +00:00
|
|
|
|
2003-09-29 06:39:54 +00:00
|
|
|
/* If this file doesn't exist, leave the music alone (eg. ScreenPlayerOptions music sample
|
|
|
|
|
* left over from ScreenSelectMusic). If you really want to play no music, add a redir
|
|
|
|
|
* to _silent. */
|
|
|
|
|
CString MusicPath = THEME->GetPathToS( ssprintf("%s music", m_sName.c_str()), true );
|
|
|
|
|
if( MusicPath != "" )
|
|
|
|
|
SOUND->PlayMusic( MusicPath );
|
2003-09-28 05:19:37 +00:00
|
|
|
|
2003-09-28 04:07:53 +00:00
|
|
|
CStringArray Flags;
|
|
|
|
|
split( OPTION_MENU_FLAGS, ";", Flags, true );
|
|
|
|
|
InputMode im = INPUTMODE_INDIVIDUAL;
|
|
|
|
|
bool Explanations = false;
|
|
|
|
|
int NumRows = -1;
|
|
|
|
|
|
|
|
|
|
unsigned i;
|
|
|
|
|
for( i = 0; i < Flags.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
Flags[i].MakeLower();
|
|
|
|
|
|
|
|
|
|
if( sscanf( Flags[i], "rows,%i", &NumRows ) == 1 )
|
|
|
|
|
continue;
|
|
|
|
|
if( Flags[i] == "together" )
|
|
|
|
|
im = INPUTMODE_TOGETHER;
|
|
|
|
|
if( Flags[i] == "explanations" )
|
|
|
|
|
Explanations = true;
|
|
|
|
|
if( Flags[i] == "forceallplayers" )
|
|
|
|
|
{
|
|
|
|
|
for( int pn=0; pn<NUM_PLAYERS; pn++ )
|
|
|
|
|
GAMESTATE->m_bSideIsJoined[pn] = true;
|
|
|
|
|
GAMESTATE->m_MasterPlayerNumber = PlayerNumber(0);
|
|
|
|
|
}
|
2003-09-29 00:43:25 +00:00
|
|
|
if( Flags[i] == "smnavigation" )
|
2004-01-09 05:50:15 +00:00
|
|
|
SetNavigation( NAV_THREE_KEY_MENU );
|
2003-09-28 04:07:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( NumRows == -1 )
|
|
|
|
|
RageException::Throw( "%s::OptionMenuFlags is missing \"rows\" field", m_sName.c_str() );
|
|
|
|
|
|
|
|
|
|
m_OptionRowAlloc = new OptionRow[NumRows];
|
|
|
|
|
for( i = 0; (int) i < NumRows; ++i )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
|
|
|
|
OptionRow &row = m_OptionRowAlloc[i];
|
|
|
|
|
|
|
|
|
|
CStringArray asParts;
|
|
|
|
|
split( ROW_LINE(i), ";", asParts );
|
|
|
|
|
if( asParts.size() < 1 )
|
|
|
|
|
RageException::Throw( "Parse error in %s::Line%i", m_sName.c_str(), i+1 );
|
|
|
|
|
|
|
|
|
|
OptionRowHandler hand;
|
|
|
|
|
for( unsigned part = 0; part < asParts.size(); ++part)
|
|
|
|
|
{
|
|
|
|
|
CStringArray asBits;
|
|
|
|
|
split( asParts[part], ",", asBits );
|
|
|
|
|
|
|
|
|
|
const CString name = asBits[0];
|
|
|
|
|
const CString param = asBits.size() > 1? asBits[1]: "";
|
|
|
|
|
|
2003-11-08 04:25:33 +00:00
|
|
|
if( !name.CompareNoCase("list") )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
2003-11-07 07:25:52 +00:00
|
|
|
SetList( row, hand, param, row.name );
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
else if( !name.CompareNoCase("steps") )
|
|
|
|
|
{
|
|
|
|
|
SetStep( row, hand );
|
2003-11-07 07:25:52 +00:00
|
|
|
row.name = "Steps";
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
else if( !name.CompareNoCase("conf") )
|
|
|
|
|
{
|
2003-11-07 07:25:52 +00:00
|
|
|
SetConf( row, hand, param, row.name );
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
else if( !name.CompareNoCase("characters") )
|
|
|
|
|
{
|
|
|
|
|
SetCharacter( row, hand );
|
2003-11-07 07:25:52 +00:00
|
|
|
row.name = "Characters";
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
2003-11-10 04:32:12 +00:00
|
|
|
else if( !name.CompareNoCase("SaveToProfile") )
|
|
|
|
|
{
|
|
|
|
|
SetSaveToProfile( row, hand );
|
|
|
|
|
row.name = "Save To\nProfile";
|
|
|
|
|
}
|
2003-09-28 02:59:02 +00:00
|
|
|
else
|
|
|
|
|
RageException::Throw( "Unexpected type '%s' in %s::Line%i", name.c_str(), m_sName.c_str(), i );
|
|
|
|
|
}
|
|
|
|
|
OptionRowHandlers.push_back( hand );
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-28 04:07:53 +00:00
|
|
|
ASSERT( (int) OptionRowHandlers.size() == NumRows );
|
2003-09-28 02:59:02 +00:00
|
|
|
|
2003-11-05 07:46:20 +00:00
|
|
|
Init( im, m_OptionRowAlloc, NumRows );
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScreenOptionsMaster::~ScreenOptionsMaster()
|
|
|
|
|
{
|
2003-09-29 06:56:36 +00:00
|
|
|
delete [] m_OptionRowAlloc;
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
2003-10-03 07:02:05 +00:00
|
|
|
int ScreenOptionsMaster::ImportOption( const OptionRow &row, const OptionRowHandler &hand, int pn, int rowno )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
|
|
|
|
/* Figure out which selection is the default. */
|
|
|
|
|
switch( hand.type )
|
|
|
|
|
{
|
|
|
|
|
case ROW_LIST:
|
|
|
|
|
{
|
2003-09-29 09:00:59 +00:00
|
|
|
int ret = -1;
|
2003-09-28 02:59:02 +00:00
|
|
|
for( unsigned e = 0; e < hand.ListEntries.size(); ++e )
|
|
|
|
|
{
|
|
|
|
|
const ModeChoice &mc = hand.ListEntries[e];
|
2003-09-29 09:00:59 +00:00
|
|
|
|
|
|
|
|
if( mc.IsZero() )
|
|
|
|
|
{
|
|
|
|
|
/* The entry has no effect. This is usually a default "none of the
|
|
|
|
|
* above" entry. It will always return true for DescribesCurrentMode().
|
|
|
|
|
* It's only the selected choice if nothing else matches. */
|
|
|
|
|
ret = e;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
if( row.bOneChoiceForAllPlayers )
|
|
|
|
|
{
|
|
|
|
|
if( mc.DescribesCurrentModeForAllPlayers() )
|
|
|
|
|
return e;
|
|
|
|
|
} else {
|
|
|
|
|
if( mc.DescribesCurrentMode( (PlayerNumber) pn) )
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-09 00:19:51 +00:00
|
|
|
if( ret == -1 )
|
|
|
|
|
{
|
|
|
|
|
LOG->Warn( "%s line %i (\"%s\"): couldn't find default", m_sName.c_str(), rowno, row.name.c_str() );
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-29 09:00:59 +00:00
|
|
|
return ret;
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
case ROW_STEP:
|
|
|
|
|
if( GAMESTATE->m_bEditing )
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if( GAMESTATE->m_pCurCourse ) // playing a course
|
|
|
|
|
{
|
|
|
|
|
if( GAMESTATE->m_bDifficultCourses &&
|
|
|
|
|
GAMESTATE->m_pCurCourse->HasDifficult( GAMESTATE->GetCurrentStyleDef()->m_StepsType ) )
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( GAMESTATE->m_pCurSong ) // playing a song
|
|
|
|
|
{
|
|
|
|
|
vector<Steps*> vNotes;
|
|
|
|
|
GAMESTATE->m_pCurSong->GetSteps( vNotes, GAMESTATE->GetCurrentStyleDef()->m_StepsType );
|
|
|
|
|
SortNotesArrayByDifficulty( vNotes );
|
|
|
|
|
for( unsigned i=0; i<vNotes.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
if( GAMESTATE->m_pCurNotes[pn] == vNotes[i] )
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2003-09-28 04:13:40 +00:00
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
case ROW_CHARACTER:
|
|
|
|
|
{
|
|
|
|
|
vector<Character*> apCharacters;
|
|
|
|
|
GAMESTATE->GetCharacters( apCharacters );
|
|
|
|
|
for( unsigned i=0; i<apCharacters.size(); i++ )
|
|
|
|
|
if( GAMESTATE->m_pCurCharacters[pn] == apCharacters[i] )
|
|
|
|
|
return i+1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ROW_CONFIG:
|
2003-09-28 07:14:07 +00:00
|
|
|
return hand.opt->Get( row.choices );
|
2003-09-28 02:59:02 +00:00
|
|
|
|
2003-11-10 04:32:12 +00:00
|
|
|
case ROW_SAVE_TO_PROFILE:
|
|
|
|
|
return 0;
|
|
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenOptionsMaster::ImportOptions()
|
|
|
|
|
{
|
|
|
|
|
for( unsigned i = 0; i < OptionRowHandlers.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const OptionRowHandler &hand = OptionRowHandlers[i];
|
|
|
|
|
const OptionRow &row = m_OptionRowAlloc[i];
|
|
|
|
|
|
|
|
|
|
if( row.bOneChoiceForAllPlayers )
|
|
|
|
|
{
|
2003-10-03 07:02:05 +00:00
|
|
|
int col = ImportOption( row, hand, 0, i );
|
2003-09-28 02:59:02 +00:00
|
|
|
m_iSelectedOption[0][i] = col;
|
2003-10-01 10:04:23 +00:00
|
|
|
ASSERT( m_iSelectedOption[0][i] < (int)row.choices.size() );
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
for( int pn=0; pn<NUM_PLAYERS; pn++ )
|
|
|
|
|
{
|
|
|
|
|
if( !GAMESTATE->IsHumanPlayer(pn) )
|
|
|
|
|
continue;
|
|
|
|
|
|
2003-10-03 07:02:05 +00:00
|
|
|
int col = ImportOption( row, hand, pn, i );
|
2003-09-28 02:59:02 +00:00
|
|
|
m_iSelectedOption[pn][i] = col;
|
2003-10-01 10:04:23 +00:00
|
|
|
ASSERT( m_iSelectedOption[pn][i] < (int)row.choices.size() );
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-29 02:24:53 +00:00
|
|
|
|
|
|
|
|
/* Returns an OPT mask. */
|
|
|
|
|
int ScreenOptionsMaster::ExportOption( const OptionRow &row, const OptionRowHandler &hand, int pn, int sel )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
|
|
|
|
/* Figure out which selection is the default. */
|
|
|
|
|
switch( hand.type )
|
|
|
|
|
{
|
|
|
|
|
case ROW_LIST:
|
|
|
|
|
hand.Default.Apply( (PlayerNumber)pn );
|
2003-09-28 04:07:53 +00:00
|
|
|
hand.ListEntries[sel].Apply( (PlayerNumber)pn );
|
2003-09-28 02:59:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ROW_CONFIG:
|
2003-09-29 02:24:53 +00:00
|
|
|
{
|
|
|
|
|
/* Get the original choice. */
|
|
|
|
|
int Original = hand.opt->Get( row.choices );
|
|
|
|
|
|
|
|
|
|
/* Apply. */
|
2003-09-28 07:14:07 +00:00
|
|
|
hand.opt->Put( sel, row.choices );
|
2003-09-29 02:24:53 +00:00
|
|
|
|
|
|
|
|
/* Get the new choice. */
|
|
|
|
|
int New = hand.opt->Get( row.choices );
|
|
|
|
|
|
|
|
|
|
/* If it didn't change, don't return any side-effects. */
|
|
|
|
|
if( Original == New )
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return hand.opt->GetEffects();
|
|
|
|
|
}
|
2003-09-28 02:59:02 +00:00
|
|
|
|
|
|
|
|
case ROW_CHARACTER:
|
|
|
|
|
if( sel == 0 )
|
2003-10-29 00:34:34 +00:00
|
|
|
GAMESTATE->m_pCurCharacters[pn] = GAMESTATE->GetDefaultCharacter();
|
2003-09-28 02:59:02 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
vector<Character*> apCharacters;
|
|
|
|
|
GAMESTATE->GetCharacters( apCharacters );
|
2003-10-01 10:04:23 +00:00
|
|
|
ASSERT( sel - 1 < (int)apCharacters.size() );
|
2003-09-28 02:59:02 +00:00
|
|
|
GAMESTATE->m_pCurCharacters[pn] = apCharacters[sel - 1];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ROW_STEP:
|
|
|
|
|
if( GAMESTATE->m_bEditing )
|
|
|
|
|
{
|
|
|
|
|
// do nothing
|
|
|
|
|
}
|
|
|
|
|
else if( GAMESTATE->m_pCurCourse ) // playing a course
|
|
|
|
|
{
|
|
|
|
|
if( sel == 1 )
|
|
|
|
|
{
|
|
|
|
|
GAMESTATE->m_bDifficultCourses = true;
|
|
|
|
|
LOG->Trace("ScreenPlayerOptions: Using difficult course");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GAMESTATE->m_bDifficultCourses = false;
|
|
|
|
|
LOG->Trace("ScreenPlayerOptions: Using normal course");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( GAMESTATE->m_pCurSong ) // playing a song
|
|
|
|
|
{
|
2003-11-29 18:10:43 +00:00
|
|
|
vector<Steps*> vSteps;
|
|
|
|
|
GAMESTATE->m_pCurSong->GetSteps( vSteps, GAMESTATE->GetCurrentStyleDef()->m_StepsType );
|
|
|
|
|
SortNotesArrayByDifficulty( vSteps );
|
|
|
|
|
Steps* pSteps = vSteps[ sel ];
|
|
|
|
|
// set current notes
|
|
|
|
|
GAMESTATE->m_pCurNotes[pn] = pSteps;
|
|
|
|
|
// set preferred difficulty
|
|
|
|
|
GAMESTATE->m_PreferredDifficulty[pn] = pSteps->GetDifficulty();
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
2003-11-10 04:32:12 +00:00
|
|
|
|
|
|
|
|
case ROW_SAVE_TO_PROFILE:
|
|
|
|
|
if( sel == 1 )
|
|
|
|
|
{
|
|
|
|
|
if( PROFILEMAN->IsUsingProfile((PlayerNumber)pn) )
|
|
|
|
|
{
|
|
|
|
|
Profile* pProfile = PROFILEMAN->GetProfile((PlayerNumber)pn);
|
|
|
|
|
pProfile->m_bUsingProfileDefaultModifiers = true;
|
|
|
|
|
pProfile->m_sDefaultModifiers = GAMESTATE->m_PlayerOptions[pn].GetString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2003-09-29 02:24:53 +00:00
|
|
|
return 0;
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenOptionsMaster::ExportOptions()
|
|
|
|
|
{
|
2003-09-29 02:24:53 +00:00
|
|
|
int ChangeMask = 0;
|
2003-09-28 07:14:07 +00:00
|
|
|
|
2004-01-09 04:14:13 +00:00
|
|
|
CHECKPOINT;
|
2003-09-28 05:04:55 +00:00
|
|
|
unsigned i;
|
|
|
|
|
for( i = 0; i < OptionRowHandlers.size(); ++i )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
|
|
|
|
const OptionRowHandler &hand = OptionRowHandlers[i];
|
|
|
|
|
const OptionRow &row = m_OptionRowAlloc[i];
|
|
|
|
|
|
2003-12-01 00:06:52 +00:00
|
|
|
for( int pn=0; pn<NUM_PLAYERS; pn++ )
|
2003-09-28 02:59:02 +00:00
|
|
|
{
|
2003-12-01 00:06:52 +00:00
|
|
|
if( !GAMESTATE->IsHumanPlayer(pn) )
|
|
|
|
|
continue;
|
2003-09-28 02:59:02 +00:00
|
|
|
|
2003-12-01 00:06:52 +00:00
|
|
|
ChangeMask |= ExportOption( row, hand, pn, m_iSelectedOption[pn][i] );
|
|
|
|
|
}
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-09 04:14:13 +00:00
|
|
|
CHECKPOINT;
|
2003-09-28 04:07:53 +00:00
|
|
|
/* If the selection is on a LIST, and the selected LIST option sets the screen,
|
|
|
|
|
* honor it. */
|
|
|
|
|
m_NextScreen = "";
|
|
|
|
|
|
|
|
|
|
const int row = this->GetCurrentRow();
|
2004-01-09 04:14:13 +00:00
|
|
|
if( row != -1 )
|
2003-09-28 04:07:53 +00:00
|
|
|
{
|
2003-09-29 04:22:59 +00:00
|
|
|
const OptionRowHandler &hand = OptionRowHandlers[row];
|
|
|
|
|
if( hand.type == ROW_LIST )
|
|
|
|
|
{
|
|
|
|
|
const int sel = m_iSelectedOption[0][row];
|
|
|
|
|
const ModeChoice &mc = hand.ListEntries[sel];
|
|
|
|
|
if( mc.m_sScreen != "" )
|
|
|
|
|
m_NextScreen = mc.m_sScreen;
|
|
|
|
|
}
|
2003-09-28 04:07:53 +00:00
|
|
|
}
|
2004-01-09 04:14:13 +00:00
|
|
|
CHECKPOINT;
|
2003-09-28 04:07:53 +00:00
|
|
|
|
2003-09-28 02:59:02 +00:00
|
|
|
// NEXT_SCREEN(GAMESTATE->m_PlayMode) );
|
|
|
|
|
// XXX: handle different destinations based on play mode?
|
|
|
|
|
if( m_NextScreen == "" )
|
|
|
|
|
m_NextScreen = NEXT_SCREEN;
|
2003-09-28 05:04:55 +00:00
|
|
|
|
2003-09-28 07:14:07 +00:00
|
|
|
/* Did the theme change? */
|
2003-09-29 02:24:53 +00:00
|
|
|
if( (ChangeMask & OPT_APPLY_THEME) ||
|
|
|
|
|
(ChangeMask & OPT_APPLY_GRAPHICS) ) // reset graphics to apply new window title and icon
|
|
|
|
|
ApplyGraphicOptions();
|
2003-09-28 05:04:55 +00:00
|
|
|
|
2003-09-29 02:24:53 +00:00
|
|
|
if( ChangeMask & OPT_SAVE_PREFERENCES )
|
2003-09-28 05:04:55 +00:00
|
|
|
{
|
2003-09-29 02:24:53 +00:00
|
|
|
/* Save preferences. */
|
2003-09-28 05:04:55 +00:00
|
|
|
LOG->Trace("ROW_CONFIG used; saving ...");
|
|
|
|
|
PREFSMAN->SaveGlobalPrefsToDisk();
|
2003-10-02 01:41:09 +00:00
|
|
|
SaveGamePrefsToDisk();
|
2003-09-28 05:04:55 +00:00
|
|
|
}
|
2003-09-29 03:22:51 +00:00
|
|
|
|
|
|
|
|
if( ChangeMask & OPT_RESET_GAME )
|
|
|
|
|
{
|
|
|
|
|
ResetGame();
|
|
|
|
|
m_NextScreen = "";
|
|
|
|
|
}
|
2003-10-12 20:34:46 +00:00
|
|
|
|
|
|
|
|
if( ChangeMask & OPT_APPLY_SOUND )
|
|
|
|
|
{
|
|
|
|
|
SOUNDMAN->SetPrefs( PREFSMAN->m_fSoundVolume );
|
|
|
|
|
}
|
2003-11-10 04:32:12 +00:00
|
|
|
|
|
|
|
|
if( ChangeMask & OPT_SAVE_MODIFIERS_TO_PROFILE )
|
|
|
|
|
{
|
|
|
|
|
SOUNDMAN->SetPrefs( PREFSMAN->m_fSoundVolume );
|
|
|
|
|
}
|
2004-01-09 04:14:13 +00:00
|
|
|
CHECKPOINT;
|
2003-09-28 02:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenOptionsMaster::GoToNextState()
|
|
|
|
|
{
|
|
|
|
|
if( GAMESTATE->m_bEditing )
|
|
|
|
|
SCREENMAN->PopTopScreen();
|
2003-09-29 03:22:51 +00:00
|
|
|
else if( m_NextScreen != "" )
|
2003-09-28 02:59:02 +00:00
|
|
|
SCREENMAN->SetNewScreen( m_NextScreen );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenOptionsMaster::GoToPrevState()
|
|
|
|
|
{
|
|
|
|
|
/* XXX: A better way to handle this would be to check if we're a pushed screen. */
|
|
|
|
|
if( GAMESTATE->m_bEditing )
|
|
|
|
|
SCREENMAN->PopTopScreen();
|
|
|
|
|
// XXX: handle different destinations based on play mode?
|
|
|
|
|
else
|
|
|
|
|
SCREENMAN->SetNewScreen( PREV_SCREEN ); // (GAMESTATE->m_PlayMode) );
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-07 07:25:52 +00:00
|
|
|
void ScreenOptionsMaster::RefreshIcons()
|
|
|
|
|
{
|
|
|
|
|
ASSERT( m_iNumOptionRows < (int) MAX_OPTION_LINES );
|
|
|
|
|
|
|
|
|
|
for( int p=0; p<NUM_PLAYERS; p++ ) // foreach player
|
|
|
|
|
{
|
|
|
|
|
if( !GAMESTATE->IsHumanPlayer(p) )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for( int i=0; i<m_iNumOptionRows; i++ ) // foreach options line
|
|
|
|
|
{
|
2004-01-09 04:14:13 +00:00
|
|
|
const OptionRow &row = m_OptionRow[i];
|
2003-11-07 07:25:52 +00:00
|
|
|
|
|
|
|
|
int iSelection = m_iSelectedOption[p][i];
|
|
|
|
|
if( iSelection >= (int)m_OptionRow[i].choices.size() )
|
|
|
|
|
{
|
|
|
|
|
/* Invalid selection. Send debug output, to aid debugging. */
|
2004-01-03 04:38:17 +00:00
|
|
|
CString error = ssprintf("Option row with name '%s' selects item %i, but there are only %i items:\n",
|
2003-11-07 07:25:52 +00:00
|
|
|
m_OptionRow[i].name.c_str(),
|
2004-01-03 04:38:17 +00:00
|
|
|
iSelection, (int) m_OptionRow[i].choices.size() );
|
2003-11-07 07:25:52 +00:00
|
|
|
|
|
|
|
|
for( unsigned j = 0; j < m_OptionRow[i].choices.size(); ++j )
|
|
|
|
|
error += ssprintf(" %s\n", m_OptionRow[i].choices[j].c_str());
|
|
|
|
|
|
|
|
|
|
RageException::Throw( "%s", error.c_str() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set icon name
|
|
|
|
|
CString sIcon;
|
2004-01-09 04:14:13 +00:00
|
|
|
const OptionRowHandler &handler = OptionRowHandlers[i];
|
2003-11-07 07:25:52 +00:00
|
|
|
switch( handler.type )
|
|
|
|
|
{
|
|
|
|
|
case ROW_LIST:
|
|
|
|
|
sIcon = handler.ListEntries[iSelection].m_sModifiers;
|
|
|
|
|
break;
|
|
|
|
|
case ROW_STEP:
|
|
|
|
|
case ROW_CHARACTER:
|
|
|
|
|
sIcon = row.choices[iSelection];
|
|
|
|
|
break;
|
|
|
|
|
case ROW_CONFIG:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-08 04:25:33 +00:00
|
|
|
/* XXX: hack to not display text in the song options menu */
|
|
|
|
|
if( row.bOneChoiceForAllPlayers )
|
|
|
|
|
sIcon = "";
|
|
|
|
|
|
2004-01-09 04:14:13 +00:00
|
|
|
LoadOptionIcon( (PlayerNumber)p, i, sIcon );
|
2003-11-07 07:25:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|