2003-06-20 23:07:45 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "ScreenSelectMaster.h"
|
|
|
|
|
#include "ScreenManager.h"
|
|
|
|
|
#include "PrefsManager.h"
|
|
|
|
|
#include "GameManager.h"
|
|
|
|
|
#include "ThemeManager.h"
|
2004-07-08 00:10:34 +00:00
|
|
|
#include "GameSoundManager.h"
|
2003-06-20 23:07:45 +00:00
|
|
|
#include "GameState.h"
|
|
|
|
|
#include "AnnouncerManager.h"
|
2004-12-02 06:29:20 +00:00
|
|
|
#include "GameCommand.h"
|
2003-06-20 23:07:45 +00:00
|
|
|
#include "ActorUtil.h"
|
2003-11-05 18:49:57 +00:00
|
|
|
#include "RageLog.h"
|
2004-04-13 23:11:32 +00:00
|
|
|
#include <set>
|
2004-05-29 04:06:57 +00:00
|
|
|
#include "Foreach.h"
|
2005-01-08 16:59:59 +00:00
|
|
|
#include "RageSoundManager.h"
|
2005-09-23 00:44:52 +00:00
|
|
|
#include "InputEventPlus.h"
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-03-28 08:01:36 +00:00
|
|
|
AutoScreenMessage( SM_PlayPostSwitchPage )
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
CString CURSOR_OFFSET_X_FROM_ICON_NAME( size_t p ) { return ssprintf("CursorP%dOffsetXFromIcon",int(p+1)); }
|
|
|
|
|
CString CURSOR_OFFSET_Y_FROM_ICON_NAME( size_t p ) { return ssprintf("CursorP%dOffsetYFromIcon",int(p+1)); }
|
2005-02-06 05:15:57 +00:00
|
|
|
/* e.g. "OptionOrderLeft=0:1,1:2,2:3,3:4" */
|
|
|
|
|
CString OPTION_ORDER_NAME( size_t dir ) { return "OptionOrder"+MenuDirToString((MenuDir)dir); }
|
2005-02-06 04:57:57 +00:00
|
|
|
|
2004-11-26 17:28:47 +00:00
|
|
|
REGISTER_SCREEN_CLASS( ScreenSelectMaster );
|
2005-02-02 01:38:20 +00:00
|
|
|
ScreenSelectMaster::ScreenSelectMaster( CString sClassName ) : ScreenSelect( sClassName ),
|
2005-07-14 08:47:12 +00:00
|
|
|
SHOW_ICON(m_sName,"ShowIcon"),
|
|
|
|
|
SHOW_SCROLLER(m_sName,"ShowScroller"),
|
2005-07-19 00:51:54 +00:00
|
|
|
SHOW_CURSOR(m_sName,"ShowCursor"),
|
2005-07-14 21:51:22 +00:00
|
|
|
SHARED_SELECTION(m_sName,"SharedSelection"),
|
2005-02-02 01:38:20 +00:00
|
|
|
NUM_CHOICES_ON_PAGE_1(m_sName,"NumChoicesOnPage1"),
|
2005-07-14 08:47:12 +00:00
|
|
|
CURSOR_OFFSET_X_FROM_ICON(m_sName,CURSOR_OFFSET_X_FROM_ICON_NAME,NUM_PLAYERS),
|
|
|
|
|
CURSOR_OFFSET_Y_FROM_ICON(m_sName,CURSOR_OFFSET_Y_FROM_ICON_NAME,NUM_PLAYERS),
|
2005-03-02 04:35:12 +00:00
|
|
|
OVERRIDE_LOCK_INPUT_SECONDS(m_sName,"OverrideLockInputSeconds"),
|
|
|
|
|
LOCK_INPUT_SECONDS(m_sName,"LockInputSeconds"),
|
2005-02-02 01:38:20 +00:00
|
|
|
PRE_SWITCH_PAGE_SECONDS(m_sName,"PreSwitchPageSeconds"),
|
|
|
|
|
POST_SWITCH_PAGE_SECONDS(m_sName,"PostSwitchPageSeconds"),
|
2005-03-01 16:03:11 +00:00
|
|
|
OVERRIDE_SLEEP_AFTER_TWEEN_OFF_SECONDS(m_sName,"OverrideSleepAfterTweenOffSeconds"),
|
|
|
|
|
SLEEP_AFTER_TWEEN_OFF_SECONDS(m_sName,"SleepAfterTweenOffSeconds"),
|
2005-02-06 05:15:57 +00:00
|
|
|
OPTION_ORDER(m_sName,OPTION_ORDER_NAME,NUM_MENU_DIRS),
|
2005-02-02 01:38:20 +00:00
|
|
|
WRAP_CURSOR(m_sName,"WrapCursor"),
|
2005-05-03 23:12:29 +00:00
|
|
|
WRAP_SCROLLER(m_sName,"WrapScroller"),
|
2005-07-26 19:55:00 +00:00
|
|
|
LOOP_SCROLLER(m_sName,"LoopScroller"),
|
2005-05-03 23:12:29 +00:00
|
|
|
SCROLLER_FAST_CATCHUP(m_sName,"ScrollerFastCatchup"),
|
2005-04-04 02:34:56 +00:00
|
|
|
ALLOW_REPEATING_INPUT(m_sName,"AllowRepeatingInput"),
|
2005-02-02 01:38:20 +00:00
|
|
|
SCROLLER_SECONDS_PER_ITEM(m_sName,"ScrollerSecondsPerItem"),
|
|
|
|
|
SCROLLER_NUM_ITEMS_TO_DRAW(m_sName,"ScrollerNumItemsToDraw"),
|
2005-05-03 09:29:54 +00:00
|
|
|
SCROLLER_TRANSFORM(m_sName,"ScrollerTransform"),
|
2005-09-02 21:42:34 +00:00
|
|
|
SCROLLER_SUBDIVISIONS(m_sName,"ScrollerSubdivisions"),
|
2005-02-02 01:38:20 +00:00
|
|
|
DEFAULT_CHOICE(m_sName,"DefaultChoice")
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-02-23 06:29:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenSelectMaster::Init()
|
|
|
|
|
{
|
|
|
|
|
ScreenSelect::Init();
|
2005-01-04 10:47:28 +00:00
|
|
|
|
2005-10-04 02:09:06 +00:00
|
|
|
m_TrackingRepeatingInput.MakeInvalid();
|
2005-10-04 01:40:58 +00:00
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
vector<PlayerNumber> vpns;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-14 21:51:22 +00:00
|
|
|
#define PLAYER_APPEND_WITH_SPACE(p) (SHARED_SELECTION ? CString() : ssprintf(" P%d",(p)+1))
|
|
|
|
|
#define PLAYER_APPEND_NO_SPACE(p) (SHARED_SELECTION ? CString() : ssprintf("P%d",(p)+1))
|
2005-06-29 09:22:24 +00:00
|
|
|
|
|
|
|
|
// init cursor
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_CURSOR )
|
2005-06-29 09:22:24 +00:00
|
|
|
{
|
|
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 20:15:37 +00:00
|
|
|
CString sElement = "Cursor" + PLAYER_APPEND_WITH_SPACE(*p);
|
|
|
|
|
m_sprCursor[*p].Load( THEME->GetPathG(m_sName,sElement) );
|
|
|
|
|
sElement.Replace( " ", "" );
|
|
|
|
|
m_sprCursor[*p]->SetName( sElement );
|
2005-07-14 08:47:12 +00:00
|
|
|
this->AddChild( m_sprCursor[*p] );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-02 06:29:20 +00:00
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 20:15:37 +00:00
|
|
|
GameCommand& mc = m_aGameCommands[c];
|
|
|
|
|
|
|
|
|
|
Lua *L = LUA->Get();
|
|
|
|
|
mc.PushSelf( L );
|
2005-08-15 07:48:16 +00:00
|
|
|
lua_setglobal( L, "ThisGameCommand" );
|
2005-07-14 20:15:37 +00:00
|
|
|
LUA->Release( L );
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2004-01-17 23:14:56 +00:00
|
|
|
// init icon
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_ICON )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 20:15:37 +00:00
|
|
|
CString sElement = ssprintf( "Icon Choice%s", mc.m_sName.c_str() );
|
|
|
|
|
m_sprIcon[c].Load( THEME->GetPathG(m_sName,sElement) );
|
|
|
|
|
sElement.Replace( " ", "" );
|
|
|
|
|
m_sprIcon[c]->SetName( sElement );
|
2005-07-14 08:47:12 +00:00
|
|
|
this->AddChild( m_sprIcon[c] );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-14 20:15:37 +00:00
|
|
|
// init scroll
|
|
|
|
|
if( SHOW_SCROLLER )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 20:15:37 +00:00
|
|
|
CString sElement = ssprintf( "Scroll Choice%s", mc.m_sName.c_str() ) + PLAYER_APPEND_WITH_SPACE(*p);
|
|
|
|
|
m_sprScroll[c][*p].Load( THEME->GetPathG(m_sName,sElement) );
|
|
|
|
|
sElement.Replace( " ", "" );
|
|
|
|
|
m_sprScroll[c][*p]->SetName( sElement );
|
|
|
|
|
m_Scroller[*p].AddChild( m_sprScroll[c][*p] );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
2005-09-03 04:50:49 +00:00
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
2005-07-14 20:15:37 +00:00
|
|
|
|
2005-08-15 07:48:16 +00:00
|
|
|
LUA->UnsetGlobal( "ThisGameCommand" );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-27 05:40:09 +00:00
|
|
|
// init scroll
|
|
|
|
|
if( SHOW_SCROLLER )
|
|
|
|
|
{
|
|
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
{
|
|
|
|
|
m_Scroller[*p].Load3(
|
|
|
|
|
SCROLLER_SECONDS_PER_ITEM,
|
|
|
|
|
SCROLLER_NUM_ITEMS_TO_DRAW,
|
|
|
|
|
SCROLLER_FAST_CATCHUP,
|
|
|
|
|
SCROLLER_TRANSFORM,
|
|
|
|
|
SCROLLER_SUBDIVISIONS,
|
|
|
|
|
false,
|
|
|
|
|
LOOP_SCROLLER );
|
|
|
|
|
m_Scroller[*p].SetName( "Scroller"+PLAYER_APPEND_NO_SPACE(*p) );
|
|
|
|
|
this->AddChild( &m_Scroller[*p] );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
for( int page=0; page<NUM_PAGES; page++ )
|
|
|
|
|
{
|
2005-02-06 03:32:53 +00:00
|
|
|
m_sprMore[page].Load( THEME->GetPathG(m_sName, ssprintf("more page%d",page+1)) );
|
2005-01-04 10:47:28 +00:00
|
|
|
m_sprMore[page]->SetName( ssprintf("MorePage%d",page+1) );
|
2005-08-25 23:07:42 +00:00
|
|
|
ActorUtil::LoadAllCommands( *m_sprMore[page], m_sName );
|
2005-01-04 10:47:28 +00:00
|
|
|
this->AddChild( m_sprMore[page] );
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-02-06 03:32:53 +00:00
|
|
|
m_sprExplanation[page].Load( THEME->GetPathG(m_sName, ssprintf("explanation page%d",page+1)) );
|
2003-11-05 19:35:57 +00:00
|
|
|
m_sprExplanation[page]->SetName( ssprintf("ExplanationPage%d",page+1) );
|
2005-08-25 23:07:42 +00:00
|
|
|
ActorUtil::LoadAllCommands( *m_sprExplanation[page], m_sName );
|
2003-11-05 19:35:57 +00:00
|
|
|
this->AddChild( m_sprExplanation[page] );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-06 03:32:53 +00:00
|
|
|
m_soundChange.Load( THEME->GetPathS(m_sName,"change"), true );
|
2003-06-20 23:07:45 +00:00
|
|
|
m_soundDifficult.Load( ANNOUNCER->GetPathTo("select difficulty challenge") );
|
2005-02-06 03:32:53 +00:00
|
|
|
m_soundStart.Load( THEME->GetPathS(m_sName,"start") );
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2004-01-17 23:14:56 +00:00
|
|
|
// init m_Next order info
|
2005-02-06 05:15:57 +00:00
|
|
|
FOREACH_MenuDir( dir )
|
2003-11-12 02:53:28 +00:00
|
|
|
{
|
2005-02-06 05:15:57 +00:00
|
|
|
const CString order = OPTION_ORDER.GetValue( dir );
|
2003-11-12 02:53:28 +00:00
|
|
|
vector<CString> parts;
|
|
|
|
|
split( order, ",", parts, true );
|
|
|
|
|
|
|
|
|
|
for( unsigned part = 0; part < parts.size(); ++part )
|
|
|
|
|
{
|
|
|
|
|
unsigned from, to;
|
2005-10-04 02:34:10 +00:00
|
|
|
if( sscanf( parts[part], "%d:%d", &from, &to ) != 2 )
|
2003-11-12 02:53:28 +00:00
|
|
|
{
|
2005-02-06 05:15:57 +00:00
|
|
|
LOG->Warn( "%s::OptionOrder%s parse error", m_sName.c_str(), MenuDirToString(dir).c_str() );
|
2003-11-12 02:53:28 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
--from;
|
|
|
|
|
--to;
|
|
|
|
|
|
2005-10-04 02:34:10 +00:00
|
|
|
m_mapCurrentChoiceToNextChoice[dir][from] = to;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( m_mapCurrentChoiceToNextChoice[dir].empty() ) // Didn't specify any mappings
|
|
|
|
|
{
|
|
|
|
|
// Fill with reasonable defaults
|
|
|
|
|
for( unsigned c = 0; c < m_aGameCommands.size(); ++c )
|
2003-11-12 02:53:28 +00:00
|
|
|
{
|
2005-10-04 02:34:10 +00:00
|
|
|
int add;
|
|
|
|
|
switch( dir )
|
|
|
|
|
{
|
|
|
|
|
case MENU_DIR_UP:
|
|
|
|
|
case MENU_DIR_LEFT:
|
|
|
|
|
add = -1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
add = +1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_mapCurrentChoiceToNextChoice[dir][c] = c + add;
|
|
|
|
|
/* Always wrap around MENU_DIR_AUTO. */
|
|
|
|
|
if( dir == MENU_DIR_AUTO || (bool)WRAP_CURSOR )
|
|
|
|
|
wrap( m_mapCurrentChoiceToNextChoice[dir][c], m_aGameCommands.size() );
|
|
|
|
|
else
|
|
|
|
|
m_mapCurrentChoiceToNextChoice[dir][c] = clamp( m_mapCurrentChoiceToNextChoice[dir][c], 0, (int)m_aGameCommands.size()-1 );
|
2003-11-12 02:53:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-09-21 17:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenSelectMaster::BeginScreen()
|
|
|
|
|
{
|
|
|
|
|
ScreenSelect::BeginScreen();
|
|
|
|
|
|
|
|
|
|
// TODO: Move default choice to ScreenSelect
|
|
|
|
|
int iDefaultChoice = -1;
|
|
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
|
|
|
|
{
|
|
|
|
|
const GameCommand& mc = m_aGameCommands[c];
|
|
|
|
|
if( mc.m_sName == (CString) DEFAULT_CHOICE )
|
|
|
|
|
{
|
|
|
|
|
iDefaultChoice = c;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
{
|
|
|
|
|
m_iChoice[p] = (iDefaultChoice!=-1) ? iDefaultChoice : 0;
|
|
|
|
|
CLAMP( m_iChoice[p], 0, (int)m_aGameCommands.size()-1 );
|
|
|
|
|
m_bChosen[p] = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vector<PlayerNumber> vpns;
|
|
|
|
|
if( SHARED_SELECTION )
|
|
|
|
|
{
|
|
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// position scroller items so that the items' will start from their resting
|
|
|
|
|
// position when they execute their OnCommand.
|
|
|
|
|
if( SHOW_SCROLLER )
|
|
|
|
|
{
|
|
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
m_Scroller[*p].PositionItems();
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-12 02:53:28 +00:00
|
|
|
|
2003-11-10 16:58:04 +00:00
|
|
|
this->UpdateSelectableChoices();
|
|
|
|
|
|
2005-07-14 22:23:39 +00:00
|
|
|
TweenOursOnScreen();
|
2005-03-02 04:35:12 +00:00
|
|
|
|
|
|
|
|
m_fLockInputSecs = (bool)OVERRIDE_LOCK_INPUT_SECONDS ? LOCK_INPUT_SECONDS : this->GetTweenTimeLeft();
|
2005-03-16 23:26:19 +00:00
|
|
|
if( m_fLockInputSecs == 0 )
|
|
|
|
|
m_fLockInputSecs = 0.0001f; // always lock for a tiny amount of time so that we throw away any queued inputs during the load.
|
|
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenSelectMaster::Update( float fDelta )
|
|
|
|
|
{
|
|
|
|
|
ScreenSelect::Update( fDelta );
|
|
|
|
|
m_fLockInputSecs = max( 0, m_fLockInputSecs-fDelta );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenSelectMaster::HandleScreenMessage( const ScreenMessage SM )
|
|
|
|
|
{
|
|
|
|
|
ScreenSelect::HandleScreenMessage( SM );
|
|
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
|
|
|
|
|
vector<PlayerNumber> vpns;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2005-06-29 09:22:24 +00:00
|
|
|
{
|
|
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-03-23 08:48:38 +00:00
|
|
|
if( SM == SM_PlayPostSwitchPage )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_CURSOR )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
m_sprCursor[*p]->SetXY( GetCursorX(*p), GetCursorY(*p) );
|
|
|
|
|
COMMAND( m_sprCursor[*p], "PostSwitchPage" );
|
2005-03-23 08:48:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-07-14 20:15:37 +00:00
|
|
|
if( SHOW_SCROLLER )
|
2004-02-01 03:14:37 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
{
|
|
|
|
|
int iChoice = m_iChoice[*p];
|
2005-07-14 20:15:37 +00:00
|
|
|
COMMAND( m_sprScroll[iChoice][*p], "PostSwitchPage" );
|
2005-06-29 09:22:24 +00:00
|
|
|
}
|
2004-02-01 03:14:37 +00:00
|
|
|
}
|
2005-06-29 09:22:24 +00:00
|
|
|
|
2005-03-23 08:48:38 +00:00
|
|
|
m_fLockInputSecs = POST_SWITCH_PAGE_SECONDS;
|
|
|
|
|
}
|
|
|
|
|
else if( SM == SM_BeginFadingOut )
|
|
|
|
|
{
|
2005-07-14 22:23:39 +00:00
|
|
|
TweenOursOffScreen();
|
2005-03-23 08:48:38 +00:00
|
|
|
/*
|
2005-07-14 22:23:39 +00:00
|
|
|
* We start our own tween-out (TweenOursOffScreen), wait some amount of time, then
|
2005-03-23 08:48:38 +00:00
|
|
|
* start the base tween (ScreenWithMenuElements, called from SM_AllDoneChoosing);
|
|
|
|
|
* we move on when that finishes. This is a pain to tweak, especially now
|
|
|
|
|
* that elements essentially owned by the derived class are starting to tween
|
|
|
|
|
* in the ScreenWithMenuElements tween (underlay, overlay); we have to tweak the
|
|
|
|
|
* duration of the "out" transition to determine how long to wait after fSecs
|
|
|
|
|
* before moving on.
|
|
|
|
|
*
|
|
|
|
|
* Send a command to all children, so we can run overlay and underlay tweens at the
|
2005-07-14 22:23:39 +00:00
|
|
|
* same time as the elements controlled by TweenOursOffScreen. Run this here, so
|
2005-03-23 08:48:38 +00:00
|
|
|
* it affects the result of GetTweenTimeLeft().
|
|
|
|
|
*/
|
|
|
|
|
this->PlayCommand( "TweenOff" );
|
|
|
|
|
|
|
|
|
|
float fSecs = 0;
|
|
|
|
|
/* This can be used to allow overlap between the main tween-off and the MenuElements
|
|
|
|
|
* tweenoff. */
|
|
|
|
|
if( OVERRIDE_SLEEP_AFTER_TWEEN_OFF_SECONDS )
|
|
|
|
|
fSecs = SLEEP_AFTER_TWEEN_OFF_SECONDS;
|
|
|
|
|
else
|
|
|
|
|
fSecs = GetTweenTimeLeft();
|
|
|
|
|
fSecs = max( fSecs, 0 );
|
|
|
|
|
|
|
|
|
|
SCREENMAN->PostMessageToTopScreen( SM_AllDoneChoosing, fSecs ); // nofify parent that we're finished
|
|
|
|
|
StopTimer();
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ScreenSelectMaster::GetSelectionIndex( PlayerNumber pn )
|
|
|
|
|
{
|
|
|
|
|
return m_iChoice[pn];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScreenSelectMaster::UpdateSelectableChoices()
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
vector<PlayerNumber> vpns;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2005-06-29 09:22:24 +00:00
|
|
|
{
|
|
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-02 06:29:20 +00:00
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
2005-05-08 03:59:40 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_ICON )
|
2005-07-14 20:15:37 +00:00
|
|
|
m_sprIcon[c]->PlayCommand( m_aGameCommands[c].IsPlayable()? "Enabled":"Disabled" );
|
2005-05-08 03:59:40 +00:00
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
if( m_sprScroll[c][*p].IsLoaded() )
|
|
|
|
|
m_sprScroll[c][*p]->PlayCommand( m_aGameCommands[c].IsPlayable()? "Enabled":"Disabled" );
|
2005-05-08 03:59:40 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-03-10 03:53:00 +00:00
|
|
|
/*
|
|
|
|
|
* If no options are playable at all, just wait. Some external
|
|
|
|
|
* stimulus may make options available (such as coin insertion).
|
|
|
|
|
*
|
|
|
|
|
* If any options are playable, make sure one is selected.
|
|
|
|
|
*/
|
2005-01-04 10:47:28 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
2004-12-02 06:29:20 +00:00
|
|
|
if( !m_aGameCommands[m_iChoice[p]].IsPlayable() )
|
2005-02-06 05:15:57 +00:00
|
|
|
Move( p, MENU_DIR_AUTO );
|
2005-03-10 03:53:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ScreenSelectMaster::AnyOptionsArePlayable() const
|
|
|
|
|
{
|
2005-03-10 07:56:41 +00:00
|
|
|
for( unsigned i = 0; i < m_aGameCommands.size(); ++i )
|
|
|
|
|
if( m_aGameCommands[i].IsPlayable() )
|
2005-03-10 03:53:00 +00:00
|
|
|
return true;
|
2005-03-10 07:56:41 +00:00
|
|
|
|
2005-03-10 03:53:00 +00:00
|
|
|
return false;
|
2003-11-10 16:58:04 +00:00
|
|
|
}
|
|
|
|
|
|
2005-02-06 05:15:57 +00:00
|
|
|
bool ScreenSelectMaster::Move( PlayerNumber pn, MenuDir dir )
|
2003-11-10 16:58:04 +00:00
|
|
|
{
|
2005-03-10 03:53:00 +00:00
|
|
|
if( !AnyOptionsArePlayable() )
|
|
|
|
|
return false;
|
|
|
|
|
|
2003-11-10 16:58:04 +00:00
|
|
|
int iSwitchToIndex = m_iChoice[pn];
|
2004-04-13 23:11:32 +00:00
|
|
|
set<int> seen;
|
2005-05-08 03:59:40 +00:00
|
|
|
try_again:
|
2005-10-04 02:34:10 +00:00
|
|
|
map<int,int>::const_iterator iter = m_mapCurrentChoiceToNextChoice[dir].find( iSwitchToIndex );
|
|
|
|
|
if( iter != m_mapCurrentChoiceToNextChoice[dir].end() )
|
|
|
|
|
iSwitchToIndex = iter->second;
|
|
|
|
|
|
|
|
|
|
if( iSwitchToIndex < 0 || iSwitchToIndex >= m_aGameCommands.size() ) // out of choice range
|
2005-05-08 03:59:40 +00:00
|
|
|
return false; // can't go that way
|
|
|
|
|
if( seen.find(iSwitchToIndex) != seen.end() )
|
|
|
|
|
return false; // went full circle and none found
|
|
|
|
|
seen.insert( iSwitchToIndex );
|
|
|
|
|
|
|
|
|
|
if( !m_aGameCommands[iSwitchToIndex].IsPlayable() )
|
|
|
|
|
goto try_again;
|
2003-11-10 16:58:04 +00:00
|
|
|
|
2005-05-03 23:12:29 +00:00
|
|
|
return ChangeSelection( pn, dir, iSwitchToIndex );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-23 00:44:52 +00:00
|
|
|
void ScreenSelectMaster::MenuLeft( const InputEventPlus &input )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-09-23 00:44:52 +00:00
|
|
|
PlayerNumber pn = input.MenuI.player;
|
2003-11-12 02:53:28 +00:00
|
|
|
if( m_fLockInputSecs > 0 || m_bChosen[pn] )
|
2003-06-20 23:07:45 +00:00
|
|
|
return;
|
2005-09-23 00:44:52 +00:00
|
|
|
if( input.type == IET_RELEASE )
|
2005-04-04 02:34:56 +00:00
|
|
|
return;
|
2005-10-04 02:09:06 +00:00
|
|
|
if( input.type != IET_FIRST_PRESS )
|
|
|
|
|
{
|
|
|
|
|
if( !ALLOW_REPEATING_INPUT )
|
|
|
|
|
return;
|
|
|
|
|
if( m_TrackingRepeatingInput != input.MenuI )
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-02-06 05:15:57 +00:00
|
|
|
if( Move(pn, MENU_DIR_LEFT) )
|
2005-05-02 21:33:02 +00:00
|
|
|
{
|
2005-10-04 02:09:06 +00:00
|
|
|
m_TrackingRepeatingInput = input.MenuI;
|
2003-11-10 16:58:04 +00:00
|
|
|
m_soundChange.Play();
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_MenuLeftP1+pn) );
|
2005-05-02 21:33:02 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-23 00:44:52 +00:00
|
|
|
void ScreenSelectMaster::MenuRight( const InputEventPlus &input )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-09-23 00:44:52 +00:00
|
|
|
PlayerNumber pn = input.MenuI.player;
|
2003-11-12 02:53:28 +00:00
|
|
|
if( m_fLockInputSecs > 0 || m_bChosen[pn] )
|
|
|
|
|
return;
|
2005-09-23 00:44:52 +00:00
|
|
|
if( input.type == IET_RELEASE )
|
2005-04-04 02:34:56 +00:00
|
|
|
return;
|
2005-10-04 02:09:06 +00:00
|
|
|
if( input.type != IET_FIRST_PRESS )
|
|
|
|
|
{
|
|
|
|
|
if( !ALLOW_REPEATING_INPUT )
|
|
|
|
|
return;
|
|
|
|
|
if( m_TrackingRepeatingInput != input.MenuI )
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-02-06 05:15:57 +00:00
|
|
|
if( Move(pn, MENU_DIR_RIGHT) )
|
2005-05-02 21:33:02 +00:00
|
|
|
{
|
2005-10-04 02:09:06 +00:00
|
|
|
m_TrackingRepeatingInput = input.MenuI;
|
2003-11-12 02:53:28 +00:00
|
|
|
m_soundChange.Play();
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_MenuRightP1+pn) );
|
2005-05-02 21:33:02 +00:00
|
|
|
}
|
2003-11-12 02:53:28 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-23 00:44:52 +00:00
|
|
|
void ScreenSelectMaster::MenuUp( const InputEventPlus &input )
|
2003-11-12 02:53:28 +00:00
|
|
|
{
|
2005-09-23 00:44:52 +00:00
|
|
|
PlayerNumber pn = input.MenuI.player;
|
2003-11-12 02:53:28 +00:00
|
|
|
if( m_fLockInputSecs > 0 || m_bChosen[pn] )
|
2003-06-20 23:07:45 +00:00
|
|
|
return;
|
2005-09-23 00:44:52 +00:00
|
|
|
if( input.type == IET_RELEASE )
|
2005-04-04 02:34:56 +00:00
|
|
|
return;
|
2005-10-04 02:09:06 +00:00
|
|
|
if( input.type != IET_FIRST_PRESS )
|
|
|
|
|
{
|
|
|
|
|
if( !ALLOW_REPEATING_INPUT )
|
|
|
|
|
return;
|
|
|
|
|
if( m_TrackingRepeatingInput != input.MenuI )
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-02-06 05:15:57 +00:00
|
|
|
if( Move(pn, MENU_DIR_UP) )
|
2005-05-02 21:33:02 +00:00
|
|
|
{
|
2005-10-04 02:09:06 +00:00
|
|
|
m_TrackingRepeatingInput = input.MenuI;
|
2003-11-12 02:53:28 +00:00
|
|
|
m_soundChange.Play();
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_MenuUpP1+pn) );
|
2005-05-02 21:33:02 +00:00
|
|
|
}
|
2003-11-12 02:53:28 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-23 00:44:52 +00:00
|
|
|
void ScreenSelectMaster::MenuDown( const InputEventPlus &input )
|
2003-11-12 02:53:28 +00:00
|
|
|
{
|
2005-09-23 00:44:52 +00:00
|
|
|
PlayerNumber pn = input.MenuI.player;
|
2003-11-12 02:53:28 +00:00
|
|
|
if( m_fLockInputSecs > 0 || m_bChosen[pn] )
|
2003-06-20 23:07:45 +00:00
|
|
|
return;
|
2005-09-23 00:44:52 +00:00
|
|
|
if( input.type == IET_RELEASE )
|
2005-04-04 02:34:56 +00:00
|
|
|
return;
|
2005-10-04 02:09:06 +00:00
|
|
|
if( input.type != IET_FIRST_PRESS )
|
|
|
|
|
{
|
|
|
|
|
if( !ALLOW_REPEATING_INPUT )
|
|
|
|
|
return;
|
|
|
|
|
if( m_TrackingRepeatingInput != input.MenuI )
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-02-06 05:15:57 +00:00
|
|
|
if( Move(pn, MENU_DIR_DOWN) )
|
2005-05-02 21:33:02 +00:00
|
|
|
{
|
2005-10-04 02:09:06 +00:00
|
|
|
m_TrackingRepeatingInput = input.MenuI;
|
2003-11-10 16:58:04 +00:00
|
|
|
m_soundChange.Play();
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_MenuDownP1+pn) );
|
2005-05-02 21:33:02 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-10 16:58:04 +00:00
|
|
|
bool ScreenSelectMaster::ChangePage( int iNewChoice )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2003-11-10 16:58:04 +00:00
|
|
|
Page newPage = GetPage(iNewChoice);
|
|
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
// If anyone has already chosen, don't allow changing of pages
|
2004-05-24 08:16:17 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2005-06-29 09:22:24 +00:00
|
|
|
{
|
2003-06-20 23:07:45 +00:00
|
|
|
if( GAMESTATE->IsHumanPlayer(p) && m_bChosen[p] )
|
2003-11-10 16:58:04 +00:00
|
|
|
return false;
|
2005-06-29 09:22:24 +00:00
|
|
|
}
|
|
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
vector<PlayerNumber> vpns;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_CURSOR )
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
if( GAMESTATE->IsHumanPlayer(*p) )
|
2005-07-14 08:47:12 +00:00
|
|
|
COMMAND( m_sprCursor[*p], "PreSwitchPage" );
|
|
|
|
|
}
|
2005-06-29 09:22:24 +00:00
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
const CString sIconAndExplanationCommand = ssprintf( "SwitchToPage%d", newPage+1 );
|
|
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_ICON )
|
|
|
|
|
{
|
|
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
|
|
|
|
COMMAND( m_sprIcon[c], sIconAndExplanationCommand );
|
|
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-07-14 20:15:37 +00:00
|
|
|
if( SHOW_SCROLLER )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2005-07-14 08:47:12 +00:00
|
|
|
{
|
|
|
|
|
int iChoice = m_iChoice[GetSharedPlayer()];
|
2005-07-14 20:15:37 +00:00
|
|
|
COMMAND( m_sprScroll[iChoice][0], "PreSwitchPage" );
|
2005-07-14 08:47:12 +00:00
|
|
|
}
|
2005-07-14 20:15:37 +00:00
|
|
|
else
|
2005-07-14 08:47:12 +00:00
|
|
|
{
|
2004-05-24 08:16:17 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
{
|
|
|
|
|
int iChoice = m_iChoice[p];
|
2005-07-14 20:15:37 +00:00
|
|
|
COMMAND( m_sprScroll[iChoice][p], "PreSwitchPage" );
|
2004-05-24 08:16:17 +00:00
|
|
|
}
|
2005-07-14 08:47:12 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for( int page=0; page<NUM_PAGES; page++ )
|
|
|
|
|
{
|
2004-02-01 03:14:37 +00:00
|
|
|
COMMAND( m_sprExplanation[page], sIconAndExplanationCommand );
|
|
|
|
|
COMMAND( m_sprMore[page], sIconAndExplanationCommand );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( newPage == PAGE_2 )
|
|
|
|
|
{
|
|
|
|
|
// XXX: only play this once (I thought we already did that?)
|
|
|
|
|
// DDR plays it on every change to page 2. -Chris
|
2003-11-04 20:57:19 +00:00
|
|
|
/* That sounds ugly if you go back and forth quickly. -g */
|
2004-01-17 23:14:56 +00:00
|
|
|
// DDR locks input while it's scrolling. Should we do the same? -Chris
|
2003-06-20 23:07:45 +00:00
|
|
|
m_soundDifficult.Stop();
|
|
|
|
|
m_soundDifficult.PlayRandom();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// change both players
|
2004-05-24 08:16:17 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-06-20 23:07:45 +00:00
|
|
|
m_iChoice[p] = iNewChoice;
|
|
|
|
|
|
|
|
|
|
m_fLockInputSecs = PRE_SWITCH_PAGE_SECONDS;
|
|
|
|
|
this->PostScreenMessage( SM_PlayPostSwitchPage, PRE_SWITCH_PAGE_SECONDS );
|
2003-11-10 16:58:04 +00:00
|
|
|
return true;
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-05-03 23:12:29 +00:00
|
|
|
bool ScreenSelectMaster::ChangeSelection( PlayerNumber pn, MenuDir dir, int iNewChoice )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2004-04-13 23:11:32 +00:00
|
|
|
if( iNewChoice == m_iChoice[pn] )
|
|
|
|
|
return false; // already there
|
|
|
|
|
|
2003-11-10 16:58:04 +00:00
|
|
|
if( GetPage(m_iChoice[pn]) != GetPage(iNewChoice) )
|
|
|
|
|
return ChangePage( iNewChoice );
|
|
|
|
|
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2004-04-25 22:37:54 +00:00
|
|
|
const int iOldChoice = m_iChoice[p];
|
|
|
|
|
|
2004-01-21 02:11:23 +00:00
|
|
|
/* Set the new m_iChoice even for disabled players, since a player might
|
2005-07-14 21:51:22 +00:00
|
|
|
* join on a SHARED_SELECTION after the cursor has been moved. */
|
2004-01-21 02:11:23 +00:00
|
|
|
m_iChoice[p] = iNewChoice;
|
|
|
|
|
|
2005-01-04 10:51:25 +00:00
|
|
|
if( p!=pn )
|
2003-06-20 23:07:45 +00:00
|
|
|
continue; // skip
|
|
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_ICON )
|
2003-11-05 04:09:10 +00:00
|
|
|
{
|
2003-11-05 18:49:57 +00:00
|
|
|
/* XXX: If !SharedPreviewAndCursor, this is incorrect. (Nothing uses
|
|
|
|
|
* both icon focus and !SharedPreviewAndCursor right now.) */
|
2005-07-14 20:15:37 +00:00
|
|
|
m_sprIcon[iOldChoice]->PlayCommand( "LoseFocus" );
|
|
|
|
|
m_sprIcon[iNewChoice]->PlayCommand( "GainFocus" );
|
2003-11-05 04:09:10 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-14 20:15:37 +00:00
|
|
|
if( SHOW_CURSOR )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
COMMAND( m_sprCursor[0], "Change" );
|
|
|
|
|
m_sprCursor[0]->SetXY( GetCursorX((PlayerNumber)0), GetCursorY((PlayerNumber)0) );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
2005-07-14 08:47:12 +00:00
|
|
|
else
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
COMMAND( m_sprCursor[p], "Change" );
|
|
|
|
|
m_sprCursor[p]->SetXY( GetCursorX(p), GetCursorY(p) );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-01-17 23:14:56 +00:00
|
|
|
|
|
|
|
|
if( SHOW_SCROLLER )
|
|
|
|
|
{
|
2005-05-03 23:12:29 +00:00
|
|
|
if( WRAP_SCROLLER )
|
|
|
|
|
{
|
|
|
|
|
// HACK: We can't tell from the option orders whether or not we wrapped.
|
|
|
|
|
// For now, assume that the order is increasing left to right.
|
|
|
|
|
int iPressedDir = (dir == MENU_DIR_LEFT) ? -1 : +1;
|
|
|
|
|
int iActualDir = (iOldChoice < iNewChoice) ? +1 : -1;
|
|
|
|
|
|
|
|
|
|
if( iPressedDir != iActualDir ) // wrapped
|
|
|
|
|
{
|
2005-07-14 21:51:22 +00:00
|
|
|
ActorScroller &scroller = SHARED_SELECTION ? m_Scroller[0] : m_Scroller[p];
|
2005-05-03 23:12:29 +00:00
|
|
|
float fItem = scroller.GetCurrentItem();
|
|
|
|
|
int iNumChoices = m_aGameCommands.size();
|
|
|
|
|
fItem += iActualDir * iNumChoices;
|
|
|
|
|
scroller.SetCurrentAndDestinationItem( fItem );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2005-03-31 12:57:21 +00:00
|
|
|
m_Scroller[0].SetDestinationItem( (float)iNewChoice );
|
2004-01-17 23:14:56 +00:00
|
|
|
else
|
2005-03-31 12:57:21 +00:00
|
|
|
m_Scroller[p].SetDestinationItem( (float)iNewChoice );
|
2005-07-14 20:15:37 +00:00
|
|
|
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2005-07-14 20:15:37 +00:00
|
|
|
{
|
|
|
|
|
m_sprScroll[iOldChoice][0]->PlayCommand( "LoseFocus" );
|
|
|
|
|
m_sprScroll[iNewChoice][0]->PlayCommand( "GainFocus" );
|
|
|
|
|
}
|
2004-01-17 23:14:56 +00:00
|
|
|
else
|
2005-07-14 20:15:37 +00:00
|
|
|
{
|
|
|
|
|
m_sprScroll[iOldChoice][p]->PlayCommand( "LoseFocus" );
|
|
|
|
|
m_sprScroll[iNewChoice][p]->PlayCommand( "GainFocus" );
|
|
|
|
|
}
|
2004-01-17 23:14:56 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-17 23:14:56 +00:00
|
|
|
|
2003-11-10 16:58:04 +00:00
|
|
|
return true;
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-06-23 01:21:13 +00:00
|
|
|
PlayerNumber ScreenSelectMaster::GetSharedPlayer()
|
|
|
|
|
{
|
|
|
|
|
if( GAMESTATE->m_MasterPlayerNumber != PLAYER_INVALID )
|
|
|
|
|
return GAMESTATE->m_MasterPlayerNumber;
|
|
|
|
|
|
|
|
|
|
return PLAYER_1;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-10 21:18:26 +00:00
|
|
|
ScreenSelectMaster::Page ScreenSelectMaster::GetPage( int iChoiceIndex ) const
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2003-11-10 21:18:26 +00:00
|
|
|
return iChoiceIndex < NUM_CHOICES_ON_PAGE_1? PAGE_1:PAGE_2;
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-10 21:18:26 +00:00
|
|
|
ScreenSelectMaster::Page ScreenSelectMaster::GetCurrentPage() const
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
|
|
|
|
// Both players are guaranteed to be on the same page.
|
2005-06-23 01:21:13 +00:00
|
|
|
return GetPage( m_iChoice[GetSharedPlayer()] );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-02-01 05:03:45 +00:00
|
|
|
float ScreenSelectMaster::DoMenuStart( PlayerNumber pn )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2004-09-06 21:28:56 +00:00
|
|
|
if( m_bChosen[pn] )
|
2004-02-01 05:03:45 +00:00
|
|
|
return 0;
|
2005-02-02 06:12:24 +00:00
|
|
|
|
|
|
|
|
bool bAnyChosen = false;
|
|
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
bAnyChosen |= m_bChosen[p];
|
|
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
m_bChosen[pn] = true;
|
|
|
|
|
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_MadeChoiceP1+pn) );
|
2005-05-04 09:58:12 +00:00
|
|
|
|
2005-02-02 06:12:24 +00:00
|
|
|
bool bIsFirstToChoose = bAnyChosen;
|
|
|
|
|
|
2004-02-01 05:03:45 +00:00
|
|
|
float fSecs = 0;
|
|
|
|
|
|
2005-02-02 06:12:24 +00:00
|
|
|
if( bIsFirstToChoose )
|
2004-02-01 05:03:45 +00:00
|
|
|
{
|
2005-02-02 06:12:24 +00:00
|
|
|
for( int page=0; page<NUM_PAGES; page++ )
|
|
|
|
|
{
|
|
|
|
|
OFF_COMMAND( m_sprMore[page] );
|
|
|
|
|
fSecs = max( fSecs, m_sprMore[page]->GetTweenTimeLeft() );
|
|
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-07-14 21:51:22 +00:00
|
|
|
int iIndex = SHARED_SELECTION ? 0 : pn;
|
2005-02-02 06:12:24 +00:00
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_CURSOR )
|
2005-02-02 06:12:24 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
COMMAND( m_sprCursor[pn], "Choose");
|
|
|
|
|
fSecs = max( fSecs, m_sprCursor[iIndex]->GetTweenTimeLeft() );
|
2005-02-02 06:12:24 +00:00
|
|
|
}
|
2004-02-01 05:03:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fSecs;
|
2003-11-10 18:57:29 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2003-11-10 18:57:29 +00:00
|
|
|
void ScreenSelectMaster::MenuStart( PlayerNumber pn )
|
|
|
|
|
{
|
2005-02-02 06:12:24 +00:00
|
|
|
// If the player isn't already joined, try to join them.
|
|
|
|
|
// Allow a player to join even if input is locked or someone has already already chosen.
|
|
|
|
|
MenuInput MenuI;
|
|
|
|
|
MenuI.player = pn;
|
|
|
|
|
MenuI.button = MENU_BUTTON_START;
|
|
|
|
|
Screen::JoinInput( MenuI );
|
|
|
|
|
|
2003-11-10 18:57:29 +00:00
|
|
|
if( m_fLockInputSecs > 0 )
|
|
|
|
|
return;
|
2004-09-06 21:28:56 +00:00
|
|
|
if( m_bChosen[pn] )
|
2003-11-10 21:18:26 +00:00
|
|
|
return;
|
2003-11-10 18:57:29 +00:00
|
|
|
|
2005-07-13 19:22:23 +00:00
|
|
|
if( !ProcessMenuStart( pn ) )
|
|
|
|
|
return;
|
|
|
|
|
|
2005-07-25 04:47:51 +00:00
|
|
|
const GameCommand &mc = m_aGameCommands[m_iChoice[pn]];
|
2005-03-10 03:53:00 +00:00
|
|
|
|
|
|
|
|
/* If no options are playable, then we're just waiting for one to become available.
|
|
|
|
|
* If any options are playable, then the selection must be playable. */
|
|
|
|
|
if( !AnyOptionsArePlayable() )
|
|
|
|
|
return;
|
|
|
|
|
|
2004-02-13 05:10:18 +00:00
|
|
|
SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo(ssprintf("%s comment %s",m_sName.c_str(), mc.m_sName.c_str())) );
|
2005-01-08 09:50:59 +00:00
|
|
|
|
2005-01-08 16:59:59 +00:00
|
|
|
/* Play a copy of the sound, so it'll finish playing even if we leave the screen immediately. */
|
2005-01-08 09:50:59 +00:00
|
|
|
if( mc.m_sSoundPath.empty() )
|
2005-01-08 16:59:59 +00:00
|
|
|
SOUNDMAN->PlayCopyOfSound( m_soundStart );
|
2005-01-08 09:50:59 +00:00
|
|
|
|
|
|
|
|
if( mc.m_sScreen.empty() )
|
|
|
|
|
{
|
|
|
|
|
mc.ApplyToAllPlayers();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-07-25 04:47:51 +00:00
|
|
|
|
2004-02-01 05:03:45 +00:00
|
|
|
float fSecs = 0;
|
2003-11-10 18:57:29 +00:00
|
|
|
bool bAllDone = true;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( (bool)SHARED_SELECTION || GetCurrentPage() == PAGE_2 )
|
2003-11-05 18:49:57 +00:00
|
|
|
{
|
2003-11-10 18:57:29 +00:00
|
|
|
/* Only one player has to pick. Choose this for all the other players, too. */
|
2005-02-02 06:12:24 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2004-07-28 16:05:39 +00:00
|
|
|
{
|
2005-02-02 06:12:24 +00:00
|
|
|
ASSERT( !m_bChosen[p] );
|
|
|
|
|
fSecs = max( fSecs, DoMenuStart(p) ); // no harm in calling this for an unjoined player
|
2004-07-28 16:05:39 +00:00
|
|
|
}
|
2004-02-01 03:14:37 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2004-02-01 05:03:45 +00:00
|
|
|
fSecs = max( fSecs, DoMenuStart(pn) );
|
2003-11-05 18:49:57 +00:00
|
|
|
// check to see if everyone has chosen
|
2004-07-28 16:05:39 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
bAllDone &= m_bChosen[p];
|
2003-11-05 18:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
2003-06-20 23:07:45 +00:00
|
|
|
if( bAllDone )
|
2004-02-01 05:03:45 +00:00
|
|
|
this->PostScreenMessage( SM_BeginFadingOut, fSecs );// tell our owner it's time to move on
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-05 18:49:57 +00:00
|
|
|
/*
|
|
|
|
|
* We want all items to always run OnCommand and either GainFocus or LoseFocus on
|
|
|
|
|
* tween-in. If we only run OnCommand, then it has to contain a copy of either
|
|
|
|
|
* GainFocus or LoseFocus, which implies that the default setting is hard-coded in
|
|
|
|
|
* the theme. Always run both.
|
|
|
|
|
*
|
|
|
|
|
* However, the actual tween-in is OnCommand; we don't always want to actually run
|
|
|
|
|
* through the Gain/LoseFocus tweens during initial tween-in. So, we run the focus
|
|
|
|
|
* command first, do a FinishTweening to pop it in place, and then run OnCommand.
|
|
|
|
|
* This means that the focus command should be position neutral; eg. only use "addx",
|
|
|
|
|
* not "x".
|
|
|
|
|
*/
|
2005-07-14 22:23:39 +00:00
|
|
|
void ScreenSelectMaster::TweenOursOnScreen()
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
vector<PlayerNumber> vpns;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2005-06-29 09:22:24 +00:00
|
|
|
{
|
|
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-15 01:51:05 +00:00
|
|
|
if( SHOW_ICON )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-07-14 20:15:37 +00:00
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
2003-11-05 04:09:10 +00:00
|
|
|
{
|
2005-07-14 20:15:37 +00:00
|
|
|
m_sprIcon[c]->PlayCommand( (int(c) == m_iChoice[0])? "GainFocus":"LoseFocus" );
|
2005-07-14 08:47:12 +00:00
|
|
|
m_sprIcon[c]->FinishTweening();
|
|
|
|
|
SET_XY_AND_ON_COMMAND( m_sprIcon[c] );
|
2003-11-05 04:09:10 +00:00
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-17 23:14:56 +00:00
|
|
|
if( SHOW_SCROLLER )
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2004-01-17 23:14:56 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
// Play Gain/LoseFocus before playing the on command. Gain/Lose will
|
|
|
|
|
// often stop tweening, which ruins the OnCommand.
|
2004-12-02 06:29:20 +00:00
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
2005-07-14 20:15:37 +00:00
|
|
|
{
|
|
|
|
|
m_sprScroll[c][*p]->PlayCommand( int(c) == m_iChoice[*p]? "GainFocus":"LoseFocus" );
|
|
|
|
|
m_sprScroll[c][*p]->FinishTweening();
|
|
|
|
|
ON_COMMAND( m_sprScroll[c][*p] );
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
m_Scroller[*p].SetCurrentAndDestinationItem( (float)m_iChoice[*p] );
|
|
|
|
|
SET_XY_AND_ON_COMMAND( m_Scroller[*p] );
|
2004-01-17 23:14:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2005-07-15 01:51:05 +00:00
|
|
|
// Need to SetXY of Cursor after Icons since it depends on the Icons' positions.
|
|
|
|
|
if( SHOW_CURSOR )
|
|
|
|
|
{
|
|
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
{
|
|
|
|
|
m_sprCursor[*p]->SetXY( GetCursorX(*p), GetCursorY(*p) );
|
|
|
|
|
ON_COMMAND( m_sprCursor[*p] );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-18 07:23:43 +00:00
|
|
|
//We have to move page two's explanation and more off the screen
|
|
|
|
|
//so it doesn't just sit there on page one. (Thanks Zhek)
|
|
|
|
|
|
|
|
|
|
for (int page=0;page<NUM_PAGES;page++)
|
|
|
|
|
{
|
2005-01-04 10:47:28 +00:00
|
|
|
m_sprMore[page]->SetXY(999,999);
|
2004-07-18 07:23:43 +00:00
|
|
|
m_sprExplanation[page]->SetXY(999,999);
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-01 03:14:37 +00:00
|
|
|
SET_XY_AND_ON_COMMAND( m_sprExplanation[GetCurrentPage()] );
|
|
|
|
|
SET_XY_AND_ON_COMMAND( m_sprMore[GetCurrentPage()] );
|
2003-06-20 23:07:45 +00:00
|
|
|
|
2004-05-02 03:01:27 +00:00
|
|
|
this->SortByDrawOrder();
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-14 22:23:39 +00:00
|
|
|
void ScreenSelectMaster::TweenOursOffScreen()
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
vector<PlayerNumber> vpns;
|
2005-07-14 21:51:22 +00:00
|
|
|
if( SHARED_SELECTION )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
vpns.push_back( (PlayerNumber)0 );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
vpns.push_back( p );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-06-29 09:22:24 +00:00
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_CURSOR )
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2005-07-14 08:47:12 +00:00
|
|
|
OFF_COMMAND( m_sprCursor[*p] );
|
|
|
|
|
}
|
2005-06-29 09:22:24 +00:00
|
|
|
|
2004-12-02 06:29:20 +00:00
|
|
|
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
|
|
|
|
if( GetPage(c) != GetCurrentPage() )
|
|
|
|
|
continue; // skip
|
|
|
|
|
|
2003-11-05 21:34:14 +00:00
|
|
|
bool SelectedByEitherPlayer = false;
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2003-11-24 03:59:09 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
if( m_iChoice[*p] == (int)c )
|
2003-11-05 21:34:14 +00:00
|
|
|
SelectedByEitherPlayer = true;
|
2003-11-24 03:59:09 +00:00
|
|
|
}
|
2003-11-05 21:34:14 +00:00
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
if( SHOW_ICON )
|
2003-11-05 18:49:57 +00:00
|
|
|
{
|
2005-07-14 08:47:12 +00:00
|
|
|
OFF_COMMAND( m_sprIcon[c] );
|
2005-07-14 20:15:37 +00:00
|
|
|
m_sprIcon[c]->PlayCommand( SelectedByEitherPlayer? "OffFocused":"OffUnfocused" );
|
2003-11-05 18:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-14 20:15:37 +00:00
|
|
|
if( SHOW_SCROLLER )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
2005-07-14 20:15:37 +00:00
|
|
|
COMMAND( m_sprScroll[c][*p], SelectedByEitherPlayer? "OffFocused":"OffUnfocused" );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-17 23:14:56 +00:00
|
|
|
if( SHOW_SCROLLER )
|
|
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
FOREACH( PlayerNumber, vpns, p )
|
|
|
|
|
OFF_COMMAND( m_Scroller[*p] );
|
2004-01-17 23:14:56 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-01 03:14:37 +00:00
|
|
|
OFF_COMMAND( m_sprExplanation[GetCurrentPage()] );
|
|
|
|
|
OFF_COMMAND( m_sprMore[GetCurrentPage()] );
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
float ScreenSelectMaster::GetCursorX( PlayerNumber pn )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
int iChoice = m_iChoice[pn];
|
2005-07-15 01:51:05 +00:00
|
|
|
AutoActor spr = m_sprIcon[iChoice];
|
|
|
|
|
return spr->GetX() + CURSOR_OFFSET_X_FROM_ICON.GetValue(pn);
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-14 08:47:12 +00:00
|
|
|
float ScreenSelectMaster::GetCursorY( PlayerNumber pn )
|
2003-06-20 23:07:45 +00:00
|
|
|
{
|
2005-06-29 09:22:24 +00:00
|
|
|
int iChoice = m_iChoice[pn];
|
2005-07-15 01:51:05 +00:00
|
|
|
AutoActor &spr = m_sprIcon[iChoice];
|
|
|
|
|
return spr->GetY() + CURSOR_OFFSET_Y_FROM_ICON.GetValue(pn);
|
2003-06-20 23:07:45 +00:00
|
|
|
}
|
2004-06-08 05:22:33 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* (c) 2003-2004 Chris Danford
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|