Files
itgmania212121/stepmania/src/ScreenNameEntryTraditional.cpp
T

786 lines
24 KiB
C++
Raw Normal View History

2003-10-14 09:51:16 +00:00
#include "global.h"
#include "ScreenNameEntryTraditional.h"
#include "SongManager.h"
#include "GameConstantsAndTypes.h"
#include "RageUtil.h"
#include "PrefsManager.h"
#include "GameManager.h"
#include "RageLog.h"
#include "GameState.h"
2004-07-08 00:10:34 +00:00
#include "GameSoundManager.h"
2003-10-14 09:51:16 +00:00
#include "ThemeManager.h"
#include "Course.h"
#include "ActorUtil.h"
2003-10-15 21:09:22 +00:00
#include "FontCharAliases.h"
2003-11-01 07:25:22 +00:00
#include "AnnouncerManager.h"
2003-11-07 20:24:44 +00:00
#include "song.h"
2003-12-18 03:40:57 +00:00
#include "Steps.h"
#include "ProfileManager.h"
2005-07-01 05:07:22 +00:00
#include "Profile.h"
2005-02-16 03:25:45 +00:00
#include "StatsManager.h"
#include "Foreach.h"
#include "Style.h"
#include "ScreenDimensions.h"
#include "InputEventPlus.h"
2006-06-10 06:50:50 +00:00
#include "RageInput.h"
2003-10-14 09:51:16 +00:00
//
// Defines specific to ScreenNameEntryTraditional
//
2003-10-15 04:29:06 +00:00
#define COMMAND_OPTIONAL( actor, command_name ) \
if( !(actor).GetName().empty() ) \
COMMAND( (actor), command_name );
2003-10-14 09:51:16 +00:00
AutoScreenMessage( SM_ChangeDisplayedFeat )
2003-10-15 04:29:06 +00:00
2003-10-14 09:51:16 +00:00
static const int CHAR_OK = -1;
2003-10-15 21:23:23 +00:00
static const int CHAR_BACK = -2;
2003-10-14 09:51:16 +00:00
void HighScoreWheelItem::Load( int iRankIndex, const HighScore& hs )
{
SetName( "HighScoreWheelItem" );
m_textRank.SetName( "Rank" );
m_textRank.LoadFromFont( THEME->GetPathF(m_sName,"rank") );
m_textRank.SetText( ssprintf("%d", iRankIndex+1) );
2004-03-17 06:01:17 +00:00
m_textRank.SetShadowLength( 2 );
this->AddChild( &m_textRank );
SET_XY_AND_ON_COMMAND( m_textRank );
m_textName.SetName( "Name" );
m_textName.LoadFromFont( THEME->GetPathF(m_sName,"name") );
2004-03-08 02:50:46 +00:00
m_textName.SetText( hs.GetDisplayName() );
2004-03-17 06:01:17 +00:00
m_textName.SetShadowLength( 2 );
this->AddChild( &m_textName );
SET_XY_AND_ON_COMMAND( m_textName );
m_textScore.SetName( "Score" );
m_textScore.LoadFromFont( THEME->GetPathF(m_sName,"score") );
if( PREFSMAN->m_bPercentageScoring )
2005-08-12 02:46:58 +00:00
m_textScore.SetText( PercentageDisplay::FormatPercentScore(hs.GetPercentDP()) );
else
2005-08-12 02:37:04 +00:00
m_textScore.SetText( ssprintf("%i", hs.GetScore()) );
2004-03-17 06:01:17 +00:00
m_textScore.SetShadowLength( 2 );
this->AddChild( &m_textScore );
SET_XY_AND_ON_COMMAND( m_textScore );
2005-04-29 07:11:20 +00:00
m_textDate.SetName( "Date" );
m_textDate.LoadFromFont( THEME->GetPathF(m_sName,"date") );
2005-08-12 02:55:48 +00:00
m_textDate.SetText( ssprintf("%02d/%02d", hs.GetDateTime().tm_mon+1, hs.GetDateTime().tm_mday) );
2005-04-29 07:11:20 +00:00
m_textDate.SetShadowLength( 2 );
this->AddChild( &m_textDate );
SET_XY_AND_ON_COMMAND( m_textDate );
}
2004-03-08 02:50:46 +00:00
void HighScoreWheelItem::LoadBlank( int iRankIndex )
{
HighScore hs;
Load( iRankIndex, hs );
}
void HighScoreWheelItem::ShowFocus()
{
apActorCommands c = ActorUtil::ParseActorCommands( "diffuseshift;EffectColor1,1,1,0,1;EffectColor2,0,1,1,1" );
2005-01-26 11:21:43 +00:00
m_textRank.RunCommands( c );
m_textName.RunCommands( c );
m_textScore.RunCommands( c );
2005-04-29 07:11:20 +00:00
m_textDate.RunCommands( c );
}
void HighScoreWheel::Load( const HighScoreList& hsl, int iIndexToFocus )
{
m_Items.resize( PREFSMAN->m_iMaxHighScoresPerListForMachine );
for( int i=0; i<PREFSMAN->m_iMaxHighScoresPerListForMachine; i++ )
{
2004-03-09 01:40:56 +00:00
if( unsigned(i) < hsl.vHighScores.size() )
2004-03-08 02:50:46 +00:00
m_Items[i].Load( i, hsl.vHighScores[i] );
else
m_Items[i].LoadBlank( i );
this->AddChild( &m_Items[i] );
}
m_iIndexToFocus = iIndexToFocus;
2004-03-09 01:40:56 +00:00
if( m_iIndexToFocus >= 0 && m_iIndexToFocus < int(hsl.vHighScores.size()) )
m_Items[m_iIndexToFocus].ShowFocus();
2006-01-22 01:00:06 +00:00
RString sTransformFunction =
2005-05-05 00:22:36 +00:00
"function(self,offset,itemIndex,numItems) "
" local degrees=18*offset; "
" local radians=degrees*math.pi/180; "
" self:rotationx(degrees); "
" self:y(math.sin(radians)*90); "
" self:z(math.cos(radians)*90); "
"end";
2006-09-22 03:34:06 +00:00
LuaReference ref;
ref.SetFromExpression( sTransformFunction );
2006-08-16 18:31:00 +00:00
ActorScroller::SetNumItemsToDraw( 10.5f );
ActorScroller::Load2();
2006-09-22 03:34:06 +00:00
ActorScroller::SetTransformFromReference( ref );
2005-12-07 03:53:49 +00:00
ActorScroller::SetSecondsPerItem( 0.2f );
Scroll();
}
float HighScoreWheel::Scroll()
{
2005-03-31 12:57:21 +00:00
SetCurrentAndDestinationItem( m_SubActors.size()+5.0f );
int iIndexToFocus = max( m_iIndexToFocus, 3 );
2005-03-31 12:57:21 +00:00
SetDestinationItem( (float)iIndexToFocus );
return GetTweenTimeLeft();
}
2006-01-15 20:46:15 +00:00
REGISTER_SCREEN_CLASS( ScreenNameEntryTraditional );
2006-09-21 01:22:46 +00:00
ScreenNameEntryTraditional::ScreenNameEntryTraditional()
2003-10-14 09:51:16 +00:00
{
2003-12-18 21:16:43 +00:00
if( PREFSMAN->m_bScreenTestMode )
2003-10-15 04:29:06 +00:00
{
2003-12-18 21:16:43 +00:00
GAMESTATE->m_bSideIsJoined[PLAYER_1] = true;
GAMESTATE->m_bSideIsJoined[PLAYER_2] = true;
GAMESTATE->m_MasterPlayerNumber = PLAYER_1;
2005-07-25 03:59:24 +00:00
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
2005-05-07 08:34:20 +00:00
GAMESTATE->m_pCurStyle.Set( GAMEMAN->GameAndStringToStyle( GAMEMAN->GetDefaultGame(),"versus") );
StageStats ss;
2003-12-18 21:16:43 +00:00
for( int z = 0; z < 3; ++z )
2003-10-15 04:29:06 +00:00
{
ss.vpPlayedSongs.push_back( SONGMAN->GetRandomSong() );
ss.vpPossibleSongs = ss.vpPlayedSongs;
ss.pStyle = GAMESTATE->m_pCurStyle;
ss.playMode = GAMESTATE->m_PlayMode;
ASSERT( ss.vpPlayedSongs[0]->GetAllSteps().size() );
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
FOREACH_PlayerNumber( p )
2003-12-18 21:16:43 +00:00
{
Steps *pSteps = ss.vpPlayedSongs[0]->GetAllSteps()[0];
ss.m_player[p].vpPlayedSteps.push_back( pSteps );
GAMESTATE->m_pCurSteps[p].Set( pSteps );
ss.m_player[p].iPossibleDancePoints = 100;
ss.m_player[p].iActualDancePoints = 100;
ss.m_player[p].iScore = 100;
ss.m_player[p].iPossibleDancePoints = 1000;
ss.m_player[p].iActualDancePoints = 985;
ss.m_player[p].vpPossibleSteps.push_back( pSteps );
2003-12-18 21:16:43 +00:00
2004-02-09 06:26:13 +00:00
HighScore hs;
hs.SetGrade( Grade_Tier03 );
2005-08-12 02:46:58 +00:00
hs.SetPercentDP( ss.m_player[p].GetPercentDancePoints() );
2005-08-12 02:37:04 +00:00
hs.SetScore( ss.m_player[p].iScore );
2005-08-12 02:55:48 +00:00
hs.SetDateTime( DateTime::GetNowDateTime() );
2003-12-18 21:16:43 +00:00
int a, b;
PROFILEMAN->AddStepsScore( ss.vpPlayedSongs[0], pSteps, p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpPlayedSongs[0], pSteps, p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpPlayedSongs[0], pSteps, p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpPlayedSongs[0], pSteps, p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpPlayedSongs[0], pSteps, p, hs, a, b );
PROFILEMAN->AddCategoryScore( st, RANKING_A, p, hs, a, b );
2003-12-18 21:16:43 +00:00
}
2005-02-16 03:25:45 +00:00
STATSMAN->m_vPlayedStageStats.push_back( ss );
2003-10-15 04:29:06 +00:00
}
}
2006-01-15 18:46:30 +00:00
}
2003-10-14 09:51:16 +00:00
2006-01-15 18:46:30 +00:00
void ScreenNameEntryTraditional::Init()
{
2005-02-03 02:40:40 +00:00
ALPHABET_GAP_X.Load( m_sName, "AlphabetGapX" );
NUM_ALPHABET_DISPLAYED.Load( m_sName, "NumAlphabetDisplayed" );
MAX_RANKING_NAME_LENGTH.Load( m_sName, "MaxRankingNameLength" );
FEAT_INTERVAL.Load( m_sName, "FeatInterval" );
KEYBOARD_LETTERS.Load( m_sName, "KeyboardLetters" );
ScreenWithMenuElements::Init();
2003-10-14 09:51:16 +00:00
// Find out if players deserve to enter their name
FOREACH_PlayerNumber( p )
{
vector<GameState::RankingFeat> aFeats;
2004-08-30 04:09:23 +00:00
GAMESTATE->GetRankingFeats( p, aFeats );
m_bStillEnteringName[p] = aFeats.size()>0;
m_CurFeat[p] = 0;
2003-10-14 09:51:16 +00:00
}
//
// init keyboards
//
2003-10-14 09:51:16 +00:00
{
FOREACH_HumanPlayer( p )
{
// don't show keyboard if didn't make any high scores
if( !m_bStillEnteringName[p] )
{
m_sprOutOfRanking[p].Load( THEME->GetPathG( m_sName,ssprintf("OutOfRankingP%i",p+1)) );
m_sprOutOfRanking[p]->SetName( ssprintf("OutOfRankingP%i",p+1) );
SET_XY_AND_ON_COMMAND( m_sprOutOfRanking[p] );
this->AddChild( m_sprOutOfRanking[p] );
continue; // skip
}
m_sprNameFrame[p].Load( THEME->GetPathG(m_sName,ssprintf("name frame p%i",p+1)) );
2006-06-14 02:42:29 +00:00
m_sprNameFrame[p]->SetName( ssprintf("EntryFrameP%i",p+1) );
SET_XY_AND_ON_COMMAND( m_sprNameFrame[p] );
2006-06-14 02:42:29 +00:00
this->AddChild( m_sprNameFrame[p] );
m_Keyboard[p].SetName( ssprintf("KeyboardP%i",p+1) );
SET_XY_AND_ON_COMMAND( m_Keyboard[p] );
this->AddChild( &m_Keyboard[p] );
/* Add letters to m_Keyboard. */
2006-03-28 09:34:10 +00:00
const RString sFontPath = THEME->GetPathF(m_sName,"letters");
const wstring sChars = RStringToWstring(KEYBOARD_LETTERS);
BitmapText *pLetterTemplate = new BitmapText;
pLetterTemplate->SetName( "Letter" );
pLetterTemplate->LoadFromFont( sFontPath );
ActorUtil::LoadAllCommands( *pLetterTemplate, m_sName );
pLetterTemplate->PlayCommand( "AlphabetInit" );
2006-03-28 09:34:10 +00:00
for( unsigned ch = 0; ch < sChars.size(); ++ch )
{
BitmapText *pLetter = new BitmapText( *pLetterTemplate );
2006-03-28 09:34:10 +00:00
pLetter->SetText( ssprintf("%lc", sChars[ch]) );
m_textAlphabet[p].push_back( pLetter );
m_Keyboard[p].AddChild( pLetter );
m_AlphabetLetter[p].push_back( sChars[ch] );
}
delete pLetterTemplate;
2003-10-14 09:51:16 +00:00
/* Add "<-". */
{
2006-03-28 09:34:10 +00:00
BitmapText *pLetter = new BitmapText;
pLetter->SetName( ssprintf("LetterP%i",p+1) );
ActorUtil::LoadAllCommands( *pLetter, m_sName );
2006-03-28 09:34:10 +00:00
pLetter->LoadFromFont( sFontPath );
RString sText = "&leftarrow;";
FontCharAliases::ReplaceMarkers( sText );
pLetter->SetText( sText );
pLetter->PlayCommand( "OKInit" );
2006-03-28 09:34:10 +00:00
m_textAlphabet[p].push_back( pLetter );
m_Keyboard[p].AddChild( pLetter );
m_AlphabetLetter[p].push_back( CHAR_BACK );
}
2003-10-14 09:51:16 +00:00
/* Add "OK". */
{
2006-03-28 09:34:10 +00:00
BitmapText *pLetter = new BitmapText;
pLetter->SetName( ssprintf("LetterP%i",p+1) );
ActorUtil::LoadAllCommands( *pLetter, m_sName );
2006-03-28 09:34:10 +00:00
pLetter->LoadFromFont( sFontPath );
RString sText = "&ok;";
FontCharAliases::ReplaceMarkers( sText );
pLetter->SetText( sText );
pLetter->PlayCommand( "OKInit" );
2006-03-28 09:34:10 +00:00
m_textAlphabet[p].push_back( pLetter );
m_Keyboard[p].AddChild( pLetter );
m_AlphabetLetter[p].push_back( CHAR_OK );
}
2003-10-14 09:51:16 +00:00
m_sprCursor[p].SetName( ssprintf("CursorP%i",p+1) );
m_sprCursor[p].Load( THEME->GetPathG(m_sName,ssprintf("cursor p%i",p+1)) );
m_Keyboard[p].AddChild( &m_sprCursor[p] );
2003-10-15 21:23:23 +00:00
m_textSelection[p].SetName( ssprintf("SelectionP%i",p+1) );
m_textSelection[p].LoadFromFont( THEME->GetPathF(m_sName,"entry") );
SET_XY_AND_ON_COMMAND( m_textSelection[p] );
this->AddChild( &m_textSelection[p] );
2003-10-14 09:51:16 +00:00
m_SelectedChar[p] = 0;
PositionCharsAndCursor( p );
2003-10-14 09:51:16 +00:00
// load last used ranking name if any
2004-08-30 04:09:23 +00:00
const Profile* pProfile = PROFILEMAN->GetProfile(p);
if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() )
{
2005-12-20 08:35:47 +00:00
m_sSelection[p] = RStringToWstring( pProfile->m_sLastUsedHighScoreName );
if( (int) m_sSelection[p].size() > MAX_RANKING_NAME_LENGTH )
m_sSelection[p].erase( MAX_RANKING_NAME_LENGTH );
ASSERT( (int) m_sSelection[p].size() <= MAX_RANKING_NAME_LENGTH );
if( m_sSelection[p].size() )
2006-03-29 23:11:07 +00:00
SelectChar( p, CHAR_OK, false );
}
2003-10-14 09:51:16 +00:00
UpdateSelectionText( p );
2004-02-22 22:44:39 +00:00
/* Don't tween to the initial position. */
2004-09-21 07:53:39 +00:00
for( unsigned i = 0; i < m_textAlphabet[p].size(); ++i )
m_textAlphabet[p][i]->FinishTweening();
2004-02-22 22:44:39 +00:00
}
2003-10-15 04:29:06 +00:00
}
//
// init feat displays
//
2004-05-06 06:29:33 +00:00
FOREACH_HumanPlayer( p )
{
2004-05-06 06:29:33 +00:00
/* Show feat 0, hide others without tweening. Run the ON command for
* all actors, even if we're going to hide it anyway, so any style commands
* are run. */
#define SET_ON( actor ) \
SET_XY_AND_ON_COMMAND( actor ); \
if( m_FeatDisplay[p].size()>1 ) \
2004-05-06 06:29:33 +00:00
{ \
(actor).FinishTweening(); \
2004-05-06 06:29:33 +00:00
COMMAND( actor, "Hide" ); \
(actor).FinishTweening(); \
2004-05-06 06:29:33 +00:00
}
2005-02-16 03:25:45 +00:00
m_FeatDisplay[p].reserve( STATSMAN->m_vPlayedStageStats.size() );
2004-05-07 02:53:51 +00:00
2005-02-16 03:25:45 +00:00
for( unsigned i = 0; i < STATSMAN->m_vPlayedStageStats.size(); ++i )
2003-10-15 04:29:06 +00:00
{
2005-02-16 03:25:45 +00:00
StageStats &ss = STATSMAN->m_vPlayedStageStats[i];
Song* pSong = ss.vpPlayedSongs[0];
Steps* pSteps = ss.m_player[p].vpPlayedSteps[0];
2004-05-06 06:29:33 +00:00
Course* pCourse = GAMESTATE->m_pCurCourse;
2004-06-03 08:22:02 +00:00
Trail* pTrail = GAMESTATE->m_pCurTrail[p];
2004-05-23 09:17:10 +00:00
2004-05-06 06:29:33 +00:00
int iHighScoreIndex = -1; // -1 means "out of ranking"
Grade grade = ss.m_player[p].GetGrade();
int iScore = ss.m_player[p].iScore;
float fPercentDP = ss.m_player[p].GetPercentDancePoints();
2004-05-06 06:29:33 +00:00
// If this is a SHOW_NEVER song, then it's probably a training.
// Don't show a high score
if( pSong->m_SelectionDisplay == Song::SHOW_NEVER )
continue; // skip
2004-05-06 06:29:33 +00:00
m_FeatDisplay[p].resize( m_FeatDisplay[p].size()+1 );
FeatDisplay &display = m_FeatDisplay[p].back();
2003-10-15 04:29:06 +00:00
2004-05-06 06:29:33 +00:00
const HighScoreList& hsl =
GAMESTATE->IsCourseMode() ?
2004-06-03 08:22:02 +00:00
PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse,pTrail) :
2004-05-06 06:29:33 +00:00
PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSong,pSteps);
2003-10-15 04:29:06 +00:00
2005-05-04 10:11:12 +00:00
for( int h=0; h<(int)hsl.vHighScores.size() && h<PREFSMAN->m_iMaxHighScoresPerListForMachine; h++ )
2004-05-06 06:29:33 +00:00
{
const HighScore &hs = hsl.vHighScores[h];
2005-08-12 01:52:01 +00:00
if( hs.GetName() == RANKING_TO_FILL_IN_MARKER[p] &&
2005-08-12 02:46:58 +00:00
hs.GetPercentDP() == fPercentDP &&
2005-08-12 02:37:04 +00:00
hs.GetScore() == iScore )
{
2004-05-06 06:29:33 +00:00
iHighScoreIndex = h;
break;
}
2004-05-06 06:29:33 +00:00
}
display.m_Wheel.SetName( ssprintf("WheelP%i",p+1) );
display.m_Wheel.Load( hsl, iHighScoreIndex );
SET_ON( display.m_Wheel );
this->AddChild( &display.m_Wheel );
2004-05-06 06:29:33 +00:00
2006-01-22 01:00:06 +00:00
RString sBanner;
2004-05-06 06:29:33 +00:00
if( GAMESTATE->IsCourseMode() )
sBanner = pCourse->m_sBannerPath;
else
sBanner = pSong->GetBannerPath();
2004-05-06 06:29:33 +00:00
if( !sBanner.empty() )
{
display.m_sprBanner.SetName( ssprintf("BannerP%i",p+1) );
display.m_sprBanner.Load( sBanner );
SET_ON( display.m_sprBanner );
this->AddChild( &display.m_sprBanner );
2004-05-06 06:29:33 +00:00
}
2003-10-15 04:29:06 +00:00
if( grade != Grade_NoData )
2004-05-06 06:29:33 +00:00
{
display.m_Grade.SetName( ssprintf("GradeP%i",p+1) );
display.m_Grade.Load( THEME->GetPathG(m_sName,"grades") );
2004-06-03 08:22:02 +00:00
display.m_Grade.SetGrade( p, grade );
SET_ON( display.m_Grade );
this->AddChild( &display.m_Grade );
}
2004-05-06 06:29:33 +00:00
display.m_DifficultyIcon.Load( THEME->GetPathG(m_sName,"DifficultyIcon") );
2004-05-06 06:29:33 +00:00
if( GAMESTATE->IsCourseMode() )
display.m_DifficultyIcon.SetFromTrail( p, pTrail );
2004-05-06 06:29:33 +00:00
else
display.m_DifficultyIcon.SetFromSteps( p, pSteps );
display.m_DifficultyIcon.SetName( ssprintf("DifficultyIconP%i",p+1) );
SET_ON( display.m_DifficultyIcon );
this->AddChild( &display.m_DifficultyIcon );
display.m_DifficultyMeter.Load( m_sName+ssprintf(" DifficultyMeterP%d",p+1) );
if( GAMESTATE->IsCourseMode() )
display.m_DifficultyMeter.SetFromTrail( pTrail );
else
display.m_DifficultyMeter.SetFromSteps( pSteps );
display.m_DifficultyMeter.SetName( ssprintf("DifficultyMeterP%i",p+1) );
SET_ON( display.m_DifficultyMeter );
this->AddChild( &display.m_DifficultyMeter );
2004-05-06 06:29:33 +00:00
2005-08-23 20:49:30 +00:00
display.m_textScore.Load( GAMESTATE->m_pPlayerState[p], &ss.m_player[p], "ScreenNameEntryTraditional Percent", false );
display.m_textScore.SetName( ssprintf("ScoreP%i",p+1) );
SET_ON( display.m_textScore );
this->AddChild( &display.m_textScore );
2004-05-06 06:29:33 +00:00
// if( feat.Feat != "" )
// {
// display.m_textCategory.SetName( ssprintf("CategoryP%i", p+1) );
// display.m_textCategory.LoadFromFont( THEME->GetPathF(m_sName, "category") );
// display.m_textCategory.SetText( feat.Feat );
// SET_ON( display.m_textCategory );
// this->AddChild( &display.m_textCategory );
2004-05-06 06:29:33 +00:00
// }
/* We always show the banner frame (if any), because fading from a graphic to
* itself is ugly. */
display.m_sprBannerFrame.Load( THEME->GetPathG(m_sName,ssprintf("banner frame p%i",p+1)) );
2006-06-14 02:42:29 +00:00
display.m_sprBannerFrame->SetName( ssprintf("BannerFrameP%i",p+1) );
SET_XY_AND_ON_COMMAND( display.m_sprBannerFrame );
2006-06-14 02:42:29 +00:00
this->AddChild( display.m_sprBannerFrame );
}
2004-05-06 06:29:33 +00:00
#undef SET_ON
2003-10-14 09:51:16 +00:00
}
2003-10-15 04:29:06 +00:00
this->PostScreenMessage( SM_ChangeDisplayedFeat, FEAT_INTERVAL );
m_soundKey.Load( THEME->GetPathS(m_sName,"key") );
m_soundChange.Load( THEME->GetPathS(m_sName,"change",true) );
m_soundInvalid.Load( THEME->GetPathS(m_sName,"invalid",true) );
2003-10-14 09:51:16 +00:00
this->SortByDrawOrder();
2003-10-14 09:51:16 +00:00
}
static inline int wrapn( int x, int n )
{
wrap( x, n );
return x;
}
void ScreenNameEntryTraditional::PositionCharsAndCursor( int pn )
{
2006-03-28 09:34:10 +00:00
const int iSelected = m_SelectedChar[pn];
const int iNumDisplayed = NUM_ALPHABET_DISPLAYED;
2003-10-14 09:51:16 +00:00
2006-03-28 09:34:10 +00:00
const int iTotalDisplayed = (int)m_textAlphabet[pn].size();
const int iStart = wrapn( iSelected - iTotalDisplayed/2, iTotalDisplayed );
2003-10-14 09:51:16 +00:00
2006-03-28 09:34:10 +00:00
const int iFirst = -iNumDisplayed/2;
const int iLast = iNumDisplayed/2;
2003-10-14 09:51:16 +00:00
for( int i = 0; i < (int)m_textAlphabet[pn].size(); ++i )
{
2006-03-28 09:34:10 +00:00
const int iNum = wrapn( iStart+i, (int) m_textAlphabet[pn].size() );
BitmapText *bt = m_textAlphabet[pn][iNum];
2003-10-14 09:51:16 +00:00
2006-03-28 09:34:10 +00:00
const int iPos = i - iTotalDisplayed/2;
const bool bHidden = ( iPos < iFirst || iPos > iLast );
const int iActualPos = clamp( iPos, iFirst-1, iLast+1 );
2003-10-14 09:51:16 +00:00
2006-09-21 01:22:46 +00:00
bt->PlayCommand( "Change" );
2006-03-28 09:34:10 +00:00
bt->SetX( iActualPos * ALPHABET_GAP_X );
bt->SetDiffuseAlpha( bHidden? 0.0f:1.0f );
2003-10-14 09:51:16 +00:00
}
m_sprCursor[pn].SetXY( 0,0 );
}
bool ScreenNameEntryTraditional::AnyStillEntering() const
{
FOREACH_PlayerNumber( p )
2003-10-14 09:51:16 +00:00
if( m_bStillEnteringName[p] )
return true;
return false;
}
ScreenNameEntryTraditional::~ScreenNameEntryTraditional()
{
LOG->Trace( "ScreenNameEntryTraditional::~ScreenNameEntryTraditional()" );
for( int p=0; p<NUM_PLAYERS; ++p )
{
for( unsigned i=0; i < m_textAlphabet[p].size(); ++i )
delete m_textAlphabet[p][i];
}
}
void ScreenNameEntryTraditional::Update( float fDelta )
{
2003-11-01 07:25:22 +00:00
if( m_bFirstUpdate )
SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo("name entry") );
ScreenWithMenuElements::Update(fDelta);
2003-10-14 09:51:16 +00:00
}
void ScreenNameEntryTraditional::Input( const InputEventPlus &input )
{
if( IsTransitioning() )
return;
if( input.type == IET_FIRST_PRESS )
2006-03-29 23:11:07 +00:00
{
int c;
if( input.DeviceI == DeviceInput(DEVICE_KEYBOARD, KEY_BACK) )
2006-06-11 01:28:52 +00:00
{
c = CHAR_BACK;
2006-06-11 01:28:52 +00:00
}
else
2006-06-11 01:28:52 +00:00
{
2006-06-15 03:35:54 +00:00
wchar_t ch = INPUTMAN->DeviceInputToChar(input.DeviceI,true);
2006-06-11 01:28:52 +00:00
MakeUpper( &ch, 1 );
c = ch;
}
if( c )
2006-03-29 23:11:07 +00:00
{
PlayerNumber pn = GAMESTATE->m_MasterPlayerNumber;
bool bChanged = SelectChar( pn, c, true );
2006-03-29 23:11:07 +00:00
if( bChanged )
{
m_soundChange.Play();
HandleStart( GAMESTATE->m_MasterPlayerNumber );
}
return;
2006-03-29 23:11:07 +00:00
}
}
ScreenWithMenuElements::Input( input );
}
2003-10-15 04:29:06 +00:00
void ScreenNameEntryTraditional::ChangeDisplayedFeat()
{
2004-03-24 02:23:55 +00:00
CHECKPOINT;
LOG->Trace( "ScreenNameEntryTraditional::ChangeDisplayedFeat" );
2004-03-24 03:02:24 +00:00
FOREACH_HumanPlayer( pn )
2003-10-15 04:29:06 +00:00
{
2004-05-06 06:29:33 +00:00
if( m_FeatDisplay[pn].size() < 2 )
2003-10-15 04:29:06 +00:00
continue;
2004-05-06 06:29:33 +00:00
int NewFeat = (m_CurFeat[pn]+1) % m_FeatDisplay[pn].size();
2003-10-15 04:29:06 +00:00
int OldFeat = m_CurFeat[pn];
m_CurFeat[pn] = NewFeat;
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_Wheel, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_Wheel, "Unhide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_Grade, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_Grade, "Unhide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_DifficultyIcon, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_DifficultyIcon, "Unhide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_DifficultyMeter, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_DifficultyMeter, "Unhide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_sprBanner, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_sprBanner, "Unhide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_textScore, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_textScore, "Unhide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][OldFeat].m_textCategory, "Hide" );
COMMAND_OPTIONAL( m_FeatDisplay[pn][NewFeat].m_textCategory, "Unhide" );
2004-03-12 05:43:39 +00:00
m_FeatDisplay[pn][NewFeat].m_Wheel.Scroll();
2003-10-15 04:29:06 +00:00
}
}
2003-10-14 09:51:16 +00:00
void ScreenNameEntryTraditional::HandleScreenMessage( const ScreenMessage SM )
{
2004-03-24 02:23:55 +00:00
LOG->Trace( "ScreenNameEntryTraditional::HandleScreenMessage( %d )", SM );
if( SM == SM_MenuTimer )
2003-10-14 09:51:16 +00:00
{
if( !m_Out.IsTransitioning() )
2003-10-14 09:51:16 +00:00
{
FOREACH_PlayerNumber( p )
2004-08-30 04:09:23 +00:00
Finish( p );
HandleStart( PLAYER_INVALID );
2003-10-14 09:51:16 +00:00
}
}
else if( SM == SM_ChangeDisplayedFeat )
{
2003-10-15 04:29:06 +00:00
ChangeDisplayedFeat();
this->PostScreenMessage( SM_ChangeDisplayedFeat, FEAT_INTERVAL );
}
2005-07-12 05:28:37 +00:00
ScreenWithMenuElements::HandleScreenMessage( SM );
2003-10-14 09:51:16 +00:00
}
void ScreenNameEntryTraditional::Finish( PlayerNumber pn )
{
if( !m_bStillEnteringName[pn] )
return;
m_bStillEnteringName[pn] = false;
UpdateSelectionText( pn ); /* hide NAME_ cursor */
2006-03-28 09:34:10 +00:00
RString sSelection = WStringToRString( m_sSelection[pn] );
2003-10-14 09:51:16 +00:00
// save last used ranking name
Profile* pProfile = PROFILEMAN->GetProfile(pn);
2006-03-28 09:34:10 +00:00
pProfile->m_sLastUsedHighScoreName = sSelection;
2006-03-28 09:34:10 +00:00
TrimRight( sSelection, " " );
TrimLeft( sSelection, " " );
2006-03-28 09:34:10 +00:00
GAMESTATE->StoreRankingName( pn, sSelection );
2003-10-15 04:29:06 +00:00
OFF_COMMAND( m_Keyboard[pn] );
for( int i = 0; i < (int)m_textAlphabet[pn].size(); ++i )
OFF_COMMAND( m_textAlphabet[pn][i] );
OFF_COMMAND( m_sprCursor[pn] );
if( !AnyStillEntering() )
2004-05-04 02:00:15 +00:00
AllFinished();
2003-10-14 09:51:16 +00:00
}
void ScreenNameEntryTraditional::UpdateSelectionText( int pn )
{
wstring text = m_sSelection[pn];
if( m_bStillEnteringName[pn] && (int) text.size() < MAX_RANKING_NAME_LENGTH )
2003-10-14 09:51:16 +00:00
text += L"_";
2005-12-20 08:35:47 +00:00
m_textSelection[pn].SetText( WStringToRString(text) );
2003-10-14 09:51:16 +00:00
}
2006-09-15 01:47:24 +00:00
void ScreenNameEntryTraditional::MenuStart( const InputEventPlus &input )
{
2006-09-15 01:47:24 +00:00
HandleStart( input.pn );
}
void ScreenNameEntryTraditional::HandleStart( PlayerNumber pn )
2003-10-14 09:51:16 +00:00
{
2005-04-29 23:53:55 +00:00
/* The screen may have started out with nobody entering, in which case we're
* just showing scores and the first Start press moves on. */
if( !AnyStillEntering() )
{
2004-05-04 02:00:15 +00:00
AllFinished();
return;
}
if( !m_bStillEnteringName[pn] )
return; // ignore
2003-10-14 09:51:16 +00:00
2006-03-28 09:34:10 +00:00
const int iCurrentSelection = m_SelectedChar[pn];
const int iSelectedLetter = m_AlphabetLetter[pn][iCurrentSelection];
switch( iSelectedLetter )
2003-10-14 09:51:16 +00:00
{
case CHAR_OK:
m_soundKey.Play();
Finish( pn );
2003-10-15 21:23:23 +00:00
break;
case CHAR_BACK:
2005-04-29 23:53:55 +00:00
Backspace( pn );
2003-10-14 09:51:16 +00:00
break;
2003-10-15 21:23:23 +00:00
2003-10-14 09:51:16 +00:00
default:
/* If we have room, add a new character. */
if( (int) m_sSelection[pn].size() == MAX_RANKING_NAME_LENGTH )
{
2004-02-23 01:57:24 +00:00
m_soundInvalid.Play();
2006-03-29 23:11:07 +00:00
SelectChar( pn, CHAR_BACK, false );
2003-10-14 09:51:16 +00:00
break;
}
2006-03-28 09:34:10 +00:00
m_sSelection[pn] += wchar_t(iSelectedLetter);
2003-10-14 09:51:16 +00:00
UpdateSelectionText( pn );
m_soundKey.Play();
/* If that filled the string, set the cursor on OK. */
if( (int) m_sSelection[pn].size() == MAX_RANKING_NAME_LENGTH )
2006-03-29 23:11:07 +00:00
SelectChar( pn, CHAR_OK, false );
2003-10-14 09:51:16 +00:00
}
}
2006-09-15 01:47:24 +00:00
void ScreenNameEntryTraditional::MenuSelect( const InputEventPlus &input )
2005-04-29 23:53:55 +00:00
{
2006-09-15 01:47:24 +00:00
if( !m_bStillEnteringName[input.pn] )
2005-04-29 23:53:55 +00:00
return; // ignore
2006-09-15 01:47:24 +00:00
Backspace( input.pn );
2005-04-29 23:53:55 +00:00
}
2006-03-29 23:11:07 +00:00
bool ScreenNameEntryTraditional::SelectChar( PlayerNumber pn, int c, bool bOptional )
2004-02-22 22:44:39 +00:00
{
FOREACH( int, m_AlphabetLetter[pn], letter )
{
if( *letter == c ) // character found
{
m_SelectedChar[pn] = letter - m_AlphabetLetter[pn].begin();
PositionCharsAndCursor( pn );
2006-03-29 23:11:07 +00:00
return true;
}
}
2006-03-29 23:11:07 +00:00
if( !bOptional )
ASSERT( false ); // character not found
return false;
2004-02-22 22:44:39 +00:00
}
2005-04-29 23:53:55 +00:00
void ScreenNameEntryTraditional::Backspace( PlayerNumber pn )
{
if( !m_sSelection[pn].size() )
{
m_soundInvalid.Play();
return;
}
m_sSelection[pn].erase( m_sSelection[pn].size()-1, 1 );
UpdateSelectionText( pn );
m_soundKey.Play();
}
void ScreenNameEntryTraditional::MenuLeft( const InputEventPlus &input )
2003-10-14 09:51:16 +00:00
{
2006-09-14 03:18:59 +00:00
PlayerNumber pn = input.pn;
if( !m_bStillEnteringName[pn] || IsTransitioning() )
return;
2003-10-14 09:51:16 +00:00
--m_SelectedChar[pn];
wrap( m_SelectedChar[pn], m_textAlphabet[pn].size() );
PositionCharsAndCursor( pn );
2003-10-15 04:29:06 +00:00
m_soundChange.Play();
2003-10-14 09:51:16 +00:00
}
void ScreenNameEntryTraditional::MenuRight( const InputEventPlus &input )
2003-10-14 09:51:16 +00:00
{
2006-09-14 03:18:59 +00:00
PlayerNumber pn = input.pn;
if( !m_bStillEnteringName[pn] || IsTransitioning() )
return;
2003-10-14 09:51:16 +00:00
++m_SelectedChar[pn];
wrap( m_SelectedChar[pn], m_textAlphabet[pn].size() );
PositionCharsAndCursor( pn );
2003-10-15 04:29:06 +00:00
m_soundChange.Play();
2003-10-14 09:51:16 +00:00
}
2004-05-04 02:00:15 +00:00
void ScreenNameEntryTraditional::AllFinished()
{
StartTransitioningScreen( SM_GoToNextScreen );
2004-05-04 02:00:15 +00:00
FOREACH_HumanPlayer( pn )
{
OFF_COMMAND( m_sprOutOfRanking[pn] );
OFF_COMMAND( m_sprNameFrame[pn] );
OFF_COMMAND( m_textSelection[pn] );
}
2004-05-04 03:16:51 +00:00
}
2004-06-08 05:22:33 +00:00
/*
* (c) 2001-2004 Glenn Maynard, 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.
*/