diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index b18778b5b3..e3f6770273 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -4496,14 +4496,18 @@ NextScreen=@GetGameplayNextScreen() Class=ScreenCourseManager Fallback=ScreenOptions TimerSeconds=0 -ShowExitRow=0 ThemeItems=0 [ScreenEditCourse] Class=ScreenEditCourse Fallback=ScreenOptions TimerSeconds=0 -ShowExitRow=0 +ThemeItems=0 + +[ScreenEditCourseEntry] +Class=ScreenEditCourseEntry +Fallback=ScreenOptions +TimerSeconds=0 ThemeItems=0 [ScreenMiniMenuProfiles] @@ -4515,3 +4519,6 @@ Class=ScreenOptionsProfiles Fallback=ScreenOptionsSubmenu StyleIcon=0 TimerSeconds=0 + +[ProfileManager] +NewProfileDefaultName=New diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index 7b22097bf4..3c8e96d7eb 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -31,6 +31,9 @@ ProfileManager* PROFILEMAN = NULL; // global and accessable from anywhere in our #define MACHINE_PROFILE_DIR "Data/MachineProfile/" const CString LAST_GOOD_DIR = "LastGood/"; +static ThemeMetric NEW_PROFILE_DEFAULT_NAME( "ProfileManager", "NewProfileDefaultName" ); + + // Directories to search for a profile if m_sMemoryCardProfileSubdir doesn't // exist, separated by ";": static Preference g_sMemoryCardProfileImportSubdirs( "MemoryCardProfileImportSubdirs", "" ); @@ -69,19 +72,22 @@ void ProfileManager::GetLocalProfileIDs( vector &asProfileIDsOut ) cons void ProfileManager::GetLocalProfileNames( vector &asNamesOut ) const { + asNamesOut.clear(); + CStringArray vsProfileIDs; GetLocalProfileIDs( vsProfileIDs ); LOG->Trace("GetLocalProfileNames: %u", unsigned(vsProfileIDs.size())); - for( unsigned i=0; iTrace(" '%s'", sDisplayName.c_str()); - asNamesOut.push_back( sDisplayName ); - } + FOREACH_CONST( CString, vsProfileIDs, s ) + asNamesOut.push_back( ProfileIDToName(*s) ); } +CString ProfileManager::ProfileIDToName( const CString &sProfileID ) const +{ + CString sProfileDir = USER_PROFILES_DIR + sProfileID + "/"; + CString sDisplayName = Profile::GetProfileDisplayNameFromDir( sProfileDir ); + LOG->Trace(" '%s'", sDisplayName.c_str()); + return sDisplayName; +} int ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIsMemCard ) { @@ -327,7 +333,7 @@ bool ProfileManager::RenameLocalProfile( CString sProfileID, CString sNewName ) { ASSERT( !sProfileID.empty() ); - CString sProfileDir = USER_PROFILES_DIR + sProfileID; + CString sProfileDir = USER_PROFILES_DIR + sProfileID + "/"; Profile pro; Profile::LoadResult lr; @@ -632,6 +638,22 @@ bool ProfileManager::IsPersistentProfile( ProfileSlot slot ) const } } +CString ProfileManager::GetNewProfileDefaultName() const +{ + vector vsNames; + GetLocalProfileNames( vsNames ); + + CString sPotentialName; + for( int i=1; i<1000; i++ ) + { + sPotentialName = ssprintf( "%s%04d", NEW_PROFILE_DEFAULT_NAME.GetValue().c_str(), i ); + bool bNameIsUsed = find( vsNames.begin(), vsNames.end(), sPotentialName ) != vsNames.end(); + if( !bNameIsUsed ) + return sPotentialName; + } + return sPotentialName; +} + // lua start #include "LuaBinding.h" diff --git a/stepmania/src/ProfileManager.h b/stepmania/src/ProfileManager.h index b0951faa87..bb7f31cc5f 100644 --- a/stepmania/src/ProfileManager.h +++ b/stepmania/src/ProfileManager.h @@ -30,6 +30,9 @@ public: void GetLocalProfileIDs( vector &asProfileIDsOut ) const; void GetLocalProfileNames( vector &asNamesOut ) const; + CString ProfileIDToName( const CString &sProfileID ) const; + + CString GetNewProfileDefaultName() const; bool LoadFirstAvailableProfile( PlayerNumber pn ); // memory card or local profile bool LoadLocalProfileFromMachine( PlayerNumber pn ); diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 775299f8d2..63b43a5af2 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -1865,49 +1865,49 @@ void ScreenEdit::OnSnapModeChange() // Begin helper functions for InputEdit -void ChangeDescription( CString sNew ) +void ChangeDescription( const CString &sNew ) { Steps* pSteps = GAMESTATE->m_pCurSteps[PLAYER_1]; pSteps->SetDescription(sNew); } -void ChangeMainTitle( CString sNew ) +void ChangeMainTitle( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sMainTitle = sNew; } -void ChangeSubTitle( CString sNew ) +void ChangeSubTitle( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sSubTitle = sNew; } -void ChangeArtist( CString sNew ) +void ChangeArtist( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sArtist = sNew; } -void ChangeCredit( CString sNew ) +void ChangeCredit( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sCredit = sNew; } -void ChangeMainTitleTranslit( CString sNew ) +void ChangeMainTitleTranslit( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sMainTitleTranslit = sNew; } -void ChangeSubTitleTranslit( CString sNew ) +void ChangeSubTitleTranslit( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sSubTitleTranslit = sNew; } -void ChangeArtistTranslit( CString sNew ) +void ChangeArtistTranslit( const CString &sNew ) { Song* pSong = GAMESTATE->m_pCurSong; pSong->m_sArtistTranslit = sNew; diff --git a/stepmania/src/ScreenEditMenu.cpp b/stepmania/src/ScreenEditMenu.cpp index f06a39c5a0..c1d9a9af6a 100644 --- a/stepmania/src/ScreenEditMenu.cpp +++ b/stepmania/src/ScreenEditMenu.cpp @@ -157,7 +157,7 @@ static CString GetCopyDescription( const Steps *pSourceSteps ) return s; } -static bool ValidateCurrentStepsDescription( CString s, CString &sErrorOut ) +static bool ValidateCurrentStepsDescription( const CString &s, CString &sErrorOut ) { ASSERT( GAMESTATE->m_pCurSteps[0]->GetDifficulty() == DIFFICULTY_EDIT ); @@ -176,7 +176,7 @@ static bool ValidateCurrentStepsDescription( CString s, CString &sErrorOut ) return true; } -static void SetCurrentStepsDescription( CString s ) +static void SetCurrentStepsDescription( const CString &s ) { GAMESTATE->m_pCurSteps[0]->SetDescription( s ); } diff --git a/stepmania/src/ScreenOptionsProfiles.cpp b/stepmania/src/ScreenOptionsProfiles.cpp index 58f984285f..071b1ba8a7 100644 --- a/stepmania/src/ScreenOptionsProfiles.cpp +++ b/stepmania/src/ScreenOptionsProfiles.cpp @@ -4,10 +4,40 @@ #include "ScreenMiniMenu.h" #include "ProfileManager.h" #include "ScreenTextEntry.h" +#include "ScreenPrompt.h" #include "RageUtil.h" -AutoScreenMessage( SM_BackFromCreateNewName ) +AutoScreenMessage( SM_BackFromEnterName ) AutoScreenMessage( SM_BackFromProfileContextMenu ) +AutoScreenMessage( SM_BackFromDelete ) + +CString ScreenOptionsProfiles::s_sCurrentProfileID = ""; +const int PROFILE_MAX_NAME_LENGTH = 64; + +static bool ValidateProfileName( const CString &sAnswer, CString &sErrorOut ) +{ + CString sCurrentProfileOldName = PROFILEMAN->ProfileIDToName( ScreenOptionsProfiles::s_sCurrentProfileID ); + vector vsProfileNames; + PROFILEMAN->GetLocalProfileNames( vsProfileNames ); + bool bAlreadyAProfileWithThisName = find( vsProfileNames.begin(), vsProfileNames.end(), sAnswer ) != vsProfileNames.end(); + + if( sAnswer == "" ) + { + sErrorOut = "Profile name cannot be blank."; + return false; + } + else if( sAnswer == sCurrentProfileOldName ) + { + return true; + } + else if( bAlreadyAProfileWithThisName ) + { + sErrorOut = "There is already another profile with this name. Please choose a different name."; + return false; + } + + return true; +} enum ContextMenuAnswer { @@ -19,10 +49,10 @@ enum ContextMenuAnswer static MenuDef g_ProfileContextMenu( "ScreenMiniMenuProfiles", - MenuRowDef( -1, "Edit", true, EDIT_MODE_PRACTICE, 0, "" ), - MenuRowDef( -1, "Rename", true, EDIT_MODE_PRACTICE, 0, "" ), - MenuRowDef( -1, "Delete", true, EDIT_MODE_PRACTICE, 0, "" ), - MenuRowDef( -1, "Cancel", true, EDIT_MODE_PRACTICE, 0, "" ) + MenuRowDef( A_EDIT, "Edit", true, EDIT_MODE_PRACTICE, 0, "" ), + MenuRowDef( A_RENAME, "Rename", true, EDIT_MODE_PRACTICE, 0, "" ), + MenuRowDef( A_DELETE, "Delete", true, EDIT_MODE_PRACTICE, 0, "" ), + MenuRowDef( A_CANCEL, "Cancel", true, EDIT_MODE_PRACTICE, 0, "" ) ); REGISTER_SCREEN_CLASS( ScreenOptionsProfiles ); @@ -93,17 +123,32 @@ void ScreenOptionsProfiles::GoToPrevScreen() void ScreenOptionsProfiles::HandleScreenMessage( const ScreenMessage SM ) { - if( SM == SM_BackFromCreateNewName ) + if( SM == SM_BackFromEnterName ) { - if( !ScreenTextEntry::s_bCancelledLast && ScreenTextEntry::s_sLastAnswer != "" ) + if( !ScreenTextEntry::s_bCancelledLast ) { + ASSERT( ScreenTextEntry::s_sLastAnswer != "" ); // validate should have assured this + CString sNewName = ScreenTextEntry::s_sLastAnswer; - bool bResult = PROFILEMAN->CreateLocalProfile( sNewName ); - if( bResult ) - SCREENMAN->SetNewScreen( m_sName ); // reload + if( s_sCurrentProfileID.empty() ) + { + // create + bool bResult = PROFILEMAN->CreateLocalProfile( sNewName ); + if( bResult ) + SCREENMAN->SetNewScreen( m_sName ); // reload + else + ScreenPrompt::Prompt( SM_None, ssprintf("Error creating profile '%s'.", sNewName.c_str()) ); + } else - SCREENMAN->Prompt( SM_None, ssprintf("Error creating profile '%s'.", sNewName.c_str()) ); - } + { + // rename + bool bResult = PROFILEMAN->RenameLocalProfile( s_sCurrentProfileID, sNewName ); + if( bResult ) + SCREENMAN->SetNewScreen( m_sName ); // reload + else + ScreenPrompt::Prompt( SM_None, ssprintf("Error renaming profile '%s'.", sNewName.c_str()) ); + } + } } else if( SM == SM_BackFromProfileContextMenu ) { @@ -112,13 +157,34 @@ void ScreenOptionsProfiles::HandleScreenMessage( const ScreenMessage SM ) default: ASSERT(0); case A_EDIT: + SCREENMAN->SetNewScreen( "ScreenOptionsEditProfile" ); + break; case A_RENAME: + { + CString sCurrentProfileName = PROFILEMAN->ProfileIDToName( s_sCurrentProfileID ); + ScreenTextEntry::TextEntry( SM_BackFromEnterName, "Enter a name for a new profile.", sCurrentProfileName, PROFILE_MAX_NAME_LENGTH, ValidateProfileName ); + } + break; case A_DELETE: + { + CString sCurrentProfileName = PROFILEMAN->ProfileIDToName( s_sCurrentProfileID ); + CString sMessage = ssprintf( "Are you sure you want to delete the profile '%s'?", sCurrentProfileName.c_str() ); + ScreenPrompt::Prompt( SM_BackFromDelete, sMessage, PROMPT_YES_NO ); + } + break; case A_CANCEL: SCREENMAN->PlayInvalidSound(); break; } } + else if( SM == SM_BackFromDelete ) + { + if( ScreenPrompt::s_LastAnswer == ANSWER_YES ) + { + PROFILEMAN->DeleteLocalProfile( s_sCurrentProfileID ); + SCREENMAN->SetNewScreen( m_sName ); // reload + } + } } void ScreenOptionsProfiles::ProcessMenuStart( PlayerNumber pn, const InputEventType type ) @@ -128,17 +194,21 @@ void ScreenOptionsProfiles::ProcessMenuStart( PlayerNumber pn, const InputEventT if( iRow == 0 ) // "create new" { - //ScreenOptions::BeginFadingOut(); - SCREENMAN->TextEntry( SM_BackFromCreateNewName, "Enter a name for a new profile.", "", 64 ); + s_sCurrentProfileID = ""; + ScreenTextEntry::TextEntry( SM_BackFromEnterName, "Enter a name for a new profile.", PROFILEMAN->GetNewProfileDefaultName(), PROFILE_MAX_NAME_LENGTH, ValidateProfileName ); } else if( row.GetRowType() == OptionRow::ROW_EXIT ) { + s_sCurrentProfileID = ""; ScreenOptions::ProcessMenuStart( pn, type ); } else { - SCREENMAN->MiniMenu( &g_ProfileContextMenu, SM_BackFromProfileContextMenu ); - + int iProfileIndex = iRow - 1; + vector vsProfileIDs; + PROFILEMAN->GetLocalProfileIDs( vsProfileIDs ); + s_sCurrentProfileID = vsProfileIDs[ iProfileIndex ]; + ScreenMiniMenu::MiniMenu( &g_ProfileContextMenu, SM_BackFromProfileContextMenu ); } } diff --git a/stepmania/src/ScreenOptionsProfiles.h b/stepmania/src/ScreenOptionsProfiles.h index af6dc3979d..2c79e6d19a 100644 --- a/stepmania/src/ScreenOptionsProfiles.h +++ b/stepmania/src/ScreenOptionsProfiles.h @@ -10,6 +10,8 @@ public: virtual void Init(); virtual ~ScreenOptionsProfiles(); + static CString s_sCurrentProfileID; + protected: private: virtual void ImportOptions( int row, const vector &vpns ); diff --git a/stepmania/src/ScreenTestFonts.cpp b/stepmania/src/ScreenTestFonts.cpp index d72cca3702..5eafd935c0 100644 --- a/stepmania/src/ScreenTestFonts.cpp +++ b/stepmania/src/ScreenTestFonts.cpp @@ -13,7 +13,7 @@ static const float LineHeight = 50; CString CustomText; -void ChangeText(CString txt) +void ChangeText(const CString &txt) { CustomText = txt; } diff --git a/stepmania/src/ScreenTextEntry.cpp b/stepmania/src/ScreenTextEntry.cpp index e493badfba..290ceae67c 100644 --- a/stepmania/src/ScreenTextEntry.cpp +++ b/stepmania/src/ScreenTextEntry.cpp @@ -43,8 +43,8 @@ void ScreenTextEntry::TextEntry( CString sQuestion, CString sInitialAnswer, int iMaxInputLength, - bool(*Validate)(CString sAnswer,CString &sErrorOut), - void(*OnOK)(CString sAnswer), + bool(*Validate)(const CString &sAnswer,CString &sErrorOut), + void(*OnOK)(const CString &sAnswer), void(*OnCancel)(), bool bPassword ) @@ -82,8 +82,8 @@ ScreenTextEntry::ScreenTextEntry( CString sQuestion, CString sInitialAnswer, int iMaxInputLength, - bool(*Validate)(CString sAnswer,CString &sErrorOut), - void(*OnOK)(CString sAnswer), + bool(*Validate)(const CString &sAnswer,CString &sErrorOut), + void(*OnOK)(const CString &sAnswer), void(*OnCancel)(), bool bPassword ) : Screen( sClassName ) diff --git a/stepmania/src/ScreenTextEntry.h b/stepmania/src/ScreenTextEntry.h index c80b9964d9..94ba480ee8 100644 --- a/stepmania/src/ScreenTextEntry.h +++ b/stepmania/src/ScreenTextEntry.h @@ -32,12 +32,15 @@ public: CString sQuestion, CString sInitialAnswer, int iMaxInputLength, - bool(*Validate)(CString sAnswer,CString &sErrorOut) = NULL, - void(*OnOK)(CString sAnswer) = NULL, + bool(*Validate)(const CString &sAnswer,CString &sErrorOut) = NULL, + void(*OnOK)(const CString &sAnswer) = NULL, void(*OnCanel)() = NULL, - bool bPassword = false - ); - static void Password( ScreenMessage smSendOnPop, const CString &sQuestion, void(*OnOK)(CString sPassword) = NULL, void(*OnCanel)() = NULL ) + bool bPassword = false ); + static void Password( + ScreenMessage smSendOnPop, + const CString &sQuestion, + void(*OnOK)(const CString &sPassword) = NULL, + void(*OnCanel)() = NULL ) { TextEntry( smSendOnPop, sQuestion, "", 255, NULL, OnOK, OnCanel, true ); } @@ -48,8 +51,8 @@ public: CString sQuestion, CString sInitialAnswer, int iMaxInputLength, - bool(*Validate)(CString sAnswer,CString &sErrorOut) = NULL, - void(*OnOK)(CString sAnswer) = NULL, + bool(*Validate)(const CString &sAnswer,CString &sErrorOut) = NULL, + void(*OnOK)(const CString &sAnswer) = NULL, void(*OnCanel)() = NULL, bool bPassword = false ); ~ScreenTextEntry(); @@ -91,8 +94,8 @@ protected: AutoActor m_sprAnswerBox; wstring m_sAnswer; BitmapText m_textAnswer; - bool(*m_pValidate)( CString sAnswer, CString &sErrorOut ); - void(*m_pOnOK)( CString sAnswer ); + bool(*m_pValidate)( const CString &sAnswer, CString &sErrorOut ); + void(*m_pOnOK)( const CString &sAnswer ); void(*m_pOnCancel)(); AutoActor m_sprCursor;