2011-03-17 01:47:30 -04:00
#include "global.h"
#include "OptionsList.h"
#include "GameState.h"
#include "RageLog.h"
#include "Course.h"
#include "SongUtil.h"
#include "StepsUtil.h"
#include "Style.h"
#include "InputEventPlus.h"
#include "CodeDetector.h"
#include "InputMapper.h"
#include "PlayerState.h"
#define LINE(sLineName) THEME->GetMetric (m_sName,ssprintf("Line%s",sLineName.c_str()))
#define MAX_ITEMS_BEFORE_SPLIT THEME->GetMetricI(m_sName,"MaxItemsBeforeSplit")
#define ITEMS_SPLIT_WIDTH THEME->GetMetricF(m_sName,"ItemsSplitWidth")
#define DIRECT_LINES THEME->GetMetric (m_sName,"DirectLines")
#define TOP_MENUS THEME->GetMetric (m_sName,"TopMenus")
static const RString RESET_ROW = "ResetOptions" ;
void OptionListRow :: Load ( OptionsList * pOptions , const RString & sType )
{
m_pOptions = pOptions ;
ITEMS_SPACING_Y . Load ( sType , "ItemsSpacingY" );
m_Text . resize ( 1 );
m_Text [ 0 ]. SetName ( "Text" );
m_Text [ 0 ]. LoadFromFont ( THEME -> GetPathF ( sType , "normal" ) );
ActorUtil :: LoadAllCommands ( m_Text [ 0 ], sType );
m_Underlines . resize ( 1 );
m_Underlines [ 0 ]. Load ( THEME -> GetPathG ( sType , "underline" ) );
m_Underlines [ 0 ] -> SetName ( "Underline" );
ActorUtil :: LoadAllCommands ( * m_Underlines [ 0 ], sType );
m_Text [ 0 ]. PlayCommand ( "On" );
m_Underlines [ 0 ] -> PlayCommand ( "On" );
}
// GetTitleForHandler
// can always use the title
// can have special speed row titles, note skin, or any SELECT_ONE
void OptionListRow :: SetFromHandler ( const OptionRowHandler * pHandler )
{
this -> FinishTweening ();
this -> RemoveAllChildren ();
if ( pHandler == NULL )
return ;
int iNum = max ( pHandler -> m_Def . m_vsChoices . size (), m_Text . size () ) + 1 ;
m_Text . resize ( iNum , m_Text [ 0 ] );
m_Underlines . resize ( iNum , m_Underlines [ 0 ] );
for ( unsigned i = 0 ; i < pHandler -> m_Def . m_vsChoices . size (); ++ i )
{
// init underlines
this -> AddChild ( m_Underlines [ i ] );
// init text
this -> AddChild ( & m_Text [ i ] );
}
SetTextFromHandler ( pHandler );
const unsigned iCnt = pHandler -> m_Def . m_vsChoices . size ();
m_bItemsInTwoRows = ( int ) iCnt > MAX_ITEMS_BEFORE_SPLIT ;
const float fWidth = ITEMS_SPLIT_WIDTH ;
float fY = 0 ;
for ( unsigned i = 0 ; i < iCnt ; ++ i )
{
float fX = 0 ;
if ( m_bItemsInTwoRows )
{
if ( ( i % 2 ) == 0 )
fX = - fWidth / 2 ;
else
fX = + fWidth / 2 ;
}
// set the Y position of each item in the line
m_Text [ i ]. SetXY ( fX , fY );
m_Underlines [ i ] -> SetXY ( fX , fY );
if ( m_bItemsInTwoRows )
m_Underlines [ i ] -> PlayCommand ( "SetTwoRows" );
else
m_Underlines [ i ] -> PlayCommand ( "SetOneRow" );
if ( ! m_bItemsInTwoRows || ( i % 2 ) == 1 || i + 1 == iCnt )
fY += ITEMS_SPACING_Y ;
}
int iExit = pHandler -> m_Def . m_vsChoices . size ();
m_Text [ iExit ]. SetText ( "Exit" ); // XXX localize
m_Text [ iExit ]. SetXY ( 0 , fY );
this -> AddChild ( & m_Text [ iExit ] );
}
void OptionListRow :: SetTextFromHandler ( const OptionRowHandler * pHandler )
{
2012-12-27 11:38:53 -05:00
ASSERT ( pHandler != NULL );
2011-03-17 01:47:30 -04:00
for ( unsigned i = 0 ; i < pHandler -> m_Def . m_vsChoices . size (); ++ i )
{
// init text
RString sText = pHandler -> GetThemedItemText ( i );
RString sDest = pHandler -> GetScreen ( i );
if ( m_pOptions -> m_setDirectRows . find ( sDest ) != m_pOptions -> m_setDirectRows . end () && sDest . size () )
{
const OptionRowHandler * pTarget = m_pOptions -> m_Rows [ sDest ];
if ( pTarget -> m_Def . m_selectType == SELECT_ONE )
{
int iSelection = m_pOptions -> GetOneSelection ( sDest );
sText += ": " + pTarget -> GetThemedItemText ( iSelection );
}
}
m_Text [ i ]. SetText ( sText );
}
}
void OptionListRow :: SetUnderlines ( const vector < bool > & aSelections , const OptionRowHandler * pHandler )
{
for ( unsigned i = 0 ; i < aSelections . size (); ++ i )
{
Actor * pActor = m_Underlines [ i ];
bool bSelected = aSelections [ i ];
RString sDest = pHandler -> GetScreen ( i );
if ( sDest . size () )
{
/* This is a submenu. Underline the row if its options have been changed
* from the default. */
const OptionRowHandler * pTarget = m_pOptions -> m_Rows [ sDest ];
if ( pTarget -> m_Def . m_selectType == SELECT_ONE )
{
int iSelection = m_pOptions -> GetOneSelection ( sDest );
const OptionRowHandler * lHandler = m_pOptions -> m_Rows . find ( sDest ) -> second ;
int iDefault = lHandler -> GetDefaultOption ();
if ( iDefault != - 1 && iSelection != iDefault )
bSelected |= true ;
}
else if ( pTarget -> m_Def . m_selectType == SELECT_MULTIPLE )
{
const vector < bool > & bTargetSelections = m_pOptions -> m_bSelections . find ( sDest ) -> second ;
for ( unsigned j = 0 ; j < bTargetSelections . size (); j ++ )
{
if ( bTargetSelections [ j ] )
bSelected = true ;
}
}
}
pActor -> PlayCommand ( bSelected ? "Show" : "Hide" );
}
}
void OptionListRow :: PositionCursor ( Actor * pCursor , int iSelection )
{
float fX = m_Text [ iSelection ]. GetDestX ();
float fY = m_Text [ iSelection ]. GetDestY ();
if ( m_bItemsInTwoRows )
pCursor -> PlayCommand ( "PositionTwoRows" );
else
pCursor -> PlayCommand ( "PositionOneRow" );
pCursor -> SetXY ( fX , fY );
}
OptionsList :: OptionsList ()
{
m_iCurrentRow = 0 ;
m_pLinked = NULL ;
}
OptionsList ::~ OptionsList ()
{
FOREACHM ( RString , OptionRowHandler * , m_Rows , hand )
delete hand -> second ;
}
void OptionsList :: Load ( RString sType , PlayerNumber pn )
{
TOP_MENU . Load ( sType , "TopMenu" );
m_pn = pn ;
m_bStartIsDown = false ;
m_Codes . Load ( sType );
m_Cursor . Load ( THEME -> GetPathG ( sType , "cursor" ) );
m_Cursor -> SetName ( "Cursor" );
ActorUtil :: LoadAllCommands ( * m_Cursor , sType );
this -> AddChild ( m_Cursor );
vector < RString > asDirectLines ;
split ( DIRECT_LINES , "," , asDirectLines , true );
FOREACH ( RString , asDirectLines , s )
m_setDirectRows . insert ( * s );
vector < RString > setToLoad ;
split ( TOP_MENUS , "," , setToLoad );
m_setTopMenus . insert ( setToLoad . begin (), setToLoad . end () );
while ( ! setToLoad . empty () )
{
RString sLineName = * setToLoad . begin ();
setToLoad . erase ( setToLoad . begin () );
if ( m_Rows . find ( sLineName ) != m_Rows . end () )
continue ;
RString sRowCommands = LINE ( sLineName );
Commands cmds ;
2013-10-13 15:37:05 -04:00
ParseCommands ( sRowCommands , cmds , false );
2011-03-17 01:47:30 -04:00
OptionRowHandler * pHand = OptionRowHandlerUtil :: Make ( cmds );
if ( pHand == NULL )
2014-07-12 14:59:10 -06:00
{
LuaHelpers :: ReportScriptErrorFmt ( "Invalid OptionRowHandler '%s' in %s::Line%s" , cmds . GetOriginalCommandString (). c_str (), m_sName . c_str (), sLineName . c_str ());
continue ;
}
2011-03-17 01:47:30 -04:00
m_Rows [ sLineName ] = pHand ;
m_asLoadedRows . push_back ( sLineName );
for ( size_t i = 0 ; i < pHand -> m_Def . m_vsChoices . size (); ++ i )
{
RString sScreen = pHand -> GetScreen ( i );
if ( ! sScreen . empty () )
setToLoad . push_back ( sScreen );
}
}
for ( int i = 0 ; i < 2 ; ++ i )
{
m_Row [ i ]. SetName ( "OptionsList" );
m_Row [ i ]. Load ( this , "OptionsList" );
ActorUtil :: LoadAllCommands ( m_Row [ i ], sType );
this -> AddChild ( & m_Row [ i ] );
}
this -> PlayCommand ( "TweenOff" );
this -> FinishTweening ();
}
void OptionsList :: Reset ()
{
/* Import options. */
FOREACHM ( RString , OptionRowHandler * , m_Rows , hand )
{
RString sLineName = hand -> first ;
ImportRow ( sLineName );
}
}
void OptionsList :: Open ()
{
this -> PlayCommand ( "Reset" );
Message msg ( "OptionsListOpened" );
msg . SetParam ( "Player" , m_pn );
MESSAGEMAN -> Broadcast ( msg );
/* Push the initial menu. */
ASSERT ( m_asMenuStack . size () == 0 );
Push ( TOP_MENU );
this -> FinishTweening ();
m_Row [ ! m_iCurrentRow ]. SetFromHandler ( NULL );
this -> PlayCommand ( "TweenOn" );
}
void OptionsList :: Close ()
{
Message msg ( "OptionsListClosed" );
msg . SetParam ( "Player" , m_pn );
MESSAGEMAN -> Broadcast ( msg );
m_bStartIsDown = false ;
m_asMenuStack . clear ();
this -> PlayCommand ( "TweenOff" );
}
RString OptionsList :: GetCurrentRow () const
{
ASSERT ( ! m_asMenuStack . empty () ); // called while the menu was closed
return m_asMenuStack . back ();
}
const OptionRowHandler * OptionsList :: GetCurrentHandler ()
{
RString sCurrentRow = GetCurrentRow ();
return m_Rows [ sCurrentRow ];
}
int OptionsList :: GetOneSelection ( RString sRow , bool bAllowFail ) const
{
map < RString , vector < bool > >:: const_iterator it = m_bSelections . find ( sRow );
ASSERT_M ( it != m_bSelections . end (), sRow );
const vector < bool > & bSelections = it -> second ;
for ( unsigned i = 0 ; i < bSelections . size (); i ++ )
{
if ( bSelections [ i ] )
return i ;
}
ASSERT ( bAllowFail ); // shouldn't call this if not expecting one to be selected
return - 1 ;
}
void OptionsList :: PositionCursor ()
{
m_Row [ m_iCurrentRow ]. PositionCursor ( m_Cursor , m_iMenuStackSelection );
}
/* Toggle to the next menu. This is used to switch quickly through option submenus,
* to choose many options or to find the one you're looking for. For that goal,
* it's not helpful to switch only through the options listed in the current parent
* menu; always toggle through the whole set. Skip menus that only contain other
* menus. */
void OptionsList :: SwitchMenu ( int iDir )
{
/* Consider the menu as a list, where the main menu is the first item and the
* submenus follow. This allows consistent navigation; moving right from the
* main menu walks through the menus, moving left goes back as far as the main
* menu. Don't loop, so it's harder to lose track of menus. */
RString sTopRow = m_asMenuStack . front ();
const OptionRowHandler * pHandler = m_Rows [ sTopRow ];
int iCurrentRow = 0 ;
if ( m_asMenuStack . size () == 1 )
iCurrentRow = - 1 ;
else
iCurrentRow = FindScreenInHandler ( pHandler , m_asMenuStack . back () );
iCurrentRow += iDir ;
if ( iCurrentRow >= 0 )
{
if ( iCurrentRow >= ( int ) pHandler -> m_Def . m_vsChoices . size () )
return ;
RString sDest = pHandler -> GetScreen ( iCurrentRow );
if ( sDest . empty () )
return ;
if ( m_asMenuStack . size () == 1 )
m_asMenuStack . push_back ( sDest );
else
m_asMenuStack . back () = sDest ;
}
else
{
if ( m_asMenuStack . size () == 1 )
return ;
m_asMenuStack . pop_back ();
}
SetDefaultCurrentRow ();
SwitchToCurrentRow ();
TweenOnCurrentRow ( iDir > 0 );
}
void OptionsList :: MoveItem ( const RString & sRowName , int iMove )
{
}
2013-01-12 22:48:38 -05:00
bool OptionsList :: Input ( const InputEventPlus & input )
2011-03-17 01:47:30 -04:00
{
Message msg ( "" );
if ( m_Codes . InputMessage ( input , msg ) )
this -> HandleMessage ( msg );
const OptionRowHandler * pHandler = GetCurrentHandler ();
PlayerNumber pn = input . pn ;
if ( m_bStartIsDown )
{
if ( input . MenuI == GAME_BUTTON_LEFT || input . MenuI == GAME_BUTTON_RIGHT )
{
if ( input . type != IET_FIRST_PRESS )
2013-01-12 22:48:38 -05:00
return false ;
2011-03-17 01:47:30 -04:00
m_bAcceptStartRelease = false ;
const RString & sCurrentRow = m_asMenuStack . back ();
vector < bool > & bSelections = m_bSelections [ sCurrentRow ];
if ( m_iMenuStackSelection == ( int ) bSelections . size () )
2013-01-12 22:48:38 -05:00
return false ;
2011-03-17 01:47:30 -04:00
RString sDest = pHandler -> GetScreen ( m_iMenuStackSelection );
if ( m_setDirectRows . find ( sDest ) != m_setDirectRows . end () && sDest . size () )
{
const OptionRowHandler * pTarget = m_Rows [ sDest ];
vector < bool > & bTargetSelections = m_bSelections [ sDest ];
if ( pTarget -> m_Def . m_selectType == SELECT_ONE )
{
int iSelection = GetOneSelection ( sDest );
int iDir = ( input . MenuI == GAME_BUTTON_RIGHT ? + 1 :- 1 );
iSelection += iDir ;
wrap ( iSelection , bTargetSelections . size () );
SelectItem ( sDest , iSelection );
Message lMsg ( "OptionsListQuickChange" );
lMsg . SetParam ( "Player" , pn );
lMsg . SetParam ( "Direction" , iDir );
MESSAGEMAN -> Broadcast ( lMsg );
}
}
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
}
if ( input . MenuI == GAME_BUTTON_LEFT )
{
if ( input . type == IET_RELEASE )
2013-01-12 22:48:38 -05:00
return false ;
2011-03-17 01:47:30 -04:00
if ( INPUTMAPPER -> IsBeingPressed ( GAME_BUTTON_RIGHT , pn ) )
{
if ( input . type == IET_FIRST_PRESS )
SwitchMenu ( - 1 );
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
-- m_iMenuStackSelection ;
wrap ( m_iMenuStackSelection , pHandler -> m_Def . m_vsChoices . size () + 1 ); // +1 for exit row
PositionCursor ();
Message lMsg ( "OptionsListLeft" );
lMsg . SetParam ( "Player" , input . pn );
MESSAGEMAN -> Broadcast ( lMsg );
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
else if ( input . MenuI == GAME_BUTTON_RIGHT )
{
if ( input . type == IET_RELEASE )
2013-01-12 22:48:38 -05:00
return false ;
2011-03-17 01:47:30 -04:00
if ( INPUTMAPPER -> IsBeingPressed ( GAME_BUTTON_LEFT , pn ) )
{
if ( input . type == IET_FIRST_PRESS )
SwitchMenu ( + 1 );
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
++ m_iMenuStackSelection ;
wrap ( m_iMenuStackSelection , pHandler -> m_Def . m_vsChoices . size () + 1 ); // +1 for exit row
PositionCursor ();
Message lMsg ( "OptionsListRight" );
lMsg . SetParam ( "Player" , input . pn );
MESSAGEMAN -> Broadcast ( lMsg );
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
else if ( input . MenuI == GAME_BUTTON_START )
{
if ( input . type == IET_FIRST_PRESS )
{
m_bStartIsDown = true ;
m_bAcceptStartRelease = true ;
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
if ( input . type == IET_RELEASE )
{
if ( m_bAcceptStartRelease )
Start ();
m_bStartIsDown = false ;
}
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
else if ( input . MenuI == GAME_BUTTON_SELECT )
{
if ( input . type != IET_FIRST_PRESS )
2013-01-12 22:48:38 -05:00
return false ;
2011-03-17 01:47:30 -04:00
// if( input.type == IET_RELEASE )
{
Close ();
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
2013-01-12 22:48:38 -05:00
return true ;
2011-03-17 01:47:30 -04:00
}
2013-01-12 22:48:38 -05:00
return false ;
2011-03-17 01:47:30 -04:00
}
void OptionsList :: SwitchToCurrentRow ()
{
m_iCurrentRow = ! m_iCurrentRow ;
/* Set up the new row. */
m_Row [ m_iCurrentRow ]. SetFromHandler ( GetCurrentHandler () );
m_Row [ m_iCurrentRow ]. SetUnderlines ( m_bSelections [ m_asMenuStack . back ()], GetCurrentHandler () );
PositionCursor ();
Message msg ( "OptionsMenuChanged" );
msg . SetParam ( "Player" , m_pn );
msg . SetParam ( "Menu" , m_asMenuStack . back () );
MESSAGEMAN -> Broadcast ( msg );
}
/* After setting up a new row, tween it on. */
void OptionsList :: TweenOnCurrentRow ( bool bForward )
{
OptionListRow & OldRow = m_Row [ ! m_iCurrentRow ];
OptionListRow & NewRow = m_Row [ m_iCurrentRow ];
/* Tween out the old row. */
if ( bForward )
OldRow . PlayCommand ( "TweenOutForward" );
else
OldRow . PlayCommand ( "TweenOutBackward" );
/* Tween in the old row. */
if ( bForward )
NewRow . PlayCommand ( "TweenInForward" );
else
NewRow . PlayCommand ( "TweenInBackward" );
}
void OptionsList :: ImportRow ( RString sRow )
{
vector < bool > aSelections [ NUM_PLAYERS ];
vector < PlayerNumber > vpns ;
vpns . push_back ( m_pn );
OptionRowHandler * pHandler = m_Rows [ sRow ];
aSelections [ m_pn ]. resize ( pHandler -> m_Def . m_vsChoices . size () );
pHandler -> ImportOption ( NULL , vpns , aSelections );
m_bSelections [ sRow ] = aSelections [ m_pn ];
if ( m_setTopMenus . find ( sRow ) != m_setTopMenus . end () )
fill ( m_bSelections [ sRow ]. begin (), m_bSelections [ sRow ]. end (), false );
}
void OptionsList :: ExportRow ( RString sRow )
{
if ( m_setTopMenus . find ( sRow ) != m_setTopMenus . end () )
return ;
vector < bool > aSelections [ NUM_PLAYERS ];
aSelections [ m_pn ] = m_bSelections [ sRow ];
vector < PlayerNumber > vpns ;
vpns . push_back ( m_pn );
m_Rows [ sRow ] -> ExportOption ( vpns , aSelections );
}
void OptionsList :: SetDefaultCurrentRow ()
{
/* If all items on the row just point to other menus, default to 0. */
m_iMenuStackSelection = 0 ;
const RString & sCurrentRow = m_asMenuStack . back ();
const OptionRowHandler * pHandler = m_Rows . find ( sCurrentRow ) -> second ;
if ( pHandler -> m_Def . m_selectType == SELECT_ONE )
{
/* One item is selected, so position the cursor on it. */
m_iMenuStackSelection = GetOneSelection ( sCurrentRow , true );
if ( m_iMenuStackSelection == - 1 )
m_iMenuStackSelection = 0 ;
}
}
int OptionsList :: FindScreenInHandler ( const OptionRowHandler * pHandler , RString sScreen )
{
for ( size_t i = 0 ; i < pHandler -> m_Def . m_vsChoices . size (); ++ i )
{
if ( pHandler -> GetScreen ( i ) == sScreen )
return i ;
}
return - 1 ;
}
void OptionsList :: Pop ()
{
if ( m_asMenuStack . size () == 1 )
{
Close ();
return ;
}
RString sLastMenu = m_asMenuStack . back ();
m_asMenuStack . pop_back ();
/* Choose the default option. */
SetDefaultCurrentRow ();
/* If the old menu exists as a target from the new menu, switch to it. */
const OptionRowHandler * pHandler = GetCurrentHandler ();
int iIndex = FindScreenInHandler ( pHandler , sLastMenu );
if ( iIndex != - 1 )
m_iMenuStackSelection = iIndex ;
SwitchToCurrentRow ();
TweenOnCurrentRow ( false );
}
void OptionsList :: Push ( RString sDest )
{
m_asMenuStack . push_back ( sDest );
SetDefaultCurrentRow ();
SwitchToCurrentRow ();
}
void OptionsList :: SelectItem ( const RString & sRowName , int iMenuItem )
{
const OptionRowHandler * pHandler = m_Rows [ sRowName ];
vector < bool > & bSelections = m_bSelections [ sRowName ];
if ( pHandler -> m_Def . m_selectType == SELECT_MULTIPLE )
{
bool bSelected = ! bSelections [ iMenuItem ];
bSelections [ iMenuItem ] = bSelected ;
// if( bSelected )
// m_SoundToggleOn.Play();
// else
// m_SoundToggleOff.Play();
}
else // data.selectType != SELECT_MULTIPLE
{
fill ( bSelections . begin (), bSelections . end (), false );
bSelections [ iMenuItem ] = true ;
}
SelectionsChanged ( sRowName );
UpdateMenuFromSelections ();
}
void OptionsList :: SelectionsChanged ( const RString & sRowName )
{
const OptionRowHandler * pHandler = m_Rows [ sRowName ];
vector < bool > & bSelections = m_bSelections [ sRowName ];
if ( pHandler -> m_Def . m_bOneChoiceForAllPlayers && m_pLinked != NULL )
{
vector < bool > & bLinkedSelections = m_pLinked -> m_bSelections [ sRowName ];
bLinkedSelections = bSelections ;
if ( m_pLinked -> IsOpened () )
m_pLinked -> UpdateMenuFromSelections ();
m_pLinked -> ExportRow ( sRowName );
}
ExportRow ( sRowName );
}
void OptionsList :: UpdateMenuFromSelections ()
{
const vector < bool > & bCurrentSelections = m_bSelections . find ( GetCurrentRow ()) -> second ;
m_Row [ m_iCurrentRow ]. SetUnderlines ( bCurrentSelections , GetCurrentHandler () );
m_Row [ m_iCurrentRow ]. SetTextFromHandler ( GetCurrentHandler () );
}
bool OptionsList :: Start ()
{
const OptionRowHandler * pHandler = GetCurrentHandler ();
const RString & sCurrentRow = m_asMenuStack . back ();
vector < bool > & bSelections = m_bSelections [ sCurrentRow ];
if ( m_iMenuStackSelection == ( int ) bSelections . size () )
{
Pop ();
Message msg ( "OptionsListPop" );
msg . SetParam ( "Player" , m_pn );
MESSAGEMAN -> Broadcast ( msg );
return m_asMenuStack . empty ();
}
{
RString sIconText ;
GameCommand gc ;
pHandler -> GetIconTextAndGameCommand ( m_iMenuStackSelection , sIconText , gc );
if ( gc . m_sName == RESET_ROW )
{
GAMESTATE -> m_pPlayerState [ m_pn ] -> ResetToDefaultPlayerOptions ( ModsLevel_Preferred );
GAMESTATE -> ResetToDefaultSongOptions ( ModsLevel_Preferred );
/* Import options. */
FOREACHM ( RString , OptionRowHandler * , m_Rows , hand )
{
ImportRow ( hand -> first );
SelectionsChanged ( hand -> first );
}
UpdateMenuFromSelections ();
Message msg ( "OptionsListReset" );
msg . SetParam ( "Player" , m_pn );
MESSAGEMAN -> Broadcast ( msg );
return false ;
}
}
RString sDest = pHandler -> GetScreen ( m_iMenuStackSelection );
if ( sDest . size () )
{
Push ( sDest );
TweenOnCurrentRow ( true );
Message msg ( "OptionsListPush" );
msg . SetParam ( "Player" , m_pn );
MESSAGEMAN -> Broadcast ( msg );
return false ;
}
SelectItem ( GetCurrentRow (), m_iMenuStackSelection );
/* Move to the exit row. */
m_iMenuStackSelection = ( int ) bSelections . size ();
PositionCursor ();
Message msg ( "OptionsListStart" );
msg . SetParam ( "Player" , m_pn );
MESSAGEMAN -> Broadcast ( msg );
return false ;
}
/*
* Copyright (c) 2006 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.
*/