diff --git a/stepmania/src/ModeChoice.cpp b/stepmania/src/ModeChoice.cpp index 6d6efbe2ee..e117d1ead5 100644 --- a/stepmania/src/ModeChoice.cpp +++ b/stepmania/src/ModeChoice.cpp @@ -251,7 +251,7 @@ void ModeChoice::Apply( PlayerNumber pn ) const // if( m_style != STYLE_INVALID ) { - PROFILEMAN->TryLoadProfile( pn ); + PROFILEMAN->LoadDefaultProfileFromMachine( pn ); } } diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index 7c44313295..44acaee444 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -38,83 +38,85 @@ ProfileManager::~ProfileManager() } -void ProfileManager::GetProfiles( vector &asNamesOut ) +void ProfileManager::GetMachineProfileIDs( vector &asProfileIDsOut ) { - // don't pick up the profile named "Machine" - GetDirListing( PROFILES_DIR "0*", asNamesOut, true, false ); + GetDirListing( PROFILES_DIR "*", asProfileIDsOut, true, false ); } -void ProfileManager::GetProfileDisplayNames( vector &asNamesOut ) +void ProfileManager::GetMachineProfileNames( vector &asNamesOut ) { - CStringArray vsProfiles; - GetProfiles( vsProfiles ); - for( unsigned i=0; i vsProfiles; - GetProfiles( vsProfiles ); - - return find(vsProfiles.begin(), vsProfiles.end(), sProfile) != vsProfiles.end(); -} - - -void ProfileManager::TryLoadProfile( PlayerNumber pn ) -{ - CString sProfile = PREFSMAN->m_sDefaultProfile[pn]; - if( sProfile.empty() ) + m_bUsingMemoryCard[pn] = false; + CString sProfileID = PREFSMAN->m_sDefaultProfile[pn]; + if( sProfileID.empty() ) { m_sProfileDir[pn] = ""; - return; + return false; } - if( !DoesProfileExist(sProfile) ) + m_sProfileDir[pn] = PROFILES_DIR + sProfileID + SLASH; + + bool bResult = m_Profile[pn].LoadFromIni( m_sProfileDir[pn]+PROFILE_FILE ); + if( !bResult ) { - LOG->Warn( "Default profile '%s' does not exist", sProfile.c_str() ); - return; + LOG->Warn( "Default profile '%s' does not exist", sProfileID.c_str() ); + UnloadProfile( pn ); + return false; } - m_sProfileDir[pn] = PROFILES_DIR + sProfile + SLASH; - - m_Profile[pn].LoadFromIni( m_sProfileDir[pn]+PROFILE_FILE ); - - // // Load scores into SONGMAN // SONGMAN->ReadStepsMemCardDataFromFile( m_sProfileDir[pn]+STEPS_MEM_CARD_DATA_FILE, (MemoryCard)pn ); SONGMAN->ReadCourseMemCardDataFromFile( m_sProfileDir[pn]+COURSE_MEM_CARD_DATA_FILE, (MemoryCard)pn ); + + return true; } -void ProfileManager::UnloadProfile( PlayerNumber pn ) +bool ProfileManager::SaveProfile( PlayerNumber pn ) { if( m_sProfileDir[pn].empty() ) - return; + return false; - m_Profile[pn].WriteToIni( m_sProfileDir[pn]+PROFILE_FILE ); + m_Profile[pn].SaveToIni( m_sProfileDir[pn]+PROFILE_FILE ); // // Save scores into SONGMAN // + // TODO: move record data to this class SONGMAN->SaveStepsMemCardDataToFile( m_sProfileDir[pn]+STEPS_MEM_CARD_DATA_FILE, (MemoryCard)pn ); SONGMAN->SaveCourseMemCardDataToFile( m_sProfileDir[pn]+COURSE_MEM_CARD_DATA_FILE, (MemoryCard)pn ); + + return true; +} - // clear out the displayname and highscore name when we unload the profile. +void ProfileManager::UnloadProfile( PlayerNumber pn ) +{ + m_sProfileDir[pn] = ""; + m_bUsingMemoryCard[pn] = false; m_Profile[pn].Init(); } -CString ProfileManager::GetDisplayName( PlayerNumber pn ) +Profile* ProfileManager::GetProfile( PlayerNumber pn ) { - ASSERT(!m_sProfileDir[pn].empty()); - return m_Profile[pn].m_sDisplayName; + if( m_sProfileDir[pn].empty() ) + return NULL; + else + return &m_Profile[pn]; } bool Profile::LoadFromIni( CString sIniPath ) @@ -126,7 +128,7 @@ bool Profile::LoadFromIni( CString sIniPath ) CString sLastDir = asBits.back(); // this is a number name, e.g. "0000001" // Fill in a default value in case ini doesn't have it. - m_sDisplayName = ssprintf("Profile%d", atoi(sLastDir)); + m_sName = "NewProfile"; // @@ -136,42 +138,85 @@ bool Profile::LoadFromIni( CString sIniPath ) if( !ini.ReadFile() ) return false; - ini.GetValue( "Profile", "DisplayName", m_sDisplayName ); + ini.GetValue( "Profile", "DisplayName", m_sName ); ini.GetValue( "Profile", "LastUsedHighScoreName", m_sLastUsedHighScoreName ); return true; } -bool Profile::WriteToIni( CString sIniPath ) +bool Profile::SaveToIni( CString sIniPath ) { IniFile ini( sIniPath ); - ini.SetValue( "Profile", "DisplayName", m_sDisplayName ); + ini.SetValue( "Profile", "DisplayName", m_sName ); ini.SetValue( "Profile", "LastUsedHighScoreName", m_sLastUsedHighScoreName ); ini.WriteFile(); return true; } -void ProfileManager::CreateProfile( CString sDisplayName ) +bool ProfileManager::CreateMachineProfile( CString sName ) { // // Find a free directory name in the profiles directory // - CString sProfile, sDir; - for( int i=0; i<1000; i++ ) + CString sProfileID, sProfileDir; + const int MAX_TRIES = 1000; + for( int i=0; i &asProfileIDsOut ); + void GetMachineProfileNames( vector &asNamesOut ); - void GetProfiles( vector &asProfilesOut ); - void GetProfileDisplayNames( vector &asNamesOut ); - - void TryLoadProfile( PlayerNumber pn ); + bool LoadDefaultProfileFromMachine( PlayerNumber pn ); + bool LoadProfileFromMemoryCard( PlayerNumber pn ); + bool SaveProfile( PlayerNumber pn ); void UnloadProfile( PlayerNumber pn ); - CString GetDisplayName( PlayerNumber pn ); - bool IsUsingProfile( PlayerNumber pn ) { return !m_sProfileDir[pn].empty(); } + Profile* GetProfile( PlayerNumber pn ); - bool IsMemoryCardInserted( PlayerNumber pn ) { return false; } - bool IsMemoryCardValid( PlayerNumber pn ) { return false; } + + bool IsMemoryCardInserted( PlayerNumber pn ); bool IsUsingMemoryCard( PlayerNumber pn ) { return m_bUsingMemoryCard[pn]; } private: + // Directory that contains the profile. Either on local machine or + // on a memory card. CString m_sProfileDir[NUM_PLAYERS]; - bool m_bUsingMemoryCard[NUM_PLAYERS]; - Profile m_Profile[NUM_PLAYERS]; + bool m_bUsingMemoryCard[NUM_PLAYERS]; + + // actual loaded profile data + Profile m_Profile[NUM_PLAYERS]; }; diff --git a/stepmania/src/ScreenManager.cpp b/stepmania/src/ScreenManager.cpp index 6026857305..be2727d6b7 100644 --- a/stepmania/src/ScreenManager.cpp +++ b/stepmania/src/ScreenManager.cpp @@ -183,8 +183,10 @@ void ScreenSystemLayer::RefreshCreditsMessages() ASSERT(0); } - if( PROFILEMAN->IsUsingProfile((PlayerNumber)p) ) - sText += " " + PROFILEMAN->GetDisplayName((PlayerNumber)p); + Profile* pProfile = PROFILEMAN->GetProfile( (PlayerNumber)p ); + if( pProfile ) + sText += " " + pProfile->m_sName; + m_textCreditInfo[p].SetText( sText ); } } diff --git a/stepmania/src/ScreenOptions.h b/stepmania/src/ScreenOptions.h index c1a9817362..94f4e0c566 100644 --- a/stepmania/src/ScreenOptions.h +++ b/stepmania/src/ScreenOptions.h @@ -95,7 +95,9 @@ protected: MenuElements m_Menu; OptionRow* m_OptionRow; +protected: // derived classes need access to these int m_iSelectedOption[NUM_PLAYERS][MAX_OPTION_LINES]; + int m_iCurrentRow[NUM_PLAYERS]; private: InputMode m_InputMode; @@ -115,7 +117,6 @@ private: bool m_bRowIsHidden[MAX_OPTION_LINES]; float m_fRowY[MAX_OPTION_LINES]; - int m_iCurrentRow[NUM_PLAYERS]; OptionsCursor m_Underline[NUM_PLAYERS][MAX_OPTION_LINES]; OptionIcon m_OptionIcons[NUM_PLAYERS][MAX_OPTION_LINES]; diff --git a/stepmania/src/ScreenProfileOptions.cpp b/stepmania/src/ScreenProfileOptions.cpp index ab454f36eb..15b30010a9 100644 --- a/stepmania/src/ScreenProfileOptions.cpp +++ b/stepmania/src/ScreenProfileOptions.cpp @@ -18,6 +18,8 @@ #include "ThemeManager.h" #include "PrefsManager.h" #include "ScreenManager.h" +#include "ScreenTextEntry.h" +#include "ScreenPrompt.h" enum { @@ -37,25 +39,29 @@ OptionRow g_ProfileOptionsLines[NUM_PROFILE_OPTIONS_LINES] = { OptionRow( "Rename", true ), }; +const ScreenMessage SM_DoneCreating = ScreenMessage(SM_User+1); +const ScreenMessage SM_DoneRenaming = ScreenMessage(SM_User+2); +const ScreenMessage SM_DoneDeleting = ScreenMessage(SM_User+3); + ScreenProfileOptions::ScreenProfileOptions( CString sClassName ) : ScreenOptions( sClassName ) { LOG->Trace( "ScreenProfileOptions::ScreenProfileOptions()" ); g_ProfileOptionsLines[PO_PLAYER1].choices.clear(); g_ProfileOptionsLines[PO_PLAYER1].choices.push_back( "-NONE-" ); - PROFILEMAN->GetProfileDisplayNames( g_ProfileOptionsLines[PO_PLAYER1].choices ); + PROFILEMAN->GetMachineProfileNames( g_ProfileOptionsLines[PO_PLAYER1].choices ); g_ProfileOptionsLines[PO_PLAYER2].choices.clear(); g_ProfileOptionsLines[PO_PLAYER2].choices.push_back( "-NONE-" ); - PROFILEMAN->GetProfileDisplayNames( g_ProfileOptionsLines[PO_PLAYER2].choices ); + PROFILEMAN->GetMachineProfileNames( g_ProfileOptionsLines[PO_PLAYER2].choices ); g_ProfileOptionsLines[PO_DELETE_].choices.clear(); g_ProfileOptionsLines[PO_DELETE_].choices.push_back( "-NONE-" ); - PROFILEMAN->GetProfileDisplayNames( g_ProfileOptionsLines[PO_DELETE_].choices ); + PROFILEMAN->GetMachineProfileNames( g_ProfileOptionsLines[PO_DELETE_].choices ); g_ProfileOptionsLines[PO_RENAME_].choices.clear(); g_ProfileOptionsLines[PO_RENAME_].choices.push_back( "-NONE-" ); - PROFILEMAN->GetProfileDisplayNames( g_ProfileOptionsLines[PO_RENAME_].choices ); + PROFILEMAN->GetMachineProfileNames( g_ProfileOptionsLines[PO_RENAME_].choices ); Init( INPUTMODE_TOGETHER, @@ -70,7 +76,7 @@ ScreenProfileOptions::ScreenProfileOptions( CString sClassName ) : ScreenOptions void ScreenProfileOptions::ImportOptions() { vector vsProfiles; - PROFILEMAN->GetProfiles( vsProfiles ); + PROFILEMAN->GetMachineProfileIDs( vsProfiles ); CStringArray::iterator iter; @@ -84,7 +90,7 @@ void ScreenProfileOptions::ImportOptions() iter = find( vsProfiles.begin(), vsProfiles.end(), - PREFSMAN->m_sDefaultProfile[PO_PLAYER2] ); + PREFSMAN->m_sDefaultProfile[PLAYER_2] ); if( iter != vsProfiles.end() ) m_iSelectedOption[0][PO_PLAYER2] = iter - vsProfiles.begin() + 1; } @@ -92,7 +98,7 @@ void ScreenProfileOptions::ImportOptions() void ScreenProfileOptions::ExportOptions() { vector vsProfiles; - PROFILEMAN->GetProfiles( vsProfiles ); + PROFILEMAN->GetMachineProfileIDs( vsProfiles ); if( m_iSelectedOption[0][PO_PLAYER1] > 0 ) PREFSMAN->m_sDefaultProfile[PLAYER_1] = vsProfiles[m_iSelectedOption[0][PO_PLAYER1]-1]; @@ -110,49 +116,100 @@ void ScreenProfileOptions::GoToPrevState() SCREENMAN->SetNewScreen( "ScreenOptionsMenu" ); } -void CreateProfile( CString sDisplayName ) -{ - PROFILEMAN->CreateProfile( sDisplayName ); - SCREENMAN->SetNewScreen( "ScreenProfileOptions" ); -} - void ScreenProfileOptions::GoToNextState() { PREFSMAN->SaveGlobalPrefsToDisk(); GoToPrevState(); } +void ScreenProfileOptions::HandleScreenMessage( const ScreenMessage SM ) +{ + CString sProfileID = GetSelectedProfileID(); + CString sName = GetSelectedProfileName(); + + switch( SM ) + { + case SM_DoneCreating: + if( !ScreenTextEntry::s_bCancelledLast ) + { + CString sNewProfileID = ScreenTextEntry::s_sLastAnswer; + bool bResult = PROFILEMAN->CreateMachineProfile( sNewProfileID ); + if( bResult ) + SCREENMAN->SetNewScreen( "ScreenProfileOptions" ); // reload + else + SCREENMAN->Prompt( SM_None, ssprintf("Error creating profile '%s'.", sNewProfileID.c_str()) ); + } + break; + case SM_DoneRenaming: + if( !ScreenTextEntry::s_bCancelledLast ) + { + CString sNewName = ScreenTextEntry::s_sLastAnswer; + bool bResult = PROFILEMAN->RenameMachineProfile( sProfileID, sNewName ); + if( bResult ) + SCREENMAN->SetNewScreen( "ScreenProfileOptions" ); // reload + else + SCREENMAN->Prompt( SM_None, ssprintf("Error renaming profile %s '%s'\nto '%s'.", sProfileID.c_str(), sName.c_str(), sNewName.c_str()) ); + } + break; + case SM_DoneDeleting: + if( ScreenPrompt::s_bLastAnswer ) + { + bool bResult = PROFILEMAN->DeleteMachineProfile( sProfileID ); + if( bResult ) + SCREENMAN->SetNewScreen( "ScreenProfileOptions" ); // reload + else + SCREENMAN->Prompt( SM_None, ssprintf("Error deleting profile %s '%s'.", sName.c_str(), sProfileID.c_str()) ); + } + break; + } + + ScreenOptions::HandleScreenMessage( SM ); +} + + void ScreenProfileOptions::MenuStart( PlayerNumber pn ) { - vector vsProfiles; - PROFILEMAN->GetProfiles( vsProfiles ); + CString sProfileID = GetSelectedProfileID(); + CString sName = GetSelectedProfileName(); switch( GetCurrentRow() ) { case PO_CREATE_NEW: - SCREENMAN->TextEntry( SM_None, "Enter a profile name", "", CreateProfile ); - return; + SCREENMAN->TextEntry( SM_DoneCreating, "Enter a profile name", "", NULL ); + break; case PO_DELETE_: - { - CString sProfile; - if( m_iSelectedOption[0][PO_DELETE_] > 0 ) - sProfile = vsProfiles[m_iSelectedOption[0][PO_DELETE_]-1]; - else - sProfile = ""; - } + if( sProfileID=="" ) + SOUND->PlayOnce( THEME->GetPathToS("common invalid") ); + else + SCREENMAN->Prompt( SM_DoneDeleting, ssprintf("Delete profile %s '%s'?",sProfileID.c_str(),sName.c_str()), true ); break; case PO_RENAME_: - { - CString sProfile; - if( m_iSelectedOption[0][PO_RENAME_] > 0 ) - sProfile = vsProfiles[m_iSelectedOption[0][PO_RENAME_]-1]; - else - sProfile = ""; - -// SCREENMAN->TextEntry( SM_None, "Enter a profile name", "NewProfile", SetProfile ); - } + if( sProfileID=="" ) + SOUND->PlayOnce( THEME->GetPathToS("common invalid") ); + else + SCREENMAN->TextEntry( SM_DoneRenaming, ssprintf("Rename profile %s '%s'",sProfileID.c_str(),sName.c_str()), sName, NULL ); break; default: ScreenOptions::MenuStart( pn ); } } + +CString ScreenProfileOptions::GetSelectedProfileID() +{ + vector vsProfiles; + PROFILEMAN->GetMachineProfileIDs( vsProfiles ); + + if( m_iSelectedOption[0][m_iCurrentRow[0]]==0 ) + return ""; + else + return vsProfiles[m_iSelectedOption[0][m_iCurrentRow[0]]-1]; +} + +CString ScreenProfileOptions::GetSelectedProfileName() +{ + if( m_iSelectedOption[0][m_iCurrentRow[0]]==0 ) + return ""; + else + return g_ProfileOptionsLines[PO_PLAYER1].choices[ m_iSelectedOption[0][m_iCurrentRow[0]] ]; +} + diff --git a/stepmania/src/ScreenProfileOptions.h b/stepmania/src/ScreenProfileOptions.h index 9ab88c9b66..b2fff995f3 100644 --- a/stepmania/src/ScreenProfileOptions.h +++ b/stepmania/src/ScreenProfileOptions.h @@ -16,6 +16,8 @@ class ScreenProfileOptions : public ScreenOptions public: ScreenProfileOptions( CString sName ); + virtual void HandleScreenMessage( const ScreenMessage SM ); + virtual void MenuStart( PlayerNumber pn ); private: @@ -24,5 +26,8 @@ private: void GoToNextState(); void GoToPrevState(); + + CString GetSelectedProfileID(); + CString GetSelectedProfileName(); }; diff --git a/stepmania/src/ScreenPrompt.cpp b/stepmania/src/ScreenPrompt.cpp index ecc2381b47..4d318fc790 100644 --- a/stepmania/src/ScreenPrompt.cpp +++ b/stepmania/src/ScreenPrompt.cpp @@ -25,6 +25,7 @@ const float QUESTION_Y = CENTER_Y - 60; const float PROMPT_X = CENTER_X; const float PROMPT_Y = CENTER_Y + 120; +bool ScreenPrompt::s_bLastAnswer = false; ScreenPrompt::ScreenPrompt( ScreenMessage SM_SendWhenDone, CString sText, bool bYesNoPrompt, bool bDefaultAnswer, void(*OnYes)(void*), void(*OnNo)(void*), void* pCallbackData ) : Screen("ScreenPrompt") @@ -180,10 +181,14 @@ void ScreenPrompt::MenuStart( PlayerNumber pn ) { if( m_pOnYes ) m_pOnYes(m_pCallbackData); - } else { + } + else + { if( m_pOnNo ) m_pOnNo(m_pCallbackData); } + + s_bLastAnswer = m_bAnswer; } void ScreenPrompt::MenuBack( PlayerNumber pn ) diff --git a/stepmania/src/ScreenPrompt.h b/stepmania/src/ScreenPrompt.h index e54e9ca0a6..033a53a8f1 100644 --- a/stepmania/src/ScreenPrompt.h +++ b/stepmania/src/ScreenPrompt.h @@ -28,6 +28,8 @@ public: virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); virtual void HandleScreenMessage( const ScreenMessage SM ); + static bool s_bLastAnswer; + protected: void MenuLeft( PlayerNumber pn ); void MenuRight( PlayerNumber pn ); diff --git a/stepmania/src/ScreenTextEntry.cpp b/stepmania/src/ScreenTextEntry.cpp index a0e84009c6..28238bde12 100644 --- a/stepmania/src/ScreenTextEntry.cpp +++ b/stepmania/src/ScreenTextEntry.cpp @@ -28,6 +28,11 @@ const float ANSWER_Y = CENTER_Y + 120; const float ANSWER_WIDTH = 440; const float ANSWER_HEIGHT = 30; + +CString ScreenTextEntry::s_sLastAnswer = ""; +bool ScreenTextEntry::s_bCancelledLast = false; + + /* XXX: Don't let the user use internal-use codepoints (those * that resolve to Unicode codepoints above 0xFFFF); those are * subject to change and shouldn't be written to .SMs. @@ -204,9 +209,14 @@ void ScreenTextEntry::MenuStart( PlayerNumber pn ) SOUND->PlayOnce( THEME->GetPathToS("Common start") ); - if( m_bCancelled ) { - if( m_pOnCancel ) m_pOnCancel(); - } else { + if( m_bCancelled ) + { + if( m_pOnCancel ) + m_pOnCancel(); + + } + else + { if( m_pOnOK ) { CString ret = WStringToCString(m_sAnswer); @@ -214,6 +224,9 @@ void ScreenTextEntry::MenuStart( PlayerNumber pn ) m_pOnOK( ret ); } } + + s_bCancelledLast = m_bCancelled; + s_sLastAnswer = m_bCancelled ? "" : WStringToCString(m_sAnswer); } void ScreenTextEntry::MenuBack( PlayerNumber pn ) diff --git a/stepmania/src/ScreenTextEntry.h b/stepmania/src/ScreenTextEntry.h index b8d5d0d5bb..b3ebd96d6b 100644 --- a/stepmania/src/ScreenTextEntry.h +++ b/stepmania/src/ScreenTextEntry.h @@ -29,6 +29,9 @@ public: virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); virtual void HandleScreenMessage( const ScreenMessage SM ); + static CString s_sLastAnswer; + static bool s_bCancelledLast; + protected: virtual void MenuLeft( PlayerNumber pn ); virtual void MenuRight( PlayerNumber pn ); @@ -37,7 +40,7 @@ protected: void UpdateText(); - BGAnimation m_Background; + BGAnimation m_Background; BitmapText m_textQuestion; Quad m_rectAnswerBox; wstring m_sAnswer;