diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 73c6291100..6f8d088ddc 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -100,6 +100,10 @@ Practice=Practice [EditMenu] Blank=Blank +No Group Selected.=No Group Selected. +No StepsType selected.=No StepsType selected. +No Steps selected.=No Steps selected. +No valid action.=No valid action. [EditMenuRow] Action=Action @@ -1533,6 +1537,7 @@ ExplanationSteps=Choose the steps you want to edit.\nSelect "New Edit" to create ExplanationStepsType=Choose the type of steps that you want to edit. ExplanationSourceSteps=Choose the steps you want to fill into a new edit. ExplanationSourceStepsType=Choose the type of steps that you want to use fill into a new edit.\nChoose "Blank" to create a new edit with no initial steps. +One of the selected things is invalid. Pick something valid instead.=One of the selected things is invalid. Pick something valid instead. Profile name cannot be blank.=Profile name can not be blank. The name you chose conflicts with another profile. Please use a different name.=The name you chose conflicts with another profile. Please use a different name. These steps are produced by autogen. You do not need to delete them.=These steps are produced by autogen. You do not need to delete them. diff --git a/src/EditMenu.cpp b/src/EditMenu.cpp index 2c9e205c49..69c4641b14 100644 --- a/src/EditMenu.cpp +++ b/src/EditMenu.cpp @@ -51,6 +51,11 @@ void EditMenu::StripLockedStepsAndDifficulty( vector &v ) void EditMenu::GetSongsToShowForGroup( const RString &sGroup, vector &vpSongsOut ) { + if(sGroup == "") + { + vpSongsOut.clear(); + return; + } vpSongsOut = SONGMAN->GetSongs( SHOW_GROUPS.GetValue()? sGroup:GROUP_ALL ); EditMode mode = EDIT_MODE.GetValue(); switch( mode ) @@ -189,6 +194,8 @@ void EditMenu::Load( const RString &sType ) void EditMenu::RefreshAll() { + if(!SafeToUse()) { return; } + ChangeToRow( GetFirstRow() ); OnRowValueChanged( (EditMenuRow)0 ); @@ -230,6 +237,11 @@ void EditMenu::RefreshAll() } } +bool EditMenu::SafeToUse() +{ + return !m_sGroups.empty(); +} + bool EditMenu::CanGoUp() { return m_SelectedRow != GetFirstRow(); @@ -242,6 +254,10 @@ bool EditMenu::CanGoDown() bool EditMenu::CanGoLeft() { + if(GetRowSize(m_SelectedRow) <= 0) + { + return false; + } if( m_SelectedRow == ROW_SONG || m_SelectedRow == ROW_GROUP ) return true; // wraps return m_iSelection[m_SelectedRow] != 0; @@ -265,6 +281,10 @@ int EditMenu::GetRowSize( EditMenuRow er ) const bool EditMenu::CanGoRight() { + if(GetRowSize(m_SelectedRow) <= 0) + { + return false; + } if( m_SelectedRow == ROW_SONG || m_SelectedRow == ROW_GROUP ) return true; // wraps return m_iSelection[m_SelectedRow] != GetRowSize(m_SelectedRow)-1; @@ -358,6 +378,8 @@ void EditMenu::UpdateArrows() static LocalizedString BLANK ( "EditMenu", "Blank" ); void EditMenu::OnRowValueChanged( EditMenuRow row ) { + if(!SafeToUse()) { return; } + UpdateArrows(); EditMode mode = EDIT_MODE.GetValue(); @@ -365,69 +387,108 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) switch( row ) { case ROW_GROUP: - m_textValue[ROW_GROUP].SetText( SONGMAN->ShortenGroupName(GetSelectedGroup()) ); - if( SHOW_GROUPS.GetValue() ) - { - m_GroupBanner.LoadFromSongGroup( GetSelectedGroup() ); - m_GroupBanner.PlayCommand("Changed"); - } m_pSongs.clear(); - if( mode == EditMode_Practice ) + if(GetSelectedGroup() == "") { - m_pSongs.clear(); - vector vtSongs; - GetSongsToShowForGroup( GetSelectedGroup(), vtSongs ); - // Filter out songs that aren't playable. - FOREACH( Song*, vtSongs, s ) - if( SongUtil::IsSongPlayable(*s) ) - m_pSongs.push_back(*s); + m_textValue[ROW_GROUP].SetText(THEME->GetString(m_sName, "No Group Selected.")); + if(SHOW_GROUPS.GetValue()) + { + m_GroupBanner.LoadFallback(); + m_GroupBanner.PlayCommand("Changed"); + } } else - GetSongsToShowForGroup( GetSelectedGroup(), m_pSongs ); + { + m_textValue[ROW_GROUP].SetText( SONGMAN->ShortenGroupName(GetSelectedGroup()) ); + if( SHOW_GROUPS.GetValue() ) + { + m_GroupBanner.LoadFromSongGroup(GetSelectedGroup()); + m_GroupBanner.PlayCommand("Changed"); + } + if( mode == EditMode_Practice ) + { + vector vtSongs; + GetSongsToShowForGroup(GetSelectedGroup(), vtSongs); + // Filter out songs that aren't playable. + FOREACH(Song*, vtSongs, s) + { + if(SongUtil::IsSongPlayable(*s)) + { + m_pSongs.push_back(*s); + } + } + } + else + { + GetSongsToShowForGroup(GetSelectedGroup(), m_pSongs); + } + } m_iSelection[ROW_SONG] = 0; // fall through case ROW_SONG: - m_textValue[ROW_SONG].SetText( "" ); - m_SongBanner.LoadFromSong( GetSelectedSong() ); - m_SongBanner.PlayCommand("Changed"); - m_SongTextBanner.SetFromSong( GetSelectedSong() ); - - if( mode == EditMode_Practice ) + if(GetSelectedSong() == NULL) { - StepsType orgSel = StepsType_Invalid; - if( !m_StepsTypes.empty() ) // Not first run + m_textValue[ROW_SONG].SetText(""); + m_SongBanner.LoadFallback(); + m_SongBanner.PlayCommand("Changed"); + m_SongTextBanner.SetFromString("", "", "", "", "", ""); + if(mode == EditMode_Practice) { - ASSERT( (int) m_StepsTypes.size() > m_iSelection[ROW_STEPS_TYPE] ); - orgSel = m_StepsTypes[m_iSelection[ROW_STEPS_TYPE]]; + m_iSelection[ROW_STEPS_TYPE] = 0; + m_StepsTypes.clear(); } - - // The StepsType selection may no longer be valid. Zero it for now. - m_iSelection[ROW_STEPS_TYPE] = 0; - m_StepsTypes.clear(); - - // Only show StepsTypes for which we have valid Steps. - vector vSts = CommonMetrics::STEPS_TYPES_TO_SHOW.GetValue(); - FOREACH( StepsType, vSts, st ) + } + else + { + m_textValue[ROW_SONG].SetText(""); + m_SongBanner.LoadFromSong(GetSelectedSong()); + m_SongBanner.PlayCommand("Changed"); + m_SongTextBanner.SetFromSong(GetSelectedSong()); + + if(mode == EditMode_Practice) { - if( SongUtil::GetStepsByDifficulty( GetSelectedSong(), *st, Difficulty_Invalid, false) != NULL ) - m_StepsTypes.push_back( *st ); + StepsType orgSel = StepsType_Invalid; + if(!m_StepsTypes.empty()) // Not first run + { + ASSERT( (int) m_StepsTypes.size() > m_iSelection[ROW_STEPS_TYPE] ); + orgSel = m_StepsTypes[m_iSelection[ROW_STEPS_TYPE]]; + } + + // The StepsType selection may no longer be valid. Zero it for now. + m_iSelection[ROW_STEPS_TYPE] = 0; + m_StepsTypes.clear(); + + // Only show StepsTypes for which we have valid Steps. + vector vSts = CommonMetrics::STEPS_TYPES_TO_SHOW.GetValue(); + FOREACH( StepsType, vSts, st ) + { + if(SongUtil::GetStepsByDifficulty( GetSelectedSong(), *st, Difficulty_Invalid, false) != NULL) + m_StepsTypes.push_back(*st); - // Try to preserve the user's StepsType selection. - if( *st == orgSel ) + // Try to preserve the user's StepsType selection. + if(*st == orgSel) m_iSelection[ROW_STEPS_TYPE] = m_StepsTypes.size() - 1; + } } - } // fall through case ROW_STEPS_TYPE: - m_textValue[ROW_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedStepsType()).GetLocalizedString() ); - + if(GetSelectedStepsType() == StepsType_Invalid) { + m_textValue[ROW_STEPS_TYPE].SetText(THEME->GetString(m_sName, "No StepsType selected.")); + m_vpSteps.clear(); + } + else + { + m_textValue[ROW_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedStepsType()).GetLocalizedString() ); + Difficulty dcOld = Difficulty_Invalid; - if( !m_vpSteps.empty() ) + if(!m_vpSteps.empty()) + { dcOld = GetSelectedDifficulty(); + } m_vpSteps.clear(); @@ -437,60 +498,60 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) { switch( mode ) { - case EditMode_Full: - case EditMode_CourseMods: - case EditMode_Practice: - { - vector v; - SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedStepsType(), Difficulty_Edit ); - StepsUtil::SortStepsByDescription( v ); - FOREACH_CONST( Steps*, v, p ) - m_vpSteps.push_back( StepsAndDifficulty(*p,dc) ); - } - break; - case EditMode_Home: - // have only "New Edit" - break; - default: - FAIL_M(ssprintf("Invalid edit mode: %i", mode)); + case EditMode_Full: + case EditMode_CourseMods: + case EditMode_Practice: + { + vector v; + SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedStepsType(), Difficulty_Edit ); + StepsUtil::SortStepsByDescription( v ); + FOREACH_CONST( Steps*, v, p ) + m_vpSteps.push_back( StepsAndDifficulty(*p,dc) ); + } + break; + case EditMode_Home: + // have only "New Edit" + break; + default: + FAIL_M(ssprintf("Invalid edit mode: %i", mode)); } switch( mode ) { - case EditMode_Practice: - case EditMode_CourseMods: - break; - case EditMode_Home: - case EditMode_Full: - m_vpSteps.push_back( StepsAndDifficulty(NULL,dc) ); // "New Edit" - break; - default: - FAIL_M(ssprintf("Invalid edit mode: %i", mode)); + case EditMode_Practice: + case EditMode_CourseMods: + break; + case EditMode_Home: + case EditMode_Full: + m_vpSteps.push_back( StepsAndDifficulty(NULL,dc) ); // "New Edit" + break; + default: + FAIL_M(ssprintf("Invalid edit mode: %i", mode)); } } else { Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedStepsType(), dc ); if( pSteps && UNLOCKMAN->StepsIsLocked( GetSelectedSong(), pSteps ) ) - pSteps = NULL; + pSteps = NULL; switch( mode ) { - case EditMode_Home: - // don't allow selecting of non-edits in HomeMode - break; - case EditMode_Practice: - case EditMode_CourseMods: - // only show this difficulty if steps exist - if( pSteps ) + case EditMode_Home: + // don't allow selecting of non-edits in HomeMode + break; + case EditMode_Practice: + case EditMode_CourseMods: + // only show this difficulty if steps exist + if( pSteps ) m_vpSteps.push_back( StepsAndDifficulty(pSteps,dc) ); - break; - case EditMode_Full: - // show this difficulty whether or not steps exist. - m_vpSteps.push_back( StepsAndDifficulty(pSteps,dc) ); - break; - default: - FAIL_M(ssprintf("Invalid edit mode: %i", mode)); + break; + case EditMode_Full: + // show this difficulty whether or not steps exist. + m_vpSteps.push_back( StepsAndDifficulty(pSteps,dc) ); + break; + default: + FAIL_M(ssprintf("Invalid edit mode: %i", mode)); } } } @@ -504,51 +565,75 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) break; } } + CLAMP( m_iSelection[ROW_STEPS], 0, m_vpSteps.size()-1 ); } - - CLAMP( m_iSelection[ROW_STEPS], 0, m_vpSteps.size()-1 ); - // fall through case ROW_STEPS: + if(GetSelectedSteps() == NULL && mode == EditMode_Practice) + { + m_textValue[ROW_STEPS].SetText(THEME->GetString(m_sName, "No Steps selected.")); + m_StepsDisplay.Unset(); + } + else { RString s = CustomDifficultyToLocalizedString( GetCustomDifficulty( GetSelectedStepsType(), GetSelectedDifficulty(), CourseType_Invalid ) ); m_textValue[ROW_STEPS].SetText( s ); - } - if( GetSelectedSteps() ) - m_StepsDisplay.SetFromSteps( GetSelectedSteps() ); - else - m_StepsDisplay.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedDifficulty(), CourseType_Invalid ); - // fall through - case ROW_SOURCE_STEPS_TYPE: - m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true ); - m_textValue[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true ); - m_textValue[ROW_SOURCE_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedSourceStepsType()).GetLocalizedString() ); - - m_vpSourceSteps.clear(); - m_vpSourceSteps.push_back( StepsAndDifficulty(NULL,Difficulty_Invalid) ); // "blank" - FOREACH_ENUM( Difficulty, dc ) - { - // fill in m_vpSourceSteps - if( dc != Difficulty_Edit ) + if( GetSelectedSteps() ) { - Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedSourceStepsType(), dc ); - if( pSteps != NULL ) - m_vpSourceSteps.push_back( StepsAndDifficulty(pSteps,dc) ); + m_StepsDisplay.SetFromSteps( GetSelectedSteps() ); } else { - vector v; - SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedSourceStepsType(), dc ); - StepsUtil::SortStepsByDescription( v ); - FOREACH_CONST( Steps*, v, pSteps ) - m_vpSourceSteps.push_back( StepsAndDifficulty(*pSteps,dc) ); + m_StepsDisplay.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedDifficulty(), CourseType_Invalid ); } } - StripLockedStepsAndDifficulty( m_vpSteps ); - CLAMP( m_iSelection[ROW_SOURCE_STEPS], 0, m_vpSourceSteps.size()-1 ); + // fall through + case ROW_SOURCE_STEPS_TYPE: + if(mode == EditMode_Practice) + { + m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible(false); + m_textValue[ROW_SOURCE_STEPS_TYPE].SetVisible(false); + } + else + { + m_textLabel[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true ); + m_textValue[ROW_SOURCE_STEPS_TYPE].SetVisible( GetSelectedSteps() ? false : true ); + m_textValue[ROW_SOURCE_STEPS_TYPE].SetText( GAMEMAN->GetStepsTypeInfo(GetSelectedSourceStepsType()).GetLocalizedString() ); + m_vpSourceSteps.clear(); + m_vpSourceSteps.push_back( StepsAndDifficulty(NULL,Difficulty_Invalid) ); // "blank" + + FOREACH_ENUM( Difficulty, dc ) + { + // fill in m_vpSourceSteps + if( dc != Difficulty_Edit ) + { + Steps *pSteps = SongUtil::GetStepsByDifficulty( GetSelectedSong(), GetSelectedSourceStepsType(), dc ); + if( pSteps != NULL ) + m_vpSourceSteps.push_back( StepsAndDifficulty(pSteps,dc) ); + } + else + { + vector v; + SongUtil::GetSteps( GetSelectedSong(), v, GetSelectedSourceStepsType(), dc ); + StepsUtil::SortStepsByDescription( v ); + FOREACH_CONST( Steps*, v, pSteps ) + m_vpSourceSteps.push_back( StepsAndDifficulty(*pSteps,dc) ); + } + } + StripLockedStepsAndDifficulty( m_vpSteps ); + CLAMP( m_iSelection[ROW_SOURCE_STEPS], 0, m_vpSourceSteps.size()-1 ); + } // fall through case ROW_SOURCE_STEPS: + if(mode == EditMode_Practice) + { + m_textLabel[ROW_SOURCE_STEPS].SetVisible(false); + m_textValue[ROW_SOURCE_STEPS].SetVisible(false); + m_Actions.clear(); + m_Actions.push_back( EditMenuAction_Practice ); + } + else { m_textLabel[ROW_SOURCE_STEPS].SetVisible( GetSelectedSteps() ? false : true ); m_textValue[ROW_SOURCE_STEPS].SetVisible( GetSelectedSteps() ? false : true ); @@ -566,11 +651,11 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) } bool bHideMeter = false; if( GetSelectedSourceDifficulty() == Difficulty_Invalid ) - bHideMeter = true; + bHideMeter = true; else if( GetSelectedSourceSteps() ) - m_StepsDisplaySource.SetFromSteps( GetSelectedSourceSteps() ); + m_StepsDisplaySource.SetFromSteps( GetSelectedSourceSteps() ); else - m_StepsDisplaySource.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedSourceDifficulty(), CourseType_Invalid ); + m_StepsDisplaySource.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GetSelectedSourceStepsType(), 0, GetSelectedSourceDifficulty(), CourseType_Invalid ); m_StepsDisplaySource.SetVisible( !(bHideMeter || GetSelectedSteps()) ); m_Actions.clear(); @@ -578,17 +663,17 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) { switch( mode ) { - case EditMode_Practice: - case EditMode_CourseMods: - m_Actions.push_back( EditMenuAction_Practice ); - break; - case EditMode_Home: - case EditMode_Full: - m_Actions.push_back( EditMenuAction_Edit ); - m_Actions.push_back( EditMenuAction_Delete ); - break; - default: - FAIL_M(ssprintf("Invalid edit mode: %i", mode)); + case EditMode_Practice: + case EditMode_CourseMods: + m_Actions.push_back( EditMenuAction_Practice ); + break; + case EditMode_Home: + case EditMode_Full: + m_Actions.push_back( EditMenuAction_Edit ); + m_Actions.push_back( EditMenuAction_Delete ); + break; + default: + FAIL_M(ssprintf("Invalid edit mode: %i", mode)); } } else @@ -599,7 +684,14 @@ void EditMenu::OnRowValueChanged( EditMenuRow row ) } // fall through case ROW_ACTION: - m_textValue[ROW_ACTION].SetText( EditMenuActionToLocalizedString(GetSelectedAction()) ); + if(GetSelectedAction() == EditMenuAction_Invalid) + { + m_textValue[ROW_ACTION].SetText(THEME->GetString(m_sName, "No valid action.")); + } + else + { + m_textValue[ROW_ACTION].SetText( EditMenuActionToLocalizedString(GetSelectedAction()) ); + } break; default: FAIL_M(ssprintf("Invalid EditMenuRow: %i", row)); diff --git a/src/EditMenu.h b/src/EditMenu.h index dac6767899..a468e34b0c 100644 --- a/src/EditMenu.h +++ b/src/EditMenu.h @@ -102,74 +102,86 @@ public: void RefreshAll(); + bool SafeToUse(); + +#define RETURN_IF_INVALID(check, retval) if(check) { return retval; } + /** @brief Retrieve the currently selected group. * @return the current group. */ RString GetSelectedGroup() const { if( !SHOW_GROUPS.GetValue() ) return GROUP_ALL; int groups = static_cast(m_sGroups.size()); - ASSERT_M(m_iSelection[ROW_GROUP] < groups, - ssprintf("Group selection %d < Number of groups %d", - m_iSelection[ROW_GROUP], - groups)); + RETURN_IF_INVALID(m_iSelection[ROW_GROUP] >= groups, ""); return m_sGroups[m_iSelection[ROW_GROUP]]; } /** @brief Retrieve the currently selected song. * @return the current song. */ Song* GetSelectedSong() const { - ASSERT(m_iSelection[ROW_SONG] < (int)m_pSongs.size()); + RETURN_IF_INVALID(m_pSongs.empty() || + m_iSelection[ROW_SONG] >= (int)m_pSongs.size(), NULL); return m_pSongs[m_iSelection[ROW_SONG]]; } /** @brief Retrieve the currently selected steps type. * @return the current steps type. */ StepsType GetSelectedStepsType() const { - ASSERT(m_iSelection[ROW_STEPS_TYPE] < (int)m_StepsTypes.size()); + RETURN_IF_INVALID(m_StepsTypes.empty() || + m_iSelection[ROW_STEPS_TYPE] >= (int)m_StepsTypes.size(), StepsType_Invalid); return m_StepsTypes[m_iSelection[ROW_STEPS_TYPE]]; } /** @brief Retrieve the currently selected steps. * @return the current steps. */ Steps* GetSelectedSteps() const { - ASSERT(m_iSelection[ROW_STEPS] < (int)m_vpSteps.size()); + RETURN_IF_INVALID(m_vpSteps.empty() || + m_iSelection[ROW_STEPS] >= (int)m_vpSteps.size(), NULL); return m_vpSteps[m_iSelection[ROW_STEPS]].pSteps; } /** @brief Retrieve the currently selected difficulty. * @return the current difficulty. */ Difficulty GetSelectedDifficulty() const { - ASSERT(m_iSelection[ROW_STEPS] < (int)m_vpSteps.size()); + RETURN_IF_INVALID(m_vpSteps.empty() || + m_iSelection[ROW_STEPS] >= (int)m_vpSteps.size(), Difficulty_Invalid); return m_vpSteps[m_iSelection[ROW_STEPS]].dc; } /** @brief Retrieve the currently selected source steps type. * @return the current source steps type. */ StepsType GetSelectedSourceStepsType() const { - ASSERT(m_iSelection[ROW_SOURCE_STEPS_TYPE] < (int)m_StepsTypes.size()); + RETURN_IF_INVALID(m_StepsTypes.empty() || + m_iSelection[ROW_SOURCE_STEPS_TYPE] >= (int)m_StepsTypes.size(), StepsType_Invalid); return m_StepsTypes[m_iSelection[ROW_SOURCE_STEPS_TYPE]]; } /** @brief Retrieve the currently selected source steps. * @return the current source steps. */ Steps* GetSelectedSourceSteps() const { - ASSERT(m_iSelection[ROW_SOURCE_STEPS] < (int)m_vpSourceSteps.size()); + RETURN_IF_INVALID(m_vpSourceSteps.empty() || + m_iSelection[ROW_SOURCE_STEPS] >= (int)m_vpSourceSteps.size(), NULL); return m_vpSourceSteps[m_iSelection[ROW_SOURCE_STEPS]].pSteps; } /** @brief Retrieve the currently selected difficulty. * @return the current difficulty. */ Difficulty GetSelectedSourceDifficulty() const { - ASSERT(m_iSelection[ROW_SOURCE_STEPS] < (int)m_vpSourceSteps.size()); + RETURN_IF_INVALID(m_vpSourceSteps.empty() || + m_iSelection[ROW_SOURCE_STEPS] >= (int)m_vpSourceSteps.size(), Difficulty_Invalid); return m_vpSourceSteps[m_iSelection[ROW_SOURCE_STEPS]].dc; } /** @brief Retrieve the currently selected action. * @return the current action. */ EditMenuAction GetSelectedAction() const { - ASSERT(m_iSelection[ROW_ACTION] < (int)m_Actions.size()); + RETURN_IF_INVALID(m_Actions.empty() || + m_iSelection[ROW_ACTION] >= (int)m_Actions.size(), EditMenuAction_Invalid); return m_Actions[m_iSelection[ROW_ACTION]]; } + +#undef RETURN_IF_INVALID + /** @brief Retrieve the currently selected row. * @return the current row. */ EditMenuRow GetSelectedRow() const { return m_SelectedRow; } diff --git a/src/ScreenEditMenu.cpp b/src/ScreenEditMenu.cpp index 23111bd833..0dfd714bda 100644 --- a/src/ScreenEditMenu.cpp +++ b/src/ScreenEditMenu.cpp @@ -56,6 +56,16 @@ void ScreenEditMenu::Init() LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND( m_textNumStepsLoadedFromProfile ); RefreshNumStepsLoadedFromProfile(); this->AddChild( &m_textNumStepsLoadedFromProfile ); + if(!m_Selector.SafeToUse()) + { + m_NoSongsMessage.SetName("NoSongsMessage"); + m_NoSongsMessage.LoadFromFont(THEME->GetPathF(m_sName, "NoSongsMessage")); + LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND(m_NoSongsMessage); + AddChild(&m_NoSongsMessage); + m_Selector.SetVisible(false); + m_textExplanation.SetVisible(false); + m_textNumStepsLoadedFromProfile.SetVisible(false); + } } void ScreenEditMenu::HandleScreenMessage( const ScreenMessage SM ) @@ -161,11 +171,16 @@ static LocalizedString DELETED_AUTOGEN_STEPS ( "ScreenEditMenu", "These steps ar static LocalizedString STEPS_WILL_BE_LOST ( "ScreenEditMenu", "These steps will be lost permanently." ); static LocalizedString CONTINUE_WITH_DELETE ( "ScreenEditMenu", "Continue with delete?" ); static LocalizedString ENTER_EDIT_DESCRIPTION ( "ScreenEditMenu", "Enter a description for this edit."); +static LocalizedString INVALID_SELECTION("ScreenEditMenu", "One of the selected things is invalid. Pick something valid instead."); bool ScreenEditMenu::MenuStart( const InputEventPlus & ) { if( IsTransitioning() ) return false; + if(!m_Selector.SafeToUse()) + { + return false; + } if( m_Selector.CanGoDown() ) { @@ -182,6 +197,11 @@ bool ScreenEditMenu::MenuStart( const InputEventPlus & ) // Difficulty sourceDiff = m_Selector.GetSelectedSourceDifficulty(); Steps* pSourceSteps = m_Selector.GetSelectedSourceSteps(); EditMenuAction action = m_Selector.GetSelectedAction(); + if(st == StepsType_Invalid) + { + ScreenPrompt::Prompt(SM_None, INVALID_SELECTION); + return true; + } GAMESTATE->m_pCurSong.Set( pSong ); GAMESTATE->m_pCurCourse.Set( NULL ); diff --git a/src/ScreenEditMenu.h b/src/ScreenEditMenu.h index e95463f488..19f62201d1 100644 --- a/src/ScreenEditMenu.h +++ b/src/ScreenEditMenu.h @@ -29,6 +29,7 @@ private: private: BitmapText m_textExplanation; BitmapText m_textNumStepsLoadedFromProfile; + BitmapText m_NoSongsMessage; }; #endif diff --git a/src/SongUtil.h b/src/SongUtil.h index f09bf2ff8c..97ea6e5616 100644 --- a/src/SongUtil.h +++ b/src/SongUtil.h @@ -180,7 +180,7 @@ namespace SongUtil void GetPlayableSteps( const Song *pSong, vector &vOut ); bool IsStepsTypePlayable( Song *pSong, StepsType st ); bool IsStepsPlayable( Song *pSong, Steps *pSteps ); - + /** * @brief Determine if the song has any playable steps in the present game. * @param s the current song.