diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 5ab06b95f9..2f7d54f176 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -2321,6 +2321,7 @@ void ScreenEdit::HandleStepsInformationChoice( StepsInformationChoice c, const v "Enter a description.", m_pSteps->GetDescription(), MAX_DESCRIPTION_LENGTH, + NULL, ChangeDescription, NULL ); @@ -2335,25 +2336,25 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec switch( c ) { case main_title: - SCREENMAN->TextEntry( SM_None, "Edit main title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitle, 100, ChangeMainTitle, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit main title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitle, 100, NULL, ChangeMainTitle, NULL ); break; case sub_title: - SCREENMAN->TextEntry( SM_None, "Edit sub title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitle, 100, ChangeSubTitle, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit sub title.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitle, 100, NULL, ChangeSubTitle, NULL ); break; case artist: - SCREENMAN->TextEntry( SM_None, "Edit artist.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtist, 100, ChangeArtist, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit artist.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtist, 100, NULL, ChangeArtist, NULL ); break; case credit: - SCREENMAN->TextEntry( SM_None, "Edit credit.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sCredit, 100, ChangeCredit, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit credit.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sCredit, 100, NULL, ChangeCredit, NULL ); break; case main_title_transliteration: - SCREENMAN->TextEntry( SM_None, "Edit main title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitleTranslit, 100, ChangeMainTitleTranslit, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit main title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sMainTitleTranslit, 100, NULL, ChangeMainTitleTranslit, NULL ); break; case sub_title_transliteration: - SCREENMAN->TextEntry( SM_None, "Edit sub title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitleTranslit, 100, ChangeSubTitleTranslit, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit sub title transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sSubTitleTranslit, 100, NULL, ChangeSubTitleTranslit, NULL ); break; case artist_transliteration: - SCREENMAN->TextEntry( SM_None, "Edit artist transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtistTranslit, 100, ChangeArtistTranslit, NULL ); + SCREENMAN->TextEntry( SM_None, "Edit artist transliteration.\nPress Enter to confirm,\nEscape to cancel.", pSong->m_sArtistTranslit, 100, NULL, ChangeArtistTranslit, NULL ); break; default: ASSERT(0); diff --git a/stepmania/src/ScreenEditMenu.cpp b/stepmania/src/ScreenEditMenu.cpp index 7c676d41b9..22f670acf9 100644 --- a/stepmania/src/ScreenEditMenu.cpp +++ b/stepmania/src/ScreenEditMenu.cpp @@ -147,6 +147,19 @@ static CString GetCopyDescription( const Steps *pSourceSteps ) return s; } +static bool ValidateCurrentStepsDescription( CString s, CString &sErrorOut ) +{ + if( GAMESTATE->m_pCurSteps[0]->GetDifficulty() == DIFFICULTY_EDIT ) + { + if( !GAMESTATE->m_pCurSong->IsEditDescriptionUnique(GAMESTATE->m_pCurSteps[0]->m_StepsType, s, GAMESTATE->m_pCurSteps[0]) ) + { + sErrorOut = "The supplied name supplied conflicts with another edit. Please use a different name."; + return false; + } + } + return true; +} + static void SetCurrentStepsDescription( CString s ) { GAMESTATE->m_pCurSteps[0]->SetDescription( s ); @@ -277,6 +290,7 @@ void ScreenEditMenu::MenuStart( PlayerNumber pn ) "Name the new edit.", GAMESTATE->m_pCurSteps[0]->GetDescription(), MAX_DESCRIPTION_LENGTH, + ValidateCurrentStepsDescription, SetCurrentStepsDescription, DeleteCurrentSteps ); } diff --git a/stepmania/src/ScreenManager.cpp b/stepmania/src/ScreenManager.cpp index a06def194e..ca8eae8e2b 100644 --- a/stepmania/src/ScreenManager.cpp +++ b/stepmania/src/ScreenManager.cpp @@ -500,6 +500,7 @@ void ScreenManager::TextEntry( CString sQuestion, CString sInitialAnswer, int iMaxInputLength, + bool(*Validate)(CString sAnswer,CString &sErrorOut), void(*OnOK)(CString sAnswer), void(*OnCancel)(), bool bPassword @@ -509,7 +510,15 @@ void ScreenManager::TextEntry( m_ScreenStack.back()->HandleScreenMessage( SM_LoseFocus ); // add the new state onto the back of the array - Screen *pNewScreen = new ScreenTextEntry( "ScreenTextEntry", sQuestion, sInitialAnswer, iMaxInputLength, OnOK, OnCancel, bPassword ); + Screen *pNewScreen = new ScreenTextEntry( + "ScreenTextEntry", + sQuestion, + sInitialAnswer, + iMaxInputLength, + Validate, + OnOK, + OnCancel, + bPassword ); pNewScreen->Init(); this->ZeroNextUpdate(); SetFromNewScreen( pNewScreen, true ); diff --git a/stepmania/src/ScreenManager.h b/stepmania/src/ScreenManager.h index 8102bfae02..f5556884ab 100644 --- a/stepmania/src/ScreenManager.h +++ b/stepmania/src/ScreenManager.h @@ -62,13 +62,14 @@ public: CString sQuestion, CString sInitialAnswer, int iMaxInputLength, + bool(*Validate)(CString sAnswer,CString &sErrorOut) = NULL, void(*OnOK)(CString sAnswer) = NULL, void(*OnCanel)() = NULL, bool bPassword = false ); void Password( ScreenMessage SM_SendWhenDone, const CString &sQuestion, void(*OnOK)(CString sPassword) = NULL, void(*OnCanel)() = NULL ) { - TextEntry( SM_SendWhenDone, sQuestion, "", 255, OnOK, OnCanel, true ); + TextEntry( SM_SendWhenDone, sQuestion, "", 255, NULL, OnOK, OnCanel, true ); } void MiniMenu( Menu* pDef, ScreenMessage SM_SendOnOK, ScreenMessage SM_SendOnCancel = SM_None ); void PopTopScreen( ScreenMessage SM = SM_None ); diff --git a/stepmania/src/ScreenTestFonts.cpp b/stepmania/src/ScreenTestFonts.cpp index e8753470e9..bd8fd143c3 100644 --- a/stepmania/src/ScreenTestFonts.cpp +++ b/stepmania/src/ScreenTestFonts.cpp @@ -97,7 +97,7 @@ void ScreenTestFonts::Input( const DeviceInput& DeviceI, const InputEventType ty case '`': if(curtext != CustomText) SetText(CustomText); else - SCREENMAN->TextEntry( SM_ChangeText, "Edit text.", CustomText, 100, ChangeText, NULL); + SCREENMAN->TextEntry( SM_ChangeText, "Edit text.", CustomText, 100, NULL, ChangeText, NULL); break; case '1': SetText("Waaai"); break; case '2': SetText("WAAI ☩"); break; diff --git a/stepmania/src/ScreenTextEntry.cpp b/stepmania/src/ScreenTextEntry.cpp index dd16fa3428..9bab740be7 100644 --- a/stepmania/src/ScreenTextEntry.cpp +++ b/stepmania/src/ScreenTextEntry.cpp @@ -51,6 +51,7 @@ ScreenTextEntry::ScreenTextEntry( CString sQuestion, CString sInitialAnswer, int iMaxInputLength, + bool(*Validate)(CString sAnswer,CString &sErrorOut), void(*OnOK)(CString sAnswer), void(*OnCancel)(), bool bPassword ) : @@ -61,6 +62,7 @@ ScreenTextEntry::ScreenTextEntry( m_sQuestion = sQuestion; m_sAnswer = CStringToWstring( sInitialAnswer ); m_iMaxInputLength = iMaxInputLength; + m_pValidate = Validate; m_pOnOK = OnOK; m_pOnCancel = OnCancel; m_bPassword = bPassword; @@ -122,6 +124,9 @@ void ScreenTextEntry::Init() m_Out.Load( THEME->GetPathB(m_sName,"out") ); this->AddChild( &m_Out ); + + m_Cancel.Load( THEME->GetPathB(m_sName,"cancel") ); + this->AddChild( &m_Cancel ); m_sndType.Load( THEME->GetPathS(m_sName,"type"), true ); @@ -178,7 +183,7 @@ void ScreenTextEntry::DrawPrimitives() void ScreenTextEntry::Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ) { - if( m_In.IsTransitioning() || m_Out.IsTransitioning() ) + if( m_In.IsTransitioning() || m_Out.IsTransitioning() || m_Cancel.IsTransitioning() ) return; Screen::Input( DeviceI, type, GameI, MenuI, StyleI ); @@ -306,7 +311,34 @@ void ScreenTextEntry::MenuStart( PlayerNumber pn ) void ScreenTextEntry::End( bool bCancelled ) { - m_Out.StartTransitioning( SM_DoneOpeningWipingRight ); + if( bCancelled ) + { + if( m_pOnCancel ) + m_pOnCancel(); + + m_Cancel.StartTransitioning( SM_DoneOpeningWipingRight ); + } + else + { + CString sAnswer = WStringToCString(m_sAnswer); + CString sError; + bool bValidAnswer = m_pValidate( sAnswer, sError ); + if( !bValidAnswer ) + { + SCREENMAN->Prompt( SM_None, sError ); + return; // don't end this screen. + } + + if( m_pOnOK ) + { + CString ret = WStringToCString(m_sAnswer); + FontCharAliases::ReplaceMarkers(ret); + m_pOnOK( ret ); + } + + m_Out.StartTransitioning( SM_DoneOpeningWipingRight ); + SCREENMAN->PlayStartSound(); + } m_Background->PlayCommand("Off"); @@ -315,23 +347,6 @@ void ScreenTextEntry::End( bool bCancelled ) OFF_COMMAND( m_textAnswer ); OFF_COMMAND( m_sprCursor ); - SCREENMAN->PlayStartSound(); - - if( bCancelled ) - { - if( m_pOnCancel ) - m_pOnCancel(); - } - else - { - if( m_pOnOK ) - { - CString ret = WStringToCString(m_sAnswer); - FontCharAliases::ReplaceMarkers(ret); - m_pOnOK( ret ); - } - } - s_bCancelledLast = bCancelled; s_sLastAnswer = bCancelled ? CString("") : WStringToCString(m_sAnswer); } diff --git a/stepmania/src/ScreenTextEntry.h b/stepmania/src/ScreenTextEntry.h index 718aa93376..8d01dcd629 100644 --- a/stepmania/src/ScreenTextEntry.h +++ b/stepmania/src/ScreenTextEntry.h @@ -32,6 +32,7 @@ public: CString sQuestion, CString sInitialAnswer, int iMaxInputLength, + bool(*Validate)(CString sAnswer,CString &sErrorOut) = NULL, void(*OnOK)(CString sAnswer) = NULL, void(*OnCanel)() = NULL, bool bPassword = false ); @@ -73,6 +74,7 @@ protected: AutoActor m_sprAnswerBox; wstring m_sAnswer; BitmapText m_textAnswer; + bool(*m_pValidate)( CString sAnswer, CString &sErrorOut ); void(*m_pOnOK)( CString sAnswer ); void(*m_pOnCancel)(); @@ -87,6 +89,7 @@ protected: Transition m_In; Transition m_Out; + Transition m_Cancel; RageSound m_sndType; RageSound m_sndBackspace; diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 6e9b92e7d2..080d659846 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -1412,25 +1412,27 @@ bool Song::HasSignificantBpmChangesOrStops() const return m_Timing.HasBpmChangesOrStops(); } -bool IsEditDescriptionUnique( vector vSteps, StepsType st, CString sPreferredDescription ) +bool Song::IsEditDescriptionUnique( StepsType st, CString sPreferredDescription, const Steps *pExclude ) const { - FOREACH( Steps*, vSteps, s ) + FOREACH_CONST( Steps*, m_vpSteps, s ) { - if( (*s)->GetDifficulty() != DIFFICULTY_EDIT ) - continue; + Steps *pSteps = *s; - if( (*s)->m_StepsType != st ) + if( pSteps->GetDifficulty() != DIFFICULTY_EDIT ) continue; - - if( (*s)->GetDescription() == sPreferredDescription ) + if( pSteps->m_StepsType != st ) + continue; + if( pSteps == pExclude ) + continue; + if( pSteps->GetDescription() == sPreferredDescription ) return false; } return true; } -void Song::MakeUniqueEditDescription( StepsType st, CString &sPreferredDescriptionInOut ) +void Song::MakeUniqueEditDescription( StepsType st, CString &sPreferredDescriptionInOut ) const { - if( IsEditDescriptionUnique( m_vpSteps, st, sPreferredDescriptionInOut ) ) + if( IsEditDescriptionUnique( st, sPreferredDescriptionInOut, NULL ) ) return; CString sTemp; @@ -1441,7 +1443,7 @@ void Song::MakeUniqueEditDescription( StepsType st, CString &sPreferredDescripti CString sNum = ssprintf("%d", i+1); sTemp = sPreferredDescriptionInOut.Left( MAX_DESCRIPTION_LENGTH - sNum.size() ) + sNum; - if( IsEditDescriptionUnique(m_vpSteps, st, sTemp) ) + if( IsEditDescriptionUnique(st, sTemp, NULL) ) { sPreferredDescriptionInOut = sTemp; return; @@ -1449,7 +1451,6 @@ void Song::MakeUniqueEditDescription( StepsType st, CString &sPreferredDescripti } // Edit limit guards should keep us from ever having more than 1000 edits per song. - return; } diff --git a/stepmania/src/song.h b/stepmania/src/song.h index 736f58f73f..5a96321862 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -220,7 +220,8 @@ public: int GetNumStepsLoadedFromProfile( ProfileSlot slot ) const; bool IsEditAlreadyLoaded( Steps* pSteps ) const; - void MakeUniqueEditDescription( StepsType st, CString &sPreferredDescriptionInOut ); + bool IsEditDescriptionUnique( StepsType st, CString sPreferredDescription, const Steps *pExclude ) const; + void MakeUniqueEditDescription( StepsType st, CString &sPreferredDescriptionInOut ) const; // An array of keysound file names (e.g. "beep.wav"). // The index in this array corresponds to the index in TapNote. If you