diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 909663fe92..a612cbd760 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -260,7 +260,7 @@ void GameState::Reset() m_bBackedOutOfFinalStage = false; - m_sEditingProfileID = ""; + m_sLastSelectedProfileID = ""; ApplyCmdline(); } @@ -2035,7 +2035,7 @@ public: lua_pushboolean(L, p->GetStageResult(pn)==RESULT_WIN); return 1; } static int GetCurrentGame( T* p, lua_State *L ) { const_cast(p->GetCurrentGame())->PushSelf( L ); return 1; } - static int GetEditingProfileID( T* p, lua_State *L ) { lua_pushstring(L, p->m_sEditingProfileID ); return 1; } + static int GetLastSelectedProfileID( T* p, lua_State *L ) { lua_pushstring(L, p->m_sLastSelectedProfileID ); return 1; } static void Register(lua_State *L) { ADD_METHOD( IsPlayerEnabled ) @@ -2086,7 +2086,7 @@ public: ADD_METHOD( IsSyncDataChanged ) ADD_METHOD( IsWinner ) ADD_METHOD( GetCurrentGame ) - ADD_METHOD( GetEditingProfileID ) + ADD_METHOD( GetLastSelectedProfileID ) Luna::Register( L ); diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 2fe406d00d..d931cf795c 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -312,7 +312,7 @@ public: void RevertSyncChanges(); // profile stuff - CString m_sEditingProfileID; + CString m_sLastSelectedProfileID; // Lua void PushSelf( lua_State *L ); diff --git a/stepmania/src/Profile.cpp b/stepmania/src/Profile.cpp index 73f4a3fcf1..a31e04f2be 100644 --- a/stepmania/src/Profile.cpp +++ b/stepmania/src/Profile.cpp @@ -450,13 +450,6 @@ float Profile::GetSongsAndCoursesPercentCompleteAllDifficulties( StepsType st ) return fActual / fPossible; } -CString Profile::GetProfileDisplayNameFromDir( CString sDir ) -{ - Profile profile; - profile.LoadEditableDataFromDir( sDir ); - return profile.GetDisplayName(); -} - int Profile::GetSongNumTimesPlayed( const Song* pSong ) const { SongID songID; @@ -1835,6 +1828,7 @@ class LunaProfile: public Luna public: LunaProfile() { LUA->Register( Register ); } + static int GetDisplayName( T* p, lua_State *L ) { lua_pushstring(L, p->m_sDisplayName ); return 1; } static int GetWeightPounds( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iWeightPounds ); return 1; } static int SetWeightPounds( T* p, lua_State *L ) { p->m_iWeightPounds = IArg(1); return 0; } static int GetGoalType( T* p, lua_State *L ) { lua_pushnumber(L, p->m_GoalType ); return 1; } @@ -1858,6 +1852,7 @@ public: static void Register(lua_State *L) { + ADD_METHOD( GetDisplayName ) ADD_METHOD( GetWeightPounds ) ADD_METHOD( SetWeightPounds ) ADD_METHOD( GetGoalType ) diff --git a/stepmania/src/Profile.h b/stepmania/src/Profile.h index 59daf46d4c..c12614ba4d 100644 --- a/stepmania/src/Profile.h +++ b/stepmania/src/Profile.h @@ -78,7 +78,6 @@ public: float GetSongsPercentComplete( StepsType st, Difficulty dc ) const; float GetCoursesPercentComplete( StepsType st, CourseDifficulty cd ) const; float GetSongsAndCoursesPercentCompleteAllDifficulties( StepsType st ) const; - static CString GetProfileDisplayNameFromDir( CString sDir ); bool GetDefaultModifiers( const Game* pGameType, CString &sModifiersOut ) const; void SetDefaultModifiers( const Game* pGameType, const CString &sModifiers ); bool IsCodeUnlocked( int iCode ) const; diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index 3c8e96d7eb..7117fab087 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -38,6 +38,10 @@ static ThemeMetric NEW_PROFILE_DEFAULT_NAME( "ProfileManager", "NewProf // exist, separated by ";": static Preference g_sMemoryCardProfileImportSubdirs( "MemoryCardProfileImportSubdirs", "" ); +static CString LocalProfileIdToDir( const CString &sProfileID ) { return USER_PROFILES_DIR + sProfileID + "/"; } + +static map g_mapLocalProfileIdToEditableData; + ProfileManager::ProfileManager() { @@ -48,9 +52,9 @@ ProfileManager::ProfileManager() ProfileManager::~ProfileManager() { - delete m_pMachineProfile; + SAFE_DELETE( m_pMachineProfile ); FOREACH_PlayerNumber(pn) - delete m_pProfile[pn]; + SAFE_DELETE( m_pProfile[pn] ); } void ProfileManager::Init() @@ -63,30 +67,8 @@ void ProfileManager::Init() } LoadMachineProfile(); -} -void ProfileManager::GetLocalProfileIDs( vector &asProfileIDsOut ) const -{ - GetDirListing( USER_PROFILES_DIR "*", asProfileIDsOut, true, false ); -} - -void ProfileManager::GetLocalProfileNames( vector &asNamesOut ) const -{ - asNamesOut.clear(); - - CStringArray vsProfileIDs; - GetLocalProfileIDs( vsProfileIDs ); - LOG->Trace("GetLocalProfileNames: %u", unsigned(vsProfileIDs.size())); - 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; + RefreshLocalProfilesEditableData(); } int ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIsMemCard ) @@ -148,7 +130,7 @@ bool ProfileManager::LoadLocalProfileFromMachine( PlayerNumber pn ) return false; } - CString sDir = USER_PROFILES_DIR + sProfileID + "/"; + CString sDir = LocalProfileIdToDir( sProfileID ); return LoadProfile( pn, sDir, false ) == Profile::success; } @@ -305,6 +287,34 @@ CString ProfileManager::GetPlayerName( PlayerNumber pn ) const } +void ProfileManager::RefreshLocalProfilesEditableData() +{ + g_mapLocalProfileIdToEditableData.clear(); + vector vsProfileID; + GetDirListing( USER_PROFILES_DIR "*", vsProfileID, true, false ); + FOREACH_CONST( CString, vsProfileID, s ) + { + Profile &pro = g_mapLocalProfileIdToEditableData[*s]; + CString sProfileDir = LocalProfileIdToDir( *s ); + LOG->Trace(" '%s'", pro.GetDisplayName().c_str()); + pro.LoadEditableDataFromDir( sProfileDir ); + } +} + +Profile &ProfileManager::GetLocalProfileEditableData( const CString &sProfileID ) +{ + map::iterator iter = g_mapLocalProfileIdToEditableData.find( sProfileID ); + if( iter == g_mapLocalProfileIdToEditableData.end() ) + { + LOG->Warn( "ProfileID '%s' doesn't exist", sProfileID.c_str() ); + static Profile s_pro; + s_pro.InitAll(); + return s_pro; + } + + return iter->second; +} + bool ProfileManager::CreateLocalProfile( CString sName ) { ASSERT( !sName.empty() ); @@ -318,22 +328,23 @@ bool ProfileManager::CreateLocalProfile( CString sName ) for( i=0; im_bSignProfileData ); + bool bResult = pro.SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData ); + RefreshLocalProfilesEditableData(); + return bResult; } bool ProfileManager::DeleteLocalProfile( CString sProfileID ) { // delete all files in profile dir - CString sProfileDir = USER_PROFILES_DIR + sProfileID; + CString sProfileDir = LocalProfileIdToDir( sProfileID ); CStringArray asFilesToDelete; - GetDirListing( sProfileDir + "/*", asFilesToDelete, false, true ); + GetDirListing( sProfileDir + "*", asFilesToDelete, false, true ); for( unsigned i=0; iRemove( asFilesToDelete[i] ); // delete edits - GetDirListing( sProfileDir + "/" + EDITS_SUBDIR + "*", asFilesToDelete, false, true ); + GetDirListing( sProfileDir + EDITS_SUBDIR + "*", asFilesToDelete, false, true ); for( unsigned i=0; iRemove( asFilesToDelete[i] ); // delete lastgood - GetDirListing( sProfileDir + "/" + LASTGOOD_SUBDIR + "*", asFilesToDelete, false, true ); + GetDirListing( sProfileDir + LASTGOOD_SUBDIR + "*", asFilesToDelete, false, true ); for( unsigned i=0; iRemove( asFilesToDelete[i] ); @@ -371,7 +384,10 @@ bool ProfileManager::DeleteLocalProfile( CString sProfileID ) FILEMAN->Remove( sProfileDir + "/" + LASTGOOD_SUBDIR ); // remove profile dir - return FILEMAN->Remove( sProfileDir ); + bool bResult = FILEMAN->Remove( sProfileDir ); + + RefreshLocalProfilesEditableData(); + return bResult; } void ProfileManager::SaveMachineProfile() const @@ -638,22 +654,37 @@ bool ProfileManager::IsPersistentProfile( ProfileSlot slot ) const } } -CString ProfileManager::GetNewProfileDefaultName() const +CString ProfileManager::GetNewLocalProfileDefaultName() const { - vector vsNames; - GetLocalProfileNames( vsNames ); + vector vsUsedNames; + PROFILEMAN->GetLocalProfileDisplayNames( vsUsedNames ); 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(); + bool bNameIsUsed = find( vsUsedNames.begin(), vsUsedNames.end(), sPotentialName ) != vsUsedNames.end(); if( !bNameIsUsed ) return sPotentialName; } return sPotentialName; } +void ProfileManager::GetLocalProfileIDs( vector &vsProfileIDsOut ) const +{ + vsProfileIDsOut.clear(); + FOREACHM_CONST( CString, Profile, g_mapLocalProfileIdToEditableData, iter ) + vsProfileIDsOut.push_back( iter->first ); +} + +void ProfileManager::GetLocalProfileDisplayNames( vector &vsProfileDisplayNamesOut ) const +{ + vsProfileDisplayNamesOut.clear(); + FOREACHM_CONST( CString, Profile, g_mapLocalProfileIdToEditableData, iter ) + vsProfileDisplayNamesOut.push_back( iter->second.m_sDisplayName ); +} + + // lua start #include "LuaBinding.h" @@ -666,6 +697,7 @@ public: static int GetProfile( T* p, lua_State *L ) { PlayerNumber pn = (PlayerNumber)IArg(1); Profile* pP = p->GetProfile(pn); ASSERT(pP); pP->PushSelf(L); return 1; } static int GetMachineProfile( T* p, lua_State *L ) { p->GetMachineProfile()->PushSelf(L); return 1; } static int SaveMachineProfile( T* p, lua_State *L ) { p->SaveMachineProfile(); return 1; } + static int GetLocalProfileEditableData( T* p, lua_State *L ) { Profile &pro = p->GetLocalProfileEditableData(SArg(1)); pro.PushSelf(L); return 1; } static void Register(lua_State *L) { @@ -673,6 +705,7 @@ public: ADD_METHOD( GetProfile ) ADD_METHOD( GetMachineProfile ) ADD_METHOD( SaveMachineProfile ) + ADD_METHOD( GetLocalProfileEditableData ) Luna::Register( L ); // Add global singleton if constructed already. If it's not constructed yet, diff --git a/stepmania/src/ProfileManager.h b/stepmania/src/ProfileManager.h index bb7f31cc5f..298474fd2b 100644 --- a/stepmania/src/ProfileManager.h +++ b/stepmania/src/ProfileManager.h @@ -24,15 +24,17 @@ public: void Init(); + // local profiles + void RefreshLocalProfilesEditableData(); + Profile &GetLocalProfileEditableData( const CString &sProfileID ); + bool CreateLocalProfile( CString sName ); bool RenameLocalProfile( CString sProfileID, CString sNewName ); bool DeleteLocalProfile( CString sProfileID ); + CString GetNewLocalProfileDefaultName() const; + void GetLocalProfileIDs( vector &vsProfileIDsOut ) const; + void GetLocalProfileDisplayNames( vector &vsProfileDisplayNamesOut ) const; - 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/ScreenProfileOptions.cpp b/stepmania/src/ScreenProfileOptions.cpp index 8761a7947e..05389f7d7a 100644 --- a/stepmania/src/ScreenProfileOptions.cpp +++ b/stepmania/src/ScreenProfileOptions.cpp @@ -9,6 +9,7 @@ #include "ScreenTextEntry.h" #include "ScreenPrompt.h" #include "GameState.h" +#include "Profile.h" enum { @@ -48,19 +49,19 @@ void ScreenProfileOptions::Init() g_ProfileOptionsLines[PO_PLAYER1].m_vsChoices.clear(); g_ProfileOptionsLines[PO_PLAYER1].m_vsChoices.push_back( "-NONE-" ); - PROFILEMAN->GetLocalProfileNames( g_ProfileOptionsLines[PO_PLAYER1].m_vsChoices ); + PROFILEMAN->GetLocalProfileDisplayNames( g_ProfileOptionsLines[PO_PLAYER1].m_vsChoices ); g_ProfileOptionsLines[PO_PLAYER2].m_vsChoices.clear(); g_ProfileOptionsLines[PO_PLAYER2].m_vsChoices.push_back( "-NONE-" ); - PROFILEMAN->GetLocalProfileNames( g_ProfileOptionsLines[PO_PLAYER2].m_vsChoices ); + PROFILEMAN->GetLocalProfileDisplayNames( g_ProfileOptionsLines[PO_PLAYER2].m_vsChoices ); g_ProfileOptionsLines[PO_DELETE_].m_vsChoices.clear(); g_ProfileOptionsLines[PO_DELETE_].m_vsChoices.push_back( "-NONE-" ); - PROFILEMAN->GetLocalProfileNames( g_ProfileOptionsLines[PO_DELETE_].m_vsChoices ); + PROFILEMAN->GetLocalProfileDisplayNames( g_ProfileOptionsLines[PO_DELETE_].m_vsChoices ); g_ProfileOptionsLines[PO_RENAME_].m_vsChoices.clear(); g_ProfileOptionsLines[PO_RENAME_].m_vsChoices.push_back( "-NONE-" ); - PROFILEMAN->GetLocalProfileNames( g_ProfileOptionsLines[PO_RENAME_].m_vsChoices ); + PROFILEMAN->GetLocalProfileDisplayNames( g_ProfileOptionsLines[PO_RENAME_].m_vsChoices ); if( PREFSMAN->GetMemoryCardOsMountPoint(PLAYER_1).Get().empty() ) g_ProfileOptionsLines[PO_OS_MOUNT_1].m_vsChoices[0] = "-NOT SET IN INI-"; diff --git a/stepmania/src/ScreenSMOnlineLogin.cpp b/stepmania/src/ScreenSMOnlineLogin.cpp index ca4c0f09ed..6db813baa3 100644 --- a/stepmania/src/ScreenSMOnlineLogin.cpp +++ b/stepmania/src/ScreenSMOnlineLogin.cpp @@ -12,6 +12,7 @@ #include "GameState.h" #include "NetworkSyncManager.h" #include "ScreenTextEntry.h" +#include "Profile.h" REGISTER_SCREEN_CLASS(ScreenSMOnlineLogin); @@ -32,9 +33,9 @@ void ScreenSMOnlineLogin::Init() ScreenOptions::Init(); g_ProfileLine[0].m_vsChoices.clear(); - PROFILEMAN->GetLocalProfileNames( g_ProfileLine[0].m_vsChoices ); + PROFILEMAN->GetLocalProfileDisplayNames( g_ProfileLine[0].m_vsChoices ); - if(!g_ProfileLine[0].m_vsChoices.size()) + if( g_ProfileLine[0].m_vsChoices.empty() ) { SCREENMAN->SystemMessage("You Must Define A Profile!"); SCREENMAN->SetNewScreen("ScreenProfileOptions"); @@ -63,11 +64,9 @@ void ScreenSMOnlineLogin::ImportOptions( int row, const vector &vp vector vsProfiles; PROFILEMAN->GetLocalProfileIDs( vsProfiles ); - CStringArray::iterator iter; - FOREACH_PlayerNumber( pn ) { - iter = find(vsProfiles.begin(), vsProfiles.end(), PREFSMAN->GetDefaultLocalProfileID(pn).Get() ); + CStringArray::iterator iter = find(vsProfiles.begin(), vsProfiles.end(), PREFSMAN->GetDefaultLocalProfileID(pn).Get() ); if( iter != vsProfiles.end() ) m_pRows[0]->SetOneSelection((PlayerNumber) pn, iter - vsProfiles.begin()); } diff --git a/stepmania/src/ScreenSelectProfile.cpp b/stepmania/src/ScreenSelectProfile.cpp index eb9c993a27..eb18614d28 100644 --- a/stepmania/src/ScreenSelectProfile.cpp +++ b/stepmania/src/ScreenSelectProfile.cpp @@ -7,6 +7,7 @@ #include "ScreenPrompt.h" #include "RageUtil.h" #include "GameState.h" +#include "Profile.h" AutoScreenMessage( SM_BackFromEnterName ) AutoScreenMessage( SM_BackFromProfileContextMenu ) @@ -14,12 +15,19 @@ AutoScreenMessage( SM_BackFromDelete ) const int PROFILE_MAX_NAME_LENGTH = 64; +static CString GetLastSelectedProfileName() +{ + Profile &pro = PROFILEMAN->GetLocalProfileEditableData( GAMESTATE->m_sLastSelectedProfileID ); + return pro.m_sDisplayName; +} + static bool ValidateProfileName( const CString &sAnswer, CString &sErrorOut ) { - CString sCurrentProfileOldName = PROFILEMAN->ProfileIDToName( GAMESTATE->m_sEditingProfileID ); - vector vsProfileNames; - PROFILEMAN->GetLocalProfileNames( vsProfileNames ); - bool bAlreadyAProfileWithThisName = find( vsProfileNames.begin(), vsProfileNames.end(), sAnswer ) != vsProfileNames.end(); + const CString &sCurrentProfileOldName = GetLastSelectedProfileName(); + + vector vsUsedNames; + PROFILEMAN->GetLocalProfileDisplayNames( vsUsedNames ); + bool bAlreadyAProfileWithThisName = find( vsUsedNames.begin(), vsUsedNames.end(), sAnswer ) != vsUsedNames.end(); if( sAnswer == "" ) { @@ -47,13 +55,6 @@ enum ContextMenuAnswer A_CANCEL, }; -static MenuDef g_ProfileContextMenu( - "ScreenMiniMenuProfiles", - 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( ScreenSelectProfile ); ScreenSelectProfile::ScreenSelectProfile( CString sName ) : @@ -71,16 +72,17 @@ void ScreenSelectProfile::Init() gc.m_sName = "create"; m_aGameCommands.push_back( gc ); - vector vsProfileNames; - PROFILEMAN->GetLocalProfileNames( vsProfileNames ); - - FOREACH_CONST( CString, vsProfileNames, s ) + vector vProfileIDs; + PROFILEMAN->GetLocalProfileIDs( vProfileIDs ); + FOREACH_CONST( CString, vProfileIDs, s ) { gc.m_sName = "profile"; + gc.m_sProfileID = *s; m_aGameCommands.push_back( gc ); } gc.m_sName = "exit"; + gc.m_sProfileID = ""; m_aGameCommands.push_back( gc ); @@ -101,7 +103,7 @@ void ScreenSelectProfile::HandleScreenMessage( const ScreenMessage SM ) ASSERT( ScreenTextEntry::s_sLastAnswer != "" ); // validate should have assured this CString sNewName = ScreenTextEntry::s_sLastAnswer; - if( GAMESTATE->m_sEditingProfileID.empty() ) + if( GAMESTATE->m_sLastSelectedProfileID.empty() ) { // create bool bResult = PROFILEMAN->CreateLocalProfile( sNewName ); @@ -113,7 +115,7 @@ void ScreenSelectProfile::HandleScreenMessage( const ScreenMessage SM ) else { // rename - bool bResult = PROFILEMAN->RenameLocalProfile( GAMESTATE->m_sEditingProfileID, sNewName ); + bool bResult = PROFILEMAN->RenameLocalProfile( GAMESTATE->m_sLastSelectedProfileID, sNewName ); if( bResult ) SCREENMAN->SetNewScreen( m_sName ); // reload else @@ -134,14 +136,12 @@ void ScreenSelectProfile::HandleScreenMessage( const ScreenMessage SM ) break; case A_RENAME: { - CString sCurrentProfileName = PROFILEMAN->ProfileIDToName( GAMESTATE->m_sEditingProfileID ); - ScreenTextEntry::TextEntry( SM_BackFromEnterName, "Enter a name for a new profile.", sCurrentProfileName, PROFILE_MAX_NAME_LENGTH, ValidateProfileName ); + ScreenTextEntry::TextEntry( SM_BackFromEnterName, "Enter a name for a new profile.", GetLastSelectedProfileName(), PROFILE_MAX_NAME_LENGTH, ValidateProfileName ); } break; case A_DELETE: { - CString sCurrentProfileName = PROFILEMAN->ProfileIDToName( GAMESTATE->m_sEditingProfileID ); - CString sMessage = ssprintf( "Are you sure you want to delete the profile '%s'?", sCurrentProfileName.c_str() ); + CString sMessage = ssprintf( "Are you sure you want to delete the profile '%s'?", GetLastSelectedProfileName().c_str() ); ScreenPrompt::Prompt( SM_BackFromDelete, sMessage, PROMPT_YES_NO ); } break; @@ -155,7 +155,7 @@ void ScreenSelectProfile::HandleScreenMessage( const ScreenMessage SM ) { if( ScreenPrompt::s_LastAnswer == ANSWER_YES ) { - PROFILEMAN->DeleteLocalProfile( GAMESTATE->m_sEditingProfileID ); + PROFILEMAN->DeleteLocalProfile( GAMESTATE->m_sLastSelectedProfileID ); SCREENMAN->SetNewScreen( m_sName ); // reload } }