From 223f4b57c285ca1ed07c0421cb34111a8687c99a Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Thu, 15 Mar 2007 20:38:12 +0000 Subject: [PATCH] unify code types --- stepmania/src/CodeDetector.cpp | 158 ++++++++++++++++++++++++--------- stepmania/src/CodeDetector.h | 15 ++-- stepmania/src/InputQueue.cpp | 7 +- stepmania/src/InputQueue.h | 2 + 4 files changed, 130 insertions(+), 52 deletions(-) diff --git a/stepmania/src/CodeDetector.cpp b/stepmania/src/CodeDetector.cpp index 12c6321485..cbd900bcba 100644 --- a/stepmania/src/CodeDetector.cpp +++ b/stepmania/src/CodeDetector.cpp @@ -10,6 +10,7 @@ #include "RageUtil.h" #include "PlayerState.h" #include "InputEventPlus.h" +#include "Foreach.h" const char *CodeNames[] = { "Easier1", @@ -56,46 +57,103 @@ XToString( Code ); static CodeItem g_CodeItems[NUM_Code]; +static const float g_fSimultaneousThreshold = 0.05f; bool CodeItem::EnteredCode( GameController controller ) const { if( controller == GameController_Invalid ) return false; - if( buttons.size() == 0 ) + if( m_aPresses.size() == 0 ) return false; - switch( m_Type ) - { - case sequence: - return INPUTQUEUE->MatchesSequence( controller, &buttons[0], buttons.size(), fMaxSecondsBack ); - case hold_and_press: - { - RageTimer OldestTimeAllowed = RageTimer() - 0.05f; - InputEventPlus iep; - if( !INPUTQUEUE->WasPressedRecently(controller, buttons[buttons.size()-1], OldestTimeAllowed, &iep) ) - return false; + RageTimer OldestTimeAllowed; + OldestTimeAllowed += -fMaxSecondsBack; - // Check that all but the last were being held when the last button was pressed. - for( unsigned i=0; i &aQueue = INPUTQUEUE->GetQueue( controller ); + int iQueueIndex = aQueue.size()-1; + while( iQueueIndex >= 0 ) + { + { + const InputEventPlus &iep = aQueue[iQueueIndex]; + if( iep.DeviceI.ts < OldestTimeAllowed ) + return false; + } + + /* Search backwards for all of Press.m_aButtonsToPress pressed within g_fTapThreshold seconds + * with m_aButtonsToHold pressed. */ + const ButtonPress &Press = m_aPresses[iSequenceIndex]; + bool bMatched = false; + int iMinSearchIndexUsed = iQueueIndex; + for( int b=0; b<(int) Press.m_aButtonsToPress.size(); ++b ) + { + /* Search backwards for the buttons in this tap, within the tap threshold since iQueueIndex. */ + RageTimer OldestTimeAllowedForTap( aQueue[iQueueIndex].DeviceI.ts ); + OldestTimeAllowedForTap += -g_fSimultaneousThreshold; + + const InputEventPlus *pIEP = NULL; + int iQueueSearchIndex = iQueueIndex; + for( ; iQueueSearchIndex>=0; --iQueueSearchIndex ) // iterate newest to oldest { - GameInput gi( controller, buttons[i] ); - if( !INPUTMAPPER->IsBeingPressed(gi, MultiPlayer_Invalid, &iep.InputList) ) - return false; + const InputEventPlus &iep = aQueue[iQueueSearchIndex]; + if( iep.DeviceI.ts < OldestTimeAllowedForTap ) // buttons are too old. Stop searching because we're not going to find a match + break; + + if( iep.GameI.button == Press.m_aButtonsToPress[b] ) + { + pIEP = &iep; + break; + } } + if( pIEP == NULL ) + break; // didn't find the button + + // Check that m_aButtonsToHold were being held when the buttons were pressed. + bool bAllButtonsPressed = true; + for( unsigned i=0; iIsBeingPressed(gi, MultiPlayer_Invalid, &pIEP->InputList) ) + bAllButtonsPressed = false; + } + if( !bAllButtonsPressed ) + continue; + if( b == (int) Press.m_aButtonsToPress.size()-1 ) + { + bMatched = true; + iMinSearchIndexUsed = min( iMinSearchIndexUsed, iQueueSearchIndex ); + } + } + + if( !bMatched ) + { + /* The press wasn't matched. If m_bAllowIntermediatePresses is true, + * skip the last press, and look again. */ + if( !Press.m_bAllowIntermediatePresses ) + return false; + --iQueueIndex; + continue; + } + + if( iSequenceIndex == 0 ) + { + // we matched the whole pattern. Empty the queue so we don't match on it again. + INPUTQUEUE->ClearQueue( controller ); return true; } - break; - case tap: - return INPUTQUEUE->AllWerePressedRecently( controller, &buttons[0], buttons.size(), fMaxSecondsBack ); - default: - ASSERT(0); - return false; + + /* The press was matched. */ + iQueueIndex = iMinSearchIndexUsed - 1; + --iSequenceIndex; } + + return false; } bool CodeItem::Load( RString sButtonsNames ) { - buttons.clear(); + m_aPresses.clear(); vector asButtonNames; @@ -104,27 +162,28 @@ bool CodeItem::Load( RString sButtonsNames ) if( bHasAPlus ) { - m_Type = tap; + // press all buttons simultaneously split( sButtonsNames, "+", asButtonNames, false ); } else if( bHasADash ) { - m_Type = hold_and_press; + // hold the first iNumButtons-1 buttons, then press the last split( sButtonsNames, "-", asButtonNames, false ); } else { - m_Type = sequence; + // press the buttons in sequence split( sButtonsNames, ",", asButtonNames, false ); } if( asButtonNames.size() < 1 ) { if( sButtonsNames != "" ) - LOG->Trace( "The code '%s' is less than 2 buttons, so it will be ignored.", sButtonsNames.c_str() ); + LOG->Trace( "Ignoring empty code \"%s\".", sButtonsNames.c_str() ); return false; } + vector buttons; for( unsigned i=0; iGetInputScheme()->ButtonNameToIndex( sButtonName ); if( gb == GameButton_Invalid ) { - LOG->Trace( "The code '%s' contains an unrecognized button '%s'.", sButtonsNames.c_str(), sButtonName.c_str() ); - buttons.clear(); + LOG->Trace( "The code \"%s\" contains an unrecognized button \"%s\".", sButtonsNames.c_str(), sButtonName.c_str() ); + m_aPresses.clear(); return false; } buttons.push_back( gb ); } - switch( m_Type ) + if( bHasAPlus ) { - case sequence: - if( buttons.size() == 1 ) - fMaxSecondsBack = -1; - else - fMaxSecondsBack = (buttons.size()-1)*0.6f; - break; - case hold_and_press: - fMaxSecondsBack = -1.f; // not applicable - break; - case tap: - fMaxSecondsBack = 0.05f; // simultaneous - break; - default: - ASSERT(0); + m_aPresses.push_back( ButtonPress() ); + FOREACH( GameButton, buttons, gb ) + { + m_aPresses.back().m_aButtonsToPress.push_back( *gb ); + } } + else if( bHasADash ) + { + m_aPresses.push_back( ButtonPress() ); + m_aPresses.back().m_aButtonsToHold.insert( m_aPresses.back().m_aButtonsToHold.begin(), buttons.begin(), buttons.end()-1 ); + m_aPresses.back().m_aButtonsToPress.push_back( buttons.back() ); + } + else + { + FOREACH( GameButton, buttons, gb ) + { + m_aPresses.push_back( ButtonPress() ); + m_aPresses.back().m_aButtonsToPress.push_back( *gb ); + m_aPresses.back().m_bAllowIntermediatePresses = false; + } + } + + if( m_aPresses.size() == 1 ) + fMaxSecondsBack = 0.55f; + else + fMaxSecondsBack = (m_aPresses.size()-1)*0.6f; // if we make it here, we found all the buttons in the code return true; diff --git a/stepmania/src/CodeDetector.h b/stepmania/src/CodeDetector.h index a64f951303..fb3c37faee 100644 --- a/stepmania/src/CodeDetector.h +++ b/stepmania/src/CodeDetector.h @@ -56,14 +56,15 @@ public: bool EnteredCode( GameController controller ) const; private: - vector buttons; - 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 + struct ButtonPress + { + ButtonPress() { m_bAllowIntermediatePresses = true; } + vector m_aButtonsToHold; + vector m_aButtonsToPress; + bool m_bAllowIntermediatePresses; }; - Type m_Type; + vector m_aPresses; + float fMaxSecondsBack; }; diff --git a/stepmania/src/InputQueue.cpp b/stepmania/src/InputQueue.cpp index ba82bf2cc9..60b2821006 100644 --- a/stepmania/src/InputQueue.cpp +++ b/stepmania/src/InputQueue.cpp @@ -82,10 +82,15 @@ bool InputQueue::AllWerePressedRecently( GameController c, const GameButton* but return false; // didn't find the button } - m_aQueue[c].clear(); // empty the queue so we don't match on it again + ClearQueue( c ); // empty the queue so we don't match on it again return true; } +void InputQueue::ClearQueue( GameController c ) +{ + m_aQueue[c].clear(); +} + /* * (c) 2001-2003 Chris Danford * All rights reserved. diff --git a/stepmania/src/InputQueue.h b/stepmania/src/InputQueue.h index fec798a794..5058a61aa8 100644 --- a/stepmania/src/InputQueue.h +++ b/stepmania/src/InputQueue.h @@ -18,6 +18,8 @@ public: bool MatchesSequence( GameController c, const GameButton* button_sequence, int iNumButtons, float fMaxSecondsBack ); bool WasPressedRecently( GameController c, const GameButton button, const RageTimer &OldestTimeAllowed, InputEventPlus *pIEP = NULL ); bool AllWerePressedRecently( GameController c, const GameButton* buttons, int iNumButtons, float fMaxSecondsBack ); + const vector &GetQueue( GameController c ) const { return m_aQueue[c]; } + void ClearQueue( GameController c ); protected: vector m_aQueue[NUM_GameController];