diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index 4e9f2ad517..5369c126e6 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -2023,8 +2023,10 @@ Easier1=Up,Up Easier2=MenuUp,MenuUp Harder1=Down,Down Harder2=MenuDown,MenuDown -NextSort1=Up,Down,Up,Down -NextSort2=MenuUp,MenuDown,MenuUp,MenuDown +NextSort1=MenuLeft-MenuRight-Start +NextSort2=MenuLeft+MenuRight +AllSorts1=Up,Down,Up,Down +AllSorts2=MenuUp,MenuDown,MenuUp,MenuDown Mirror=Up,Left,Right,Left,Right Left=Up,Down,Right,Left Right=Up,Down,Left,Right diff --git a/stepmania/src/CodeDetector.cpp b/stepmania/src/CodeDetector.cpp index 7d0a50e5b4..70a0e8868e 100644 --- a/stepmania/src/CodeDetector.cpp +++ b/stepmania/src/CodeDetector.cpp @@ -14,6 +14,7 @@ #include "PlayerOptions.h" #include "GameState.h" #include "InputQueue.h" +#include "InputMapper.h" #include "ThemeManager.h" #include "RageLog.h" #include "GameDef.h" @@ -28,6 +29,8 @@ const CString g_sCodeNames[CodeDetector::NUM_CODES] = { "Harder2", "NextSort1", "NextSort2", + "AllSorts1", + "AllSorts2", "Mirror", "Left", "Right", @@ -62,6 +65,12 @@ const unsigned MAX_CODE_LENGTH = 10; struct CodeCacheItem { int iNumButtons; GameButton buttons[MAX_CODE_LENGTH]; + enum Type { + sequence, // press the buttons in sequence + hold_and_press, // hold the first iNumButtons-1 buttons, then press the last + tap // press all buttons simultaneously + }; + Type m_Type; float fMaxSecondsBack; }; CodeCacheItem g_CodeCacheItems[CodeDetector::NUM_CODES]; @@ -73,7 +82,29 @@ bool CodeDetector::EnteredCode( GameController controller, Code code ) return false; const CodeCacheItem& item = g_CodeCacheItems[code]; - return INPUTQUEUE->MatchesPattern(controller, item.buttons, item.iNumButtons, item.fMaxSecondsBack); + switch( item.m_Type ) + { + case CodeCacheItem::sequence: + return INPUTQUEUE->MatchesSequence(controller, item.buttons, item.iNumButtons, item.fMaxSecondsBack); + case CodeCacheItem::hold_and_press: + { + // check that all but the last are being held + for( int i=0; iIsButtonDown(gi) ) + return false; + } + // just pressed the last button + return INPUTQUEUE->MatchesSequence(controller, &item.buttons[item.iNumButtons-1], 1, 0.05f); + } + break; + case CodeCacheItem::tap: + return INPUTQUEUE->AllWerePressedRecently(controller, item.buttons, item.iNumButtons, item.fMaxSecondsBack); + default: + ASSERT(0); + return false; + } } void RefreshCacheItem( int iIndex ) @@ -83,7 +114,25 @@ void RefreshCacheItem( int iIndex ) CString sCodeName = g_sCodeNames[iIndex]; CString sButtonsNames = THEME->GetMetric("CodeDetector",sCodeName); CStringArray asButtonNames; - split( sButtonsNames, ",", asButtonNames, false ); + + bool bHasAPlus = sButtonsNames.Find( '+' ) != -1; + bool bHasADash = sButtonsNames.Find( '-' ) != -1; + + if( bHasAPlus ) + { + item.m_Type = CodeCacheItem::tap; + split( sButtonsNames, "+", asButtonNames, false ); + } + else if( bHasADash ) + { + item.m_Type = CodeCacheItem::hold_and_press; + split( sButtonsNames, "-", asButtonNames, false ); + } + else + { + item.m_Type = CodeCacheItem::sequence; + split( sButtonsNames, ",", asButtonNames, false ); + } if( asButtonNames.size() < 2 ) { @@ -116,7 +165,20 @@ void RefreshCacheItem( int iIndex ) } } - item.fMaxSecondsBack = item.iNumButtons*0.4f; + switch( item.m_Type ) + { + case CodeCacheItem::sequence: + item.fMaxSecondsBack = item.iNumButtons*0.4f; + break; + case CodeCacheItem::hold_and_press: + item.fMaxSecondsBack = -1.f; // not applicable + break; + case CodeCacheItem::tap: + item.fMaxSecondsBack = 0.03f; // simultaneous + break; + default: + ASSERT(0); + } // if we make it here, we found all the buttons in the code } @@ -147,6 +209,11 @@ bool CodeDetector::EnteredNextSort( GameController controller ) return EnteredCode(controller,CODE_NEXT_SORT1) || EnteredCode(controller,CODE_NEXT_SORT2); } +bool CodeDetector::EnteredAllSorts( GameController controller ) +{ + return EnteredCode(controller,CODE_ALL_SORTS1) || EnteredCode(controller,CODE_ALL_SORTS2); +} + #define TOGGLE(v,a,b) if(v!=a) v=a; else v=b; #define FLOAT_TOGGLE(v) if(v!=1.f) v=1.f; else v=0.f; // XXX: Read the metrics file instead! diff --git a/stepmania/src/CodeDetector.h b/stepmania/src/CodeDetector.h index 1ef102213f..63715d4b18 100644 --- a/stepmania/src/CodeDetector.h +++ b/stepmania/src/CodeDetector.h @@ -23,6 +23,8 @@ public: CODE_HARDER2, CODE_NEXT_SORT1, CODE_NEXT_SORT2, + CODE_ALL_SORTS1, + CODE_ALL_SORTS2, CODE_MIRROR, CODE_LEFT, CODE_RIGHT, @@ -57,6 +59,7 @@ public: static bool EnteredEasierDifficulty( GameController controller ); static bool EnteredHarderDifficulty( GameController controller ); static bool EnteredNextSort( GameController controller ); + static bool EnteredAllSorts( GameController controller ); static bool DetectAndAdjustMusicOptions( GameController controller ); static bool EnteredCode( GameController controller, Code code ); static bool EnteredNextBannerGroup( GameController controller ); diff --git a/stepmania/src/InputQueue.cpp b/stepmania/src/InputQueue.cpp index d0cafcc624..59002042af 100644 --- a/stepmania/src/InputQueue.cpp +++ b/stepmania/src/InputQueue.cpp @@ -36,7 +36,7 @@ void InputQueue::RememberInput( const GameInput GameI ) m_aQueue[c].push_back( GameButtonAndTime(GameI.button,RageTimer::GetTimeSinceStart()) ); } -bool InputQueue::MatchesPattern( const GameController c, const MenuButton* button_sequence, const int iNumButtons, float fMaxSecondsBack ) +bool InputQueue::MatchesSequence( GameController c, const MenuButton* button_sequence, const int iNumButtons, float fMaxSecondsBack ) { if( fMaxSecondsBack == -1 ) fMaxSecondsBack = 0.4f + iNumButtons*0.15f; @@ -65,7 +65,7 @@ bool InputQueue::MatchesPattern( const GameController c, const MenuButton* butto return false; } -bool InputQueue::MatchesPattern( const GameController c, const GameButton* button_sequence, const int iNumButtons, float fMaxSecondsBack ) +bool InputQueue::MatchesSequence( GameController c, const GameButton* button_sequence, const int iNumButtons, float fMaxSecondsBack ) { float fOldestTimeAllowed = RageTimer::GetTimeSinceStart() - fMaxSecondsBack; @@ -87,3 +87,29 @@ bool InputQueue::MatchesPattern( const GameController c, const GameButton* butto } return false; } + +bool InputQueue::AllWerePressedRecently( GameController c, const GameButton* buttons, int iNumButtons, float fMaxSecondsBack ) +{ + float fOldestTimeAllowed = RageTimer::GetTimeSinceStart() - fMaxSecondsBack; + + for( int b=0; b=0; queue_index-- ) // iterate newest to oldest + { + GameButtonAndTime BandT = m_aQueue[c][queue_index]; + if( BandT.fTime < fOldestTimeAllowed ) // buttons are too old. Stop searching because we're not going to find a match + return false; + + if( BandT.button == button ) + goto found_button; + } + return false; // didn't find the button +found_button: + ; // hush VC6 + } + + m_aQueue[c].clear(); // empty the queue so we don't match on it again + return true; +} diff --git a/stepmania/src/InputQueue.h b/stepmania/src/InputQueue.h index 3f9b7974e3..158d89de90 100644 --- a/stepmania/src/InputQueue.h +++ b/stepmania/src/InputQueue.h @@ -23,8 +23,9 @@ public: InputQueue(); void RememberInput( GameInput ); - bool MatchesPattern( const GameController c, const GameButton* button_sequence, const int iNumButtons, float fMaxSecondsBack ); - bool MatchesPattern( const GameController c, const MenuButton* button_sequence, const int iNumButtons, float fMaxSecondsBack ); + bool MatchesSequence( GameController c, const GameButton* button_sequence, int iNumButtons, float fMaxSecondsBack ); + bool MatchesSequence( GameController c, const MenuButton* button_sequence, int iNumButtons, float fMaxSecondsBack ); + bool AllWerePressedRecently( GameController c, const GameButton* buttons, int iNumButtons, float fMaxSecondsBack ); protected: struct GameButtonAndTime diff --git a/stepmania/src/ScreenSelectMaster.cpp b/stepmania/src/ScreenSelectMaster.cpp index 353c5e81a1..0101c836b6 100644 --- a/stepmania/src/ScreenSelectMaster.cpp +++ b/stepmania/src/ScreenSelectMaster.cpp @@ -383,13 +383,14 @@ bool ScreenSelectMaster::ChangeSelection( PlayerNumber pn, int iNewChoice ) if( GetPage(m_iChoice[pn]) != GetPage(iNewChoice) ) return ChangePage( iNewChoice ); + bool bMoveAll = SHARED_PREVIEW_AND_CURSOR || GetCurrentPage()!=PAGE_1; + for( int p=0; pIsHumanPlayer(p) ) continue; // skip - if( !SHARED_PREVIEW_AND_CURSOR && - (p!=pn && GetCurrentPage()==PAGE_1) ) + if( !bMoveAll && p!=pn ) continue; // skip const int iOldChoice = m_iChoice[p]; diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 7590e7a0a1..ed638673d3 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -653,7 +653,6 @@ void ScreenSelectMusic::Input( const DeviceInput& DeviceI, InputEventType type, dir--; m_MusicWheel.Move(dir); - return; } if( type == IET_RELEASE ) return; // don't care @@ -682,35 +681,46 @@ void ScreenSelectMusic::Input( const DeviceInput& DeviceI, InputEventType type, PlayerNumber pn = GAMESTATE->GetCurrentStyleDef()->ControllerToPlayerNumber( GameI.controller ); - if( CodeDetector::EnteredEasierDifficulty(GameI.controller) ) + if( type == IET_FIRST_PRESS ) { - if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) - m_soundLocked.Play(); - else - EasierDifficulty( pn ); - return; - } - if( CodeDetector::EnteredHarderDifficulty(GameI.controller) ) - { - if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) - m_soundLocked.Play(); - else - HarderDifficulty( pn ); - return; - } - if( CodeDetector::EnteredNextSort(GameI.controller) ) - { - if( ( GAMESTATE->IsExtraStage() && !PREFSMAN->m_bPickExtraStage ) || GAMESTATE->IsExtraStage2() ) - m_soundLocked.Play(); - else - m_MusicWheel.ChangeSort( SORT_MENU ); - return; - } - if( !GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2() && CodeDetector::DetectAndAdjustMusicOptions(GameI.controller) ) - { - m_soundOptionsChange.Play(); - UpdateOptionsDisplays(); - return; + if( CodeDetector::EnteredEasierDifficulty(GameI.controller) ) + { + if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) + m_soundLocked.Play(); + else + EasierDifficulty( pn ); + return; + } + if( CodeDetector::EnteredHarderDifficulty(GameI.controller) ) + { + if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) + m_soundLocked.Play(); + else + HarderDifficulty( pn ); + return; + } + if( CodeDetector::EnteredAllSorts(GameI.controller) ) + { + if( ( GAMESTATE->IsExtraStage() && !PREFSMAN->m_bPickExtraStage ) || GAMESTATE->IsExtraStage2() ) + m_soundLocked.Play(); + else + m_MusicWheel.ChangeSort( SORT_MENU ); + return; + } + if( CodeDetector::EnteredNextSort(GameI.controller) ) + { + if( ( GAMESTATE->IsExtraStage() && !PREFSMAN->m_bPickExtraStage ) || GAMESTATE->IsExtraStage2() ) + m_soundLocked.Play(); + else + m_MusicWheel.NextSort(); + return; + } + if( !GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2() && CodeDetector::DetectAndAdjustMusicOptions(GameI.controller) ) + { + m_soundOptionsChange.Play(); + UpdateOptionsDisplays(); + return; + } } Screen::Input( DeviceI, type, GameI, MenuI, StyleI ); // default input handler @@ -839,18 +849,18 @@ void ScreenSelectMusic::HandleScreenMessage( const ScreenMessage SM ) void ScreenSelectMusic::MenuStart( PlayerNumber pn ) { - if( pn != PLAYER_INVALID && - INPUTMAPPER->IsButtonDown( MenuInput(pn, MENU_BUTTON_LEFT) ) && - INPUTMAPPER->IsButtonDown( MenuInput(pn, MENU_BUTTON_RIGHT) ) ) - { +// if( pn != PLAYER_INVALID && +// INPUTMAPPER->IsButtonDown( MenuInput(pn, MENU_BUTTON_LEFT) ) && +// INPUTMAPPER->IsButtonDown( MenuInput(pn, MENU_BUTTON_RIGHT) ) ) +// { // if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) // m_soundLocked.Play(); // else - { - m_MusicWheel.NextSort(); - } - return; - } +// { +// m_MusicWheel.NextSort(); +// } +// return; +// } // this needs to check whether valid Steps are selected!