From 9551afea38244a3ad51c41e79949322e55350232 Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Wed, 14 Jan 2004 04:59:07 +0000 Subject: [PATCH] add new nav type NAV_FIRST_CHOICE_GOES_DOWN ScreenOptionsMaster::ExportOption is broken when using NAV_FIRST_CHOICE_GOES_DOWN. Fix coming soon. --- stepmania/src/ScreenOptions.cpp | 123 ++++++++++++++++---------- stepmania/src/ScreenOptions.h | 2 +- stepmania/src/ScreenOptionsMaster.cpp | 54 ++++++----- 3 files changed, 113 insertions(+), 66 deletions(-) diff --git a/stepmania/src/ScreenOptions.cpp b/stepmania/src/ScreenOptions.cpp index eda5a0c8fa..04bddd21dc 100644 --- a/stepmania/src/ScreenOptions.cpp +++ b/stepmania/src/ScreenOptions.cpp @@ -81,6 +81,14 @@ const float ITEM_X[NUM_PLAYERS] = { 260, 420 }; * This is a specialized navigation for ScreenOptionsMenu. It must be enabled to * allow screens that use rows to select other screens to work with only three * buttons. (It's also used when in five-key mode.) + * + * NAV_FIRST_CHOICE_GOES_DOWN: + * left, right -> change row + * up, down -> change row + * start -> next screen + * This is a specialized navigation for ScreenOptionsMenu. It must be enabled to + * allow screens that use rows to select other screens to work with only three + * buttons. (It's also used when in five-key mode.) */ ScreenOptions::ScreenOptions( CString sClassName ) : Screen(sClassName) @@ -523,7 +531,7 @@ BitmapText &ScreenOptions::GetTextItemForRow( PlayerNumber pn, int iRow, int iCh if( row.Type == Row::ROW_EXIT ) return *row.m_textItems[0]; - bool bOneChoice = m_Rows[iRow]->m_RowDef.bOneChoiceForAllPlayers; + bool bOneChoice = row.m_RowDef.bOneChoiceForAllPlayers; int index = -1; if( row.m_bRowIsLong ) index = bOneChoice ? 0 : pn; @@ -762,20 +770,24 @@ void ScreenOptions::UpdateEnabledDisabled() row.m_sprBullet.SetGlobalDiffuseColor( color ); row.m_textTitle.SetGlobalDiffuseColor( color ); - for( unsigned j=0; jSetGlobalDiffuseColor( color ); - - for( unsigned j=0; jGetDestY() == row.m_fY && - row.m_textItems[j]->DestTweenState().diffuse[0][3] == DiffuseAlpha ) - continue; + for( unsigned j=0; jSetGlobalDiffuseColor( color ); + } - row.m_textItems[j]->StopTweening(); - row.m_textItems[j]->BeginTweening( 0.3f ); - row.m_textItems[j]->SetDiffuseAlpha( DiffuseAlpha ); - row.m_textItems[j]->SetY( row.m_fY ); + { + for( unsigned j=0; jGetDestY() == row.m_fY && + row.m_textItems[j]->DestTweenState().diffuse[0][3] == DiffuseAlpha ) + continue; + + row.m_textItems[j]->StopTweening(); + row.m_textItems[j]->BeginTweening( 0.3f ); + row.m_textItems[j]->SetDiffuseAlpha( DiffuseAlpha ); + row.m_textItems[j]->SetY( row.m_fY ); + } } if( row.Type == Row::ROW_EXIT ) @@ -854,11 +866,11 @@ void ScreenOptions::Input( const DeviceInput& DeviceI, const InputEventType type if( type != IET_RELEASE && bHoldingLeftAndRight ) { - // If moving up from a multiselect row, put focus back on the first - // choice before moving up. + // If moving up from a bFirstChoiceGoesDown row, put focus back on + // the first choice before moving up. int iCurrentRow = m_iCurrentRow[MenuI.player]; Row &row = *m_Rows[iCurrentRow]; - if( row.m_RowDef.bMultiSelect ) + if( NAV_FIRST_CHOICE_GOES_DOWN ) row.m_iChoiceWithFocus[MenuI.player] = 0; MoveRow( MenuI.player, -1, type != IET_FIRST_PRESS ); @@ -1036,6 +1048,9 @@ void ScreenOptions::OnChange( PlayerNumber pn ) /* Update all players, since changing one player can move both cursors. */ for( int p=0; pIsHumanPlayer(p) ) + continue; // skip + TweenCursor( (PlayerNumber) p ); /* If the last row is EXIT, and is hidden, then show MORE. */ @@ -1105,45 +1120,49 @@ void ScreenOptions::MenuStart( PlayerNumber pn, const InputEventType type ) Row &row = *m_Rows[m_iCurrentRow[pn]]; OptionRowData &data = row.m_RowDef; - // Toggle selection if this is a multiselect row. + if( m_OptionsNavigation == NAV_FIRST_CHOICE_GOES_DOWN ) + { + int iChoiceInRow = row.m_iChoiceWithFocus[pn]; + if( iChoiceInRow == 0 ) + { + MenuDown( pn, type ); + return; + } + } + // If this is a bFirstChoiceGoesDown, then if this is a multiselect row. // Is this the right thing to do for five key navigation? if( data.bMultiSelect ) { int iChoiceInRow = row.m_iChoiceWithFocus[pn]; - - if( iChoiceInRow == 0 ) - { - MenuDown( pn, type ); // can't go down any more - } + row.m_vbSelected[pn][iChoiceInRow] = !row.m_vbSelected[pn][iChoiceInRow]; + if( row.m_vbSelected[pn][iChoiceInRow] ) + m_SoundToggleOn.Play(); else - { - row.m_vbSelected[pn][iChoiceInRow] = !row.m_vbSelected[pn][iChoiceInRow]; - if( row.m_vbSelected[pn][iChoiceInRow] ) - m_SoundToggleOn.Play(); - else - m_SoundToggleOff.Play(); - PositionUnderlines(); - RefreshIcons(); - - // move to the first choice - ChangeValueInRow( pn, -row.m_iChoiceWithFocus[pn], type != IET_FIRST_PRESS ); - } + m_SoundToggleOff.Play(); + PositionUnderlines(); + RefreshIcons(); + + if( m_OptionsNavigation == NAV_FIRST_CHOICE_GOES_DOWN ) + ChangeValueInRow( pn, -row.m_iChoiceWithFocus[pn], type != IET_FIRST_PRESS ); // move to the first choice } else { switch( m_OptionsNavigation ) { case NAV_THREE_KEY: + case NAV_FIRST_CHOICE_GOES_DOWN: { bool bAllOnExit = true; for( int p=0; pIsHumanPlayer(p) && m_Rows[m_iCurrentRow[p]]->Type != Row::ROW_EXIT ) bAllOnExit = false; - if( m_Rows[m_iCurrentRow[pn]]->Type != Row::ROW_EXIT ) // not on exit - MenuDown( pn, type ); // can't go down any more - else if( bAllOnExit && type == IET_FIRST_PRESS ) + if( row.Type == Row::ROW_EXIT && bAllOnExit && type == IET_FIRST_PRESS ) StartGoToNextState(); + else if( m_OptionsNavigation == NAV_FIRST_CHOICE_GOES_DOWN ) + ChangeValueInRow( pn, -row.m_iChoiceWithFocus[pn], type != IET_FIRST_PRESS ); // move to the first choice + else + MenuDown( pn, type ); } break; case NAV_THREE_KEY_MENU: @@ -1196,11 +1215,18 @@ void ScreenOptions::ChangeValueInRow( PlayerNumber pn, int iDelta, bool Repeat ) { row.m_iChoiceWithFocus[p] = iNewChoiceWithFocus; - if( optrow.bMultiSelect ) - ; // do nothing. User must press Start to toggle the selection. + if( m_OptionsNavigation==NAV_FIRST_CHOICE_GOES_DOWN && iNewChoiceWithFocus==0 ) + { + ; // do nothing + } else - row.SetOneSelection( (PlayerNumber)p, iNewChoiceWithFocus ); - + { + if( optrow.bMultiSelect ) + ; // do nothing. User must press Start to toggle the selection. + else + row.SetOneSelection( (PlayerNumber)p, iNewChoiceWithFocus ); + } + UpdateText( (PlayerNumber)p, iCurRow ); } } @@ -1208,11 +1234,18 @@ void ScreenOptions::ChangeValueInRow( PlayerNumber pn, int iDelta, bool Repeat ) { row.m_iChoiceWithFocus[pn] = iNewChoiceWithFocus; - if( optrow.bMultiSelect ) - ; // do nothing. User must press Start to toggle the selection. + if( m_OptionsNavigation==NAV_FIRST_CHOICE_GOES_DOWN && iNewChoiceWithFocus==0 ) + { + ; // do nothing + } else - row.SetOneSelection( pn, iNewChoiceWithFocus ); - + { + if( optrow.bMultiSelect ) + ; // do nothing. User must press Start to toggle the selection. + else + row.SetOneSelection( pn, iNewChoiceWithFocus ); + } + UpdateText( pn, iCurRow ); } diff --git a/stepmania/src/ScreenOptions.h b/stepmania/src/ScreenOptions.h index 656bac47b5..9cb97a451c 100644 --- a/stepmania/src/ScreenOptions.h +++ b/stepmania/src/ScreenOptions.h @@ -101,7 +101,7 @@ protected: protected: // derived classes need access to these void LoadOptionIcon( PlayerNumber pn, int iRow, CString sText ); - enum Navigation { NAV_THREE_KEY, NAV_THREE_KEY_MENU, NAV_FIVE_KEY }; + enum Navigation { NAV_THREE_KEY, NAV_THREE_KEY_MENU, NAV_FIVE_KEY, NAV_FIRST_CHOICE_GOES_DOWN }; void SetNavigation( Navigation nav ) { m_OptionsNavigation = nav; } protected: diff --git a/stepmania/src/ScreenOptionsMaster.cpp b/stepmania/src/ScreenOptionsMaster.cpp index 5b5718ac62..b359be6ca5 100644 --- a/stepmania/src/ScreenOptionsMaster.cpp +++ b/stepmania/src/ScreenOptionsMaster.cpp @@ -89,7 +89,9 @@ void ScreenOptionsMaster::SetList( OptionRowData &row, OptionRowHandler &hand, C hand.ListEntries.push_back( mc ); - row.choices.push_back( ENTRY_NAME(mc.m_sName) ); + CString sName = mc.m_sName; + CString sChoice = ENTRY_NAME(mc.m_sName); + row.choices.push_back( sChoice ); } } @@ -213,6 +215,8 @@ ScreenOptionsMaster::ScreenOptionsMaster( CString sClassName ): } if( Flags[i] == "smnavigation" ) SetNavigation( NAV_THREE_KEY_MENU ); + if( Flags[i] == "firstchoicegoesdown" ) + SetNavigation( NAV_FIRST_CHOICE_GOES_DOWN ); } if( NumRows == -1 ) @@ -268,6 +272,14 @@ ScreenOptionsMaster::ScreenOptionsMaster( CString sClassName ): CheckHandledParams; } + + // TRICKY: Insert a down arrow as the first choice in the row. + if( m_OptionsNavigation == NAV_FIRST_CHOICE_GOES_DOWN ) + { + row.choices.insert( row.choices.begin(), ENTRY_NAME("NextRow") ); + hand.ListEntries.insert( hand.ListEntries.begin(), ModeChoice() ); + } + OptionRowHandlers.push_back( hand ); } @@ -331,17 +343,6 @@ void ScreenOptionsMaster::ImportOption( const OptionRowData &row, const OptionRo } } } - - if( !row.bMultiSelect ) - { - // there should be exactly one option selected - int iNumSelected = 0; - for( unsigned e = 0; e < hand.ListEntries.size(); ++e ) - if( vbSelectedOut[e] ) - iNumSelected++; - ASSERT( iNumSelected == 1 ); - } - return; } case ROW_STEP: @@ -355,9 +356,9 @@ void ScreenOptionsMaster::ImportOption( const OptionRowData &row, const OptionRo { if( GAMESTATE->m_bDifficultCourses && GAMESTATE->m_pCurCourse->HasDifficult( GAMESTATE->GetCurrentStyleDef()->m_StepsType ) ) - SelectExactlyOne( 1, vbSelectedOut ); + SelectExactlyOne( 1+(row.bMultiSelect?1:0), vbSelectedOut ); else - SelectExactlyOne( 0, vbSelectedOut ); + SelectExactlyOne( 0+(row.bMultiSelect?1:0), vbSelectedOut ); return; } @@ -370,12 +371,12 @@ void ScreenOptionsMaster::ImportOption( const OptionRowData &row, const OptionRo { if( GAMESTATE->m_pCurNotes[pn] == vNotes[i] ) { - SelectExactlyOne( i, vbSelectedOut ); + SelectExactlyOne( i+(row.bMultiSelect?1:0), vbSelectedOut ); return; } } } - SelectExactlyOne( 0, vbSelectedOut ); + SelectExactlyOne( 0+(row.bMultiSelect?1:0), vbSelectedOut ); return; case ROW_CHARACTER: @@ -385,27 +386,40 @@ void ScreenOptionsMaster::ImportOption( const OptionRowData &row, const OptionRo for( unsigned i=0; im_pCurCharacters[pn] == apCharacters[i] ) { - SelectExactlyOne( i+1, vbSelectedOut ); + SelectExactlyOne( i+1+(row.bMultiSelect?1:0), vbSelectedOut ); return; } - SelectExactlyOne( 0, vbSelectedOut ); + SelectExactlyOne( 0+(row.bMultiSelect?1:0), vbSelectedOut ); return; } case ROW_CONFIG: { int iSelection = hand.opt->Get( row.choices ); - SelectExactlyOne( iSelection, vbSelectedOut ); + SelectExactlyOne( iSelection+(row.bMultiSelect?1:0), vbSelectedOut ); return; } case ROW_SAVE_TO_PROFILE: - SelectExactlyOne( 0, vbSelectedOut ); + SelectExactlyOne( 0+(row.bMultiSelect?1:0), vbSelectedOut ); return; default: ASSERT(0); } + + if( !row.bMultiSelect ) + { + // The first row ("go down") should not be selected. + ASSERT( vbSelectedOut[0] == false ); + + // there should be exactly one option selected + int iNumSelected = 0; + for( unsigned e = 1; e < hand.ListEntries.size(); ++e ) + if( vbSelectedOut[e] ) + iNumSelected++; + ASSERT( iNumSelected == 1 ); + } } void ScreenOptionsMaster::ImportOptions()