/** @brief Check for reportable presses. */ void InputFilter::CheckButtonChange( ButtonState &bs, DeviceInput di, const RageTimer &now ) { if( bs.m_BeingHeld == bs.m_bLastReportedHeld ) return; /* If the last IET_FIRST_PRESS or IET_RELEASE event was sent too recently, * wait a while before sending it. */ if( now - bs.m_LastReportTime < g_fInputDebounceTime ) return; bs.m_LastReportTime = now; bs.m_bLastReportedHeld = bs.m_BeingHeld; bs.m_fSecsHeld = 0; bs.m_LastInputTime = bs.m_BeingHeldTime; di.ts = bs.m_BeingHeldTime; if( !bs.m_bLastReportedHeld ) di.level = 0; MakeButtonStateList( g_CurrentState ); ReportButtonChange( di, bs.m_bLastReportedHeld? IET_FIRST_PRESS:IET_RELEASE ); if( !bs.m_bLastReportedHeld ) g_DisableRepeat.erase( di ); }
/** @brief Check for reportable presses. */ void InputFilter::CheckButtonChange( ButtonState &bs, DeviceInput di, const RageTimer &now ) { if( bs.m_BeingHeld == bs.m_bLastReportedHeld ) return; GameInput gi; /* Possibly apply debounce, * If the input was coin, possibly apply distinct coin debounce in the else below. */ if (! INPUTMAPPER->DeviceToGame(di, gi) || gi.button != GAME_BUTTON_COIN ) { /* If the last IET_FIRST_PRESS or IET_RELEASE event was sent too recently, * wait a while before sending it. */ if( now - bs.m_LastReportTime < g_fInputDebounceTime ) { return; } } else { if( now - bs.m_LastReportTime < PREFSMAN->m_fDebounceCoinInputTime ) { return; } } bs.m_LastReportTime = now; bs.m_bLastReportedHeld = bs.m_BeingHeld; bs.m_fSecsHeld = 0; bs.m_LastInputTime = bs.m_BeingHeldTime; di.ts = bs.m_BeingHeldTime; if( !bs.m_bLastReportedHeld ) di.level = 0; MakeButtonStateList( g_CurrentState ); ReportButtonChange( di, bs.m_bLastReportedHeld? IET_FIRST_PRESS:IET_RELEASE ); if( !bs.m_bLastReportedHeld ) g_DisableRepeat.erase( di ); }
void InputFilter::Update( float fDeltaTime ) { RageTimer now; INPUTMAN->Update(); /* Make sure that nothing gets inserted while we do this, to prevent things * like "key pressed, key release, key repeat". */ LockMut(*queuemutex); DeviceInput di( InputDevice_Invalid, DeviceButton_Invalid, 1.0f, now ); MakeButtonStateList( g_CurrentState ); vector<ButtonStateMap::iterator> ButtonsToErase; FOREACHM( DeviceButtonPair, ButtonState, g_ButtonStates, b ) { di.device = b->first.device; di.button = b->first.button; ButtonState &bs = b->second; // Generate IET_FIRST_PRESS and IET_RELEASE events that were delayed. CheckButtonChange( bs, di, now ); // Generate IET_REPEAT events. if( !bs.m_bLastReportedHeld ) { // If the key isn't pressed, and hasn't been pressed for a while // (so debouncing isn't interested in it), purge the entry. if( now - bs.m_LastReportTime > g_fInputDebounceTime && bs.m_DeviceInput.level == 0.0f ) ButtonsToErase.push_back( b ); continue; } // If repeats are disabled for this button, skip. if( g_DisableRepeat.find(di) != g_DisableRepeat.end() ) continue; const float fOldHoldTime = bs.m_fSecsHeld; bs.m_fSecsHeld += fDeltaTime; const float fNewHoldTime = bs.m_fSecsHeld; if( fNewHoldTime <= g_fTimeBeforeRepeats ) continue; float fRepeatTime; if( fOldHoldTime < g_fTimeBeforeRepeats ) { fRepeatTime = g_fTimeBeforeRepeats; } else { float fAdjustedOldHoldTime = fOldHoldTime - g_fTimeBeforeRepeats; float fAdjustedNewHoldTime = fNewHoldTime - g_fTimeBeforeRepeats; if( int(fAdjustedOldHoldTime/g_fTimeBetweenRepeats) == int(fAdjustedNewHoldTime/g_fTimeBetweenRepeats) ) continue; fRepeatTime = ftruncf( fNewHoldTime, g_fTimeBetweenRepeats ); } /* Set the timestamp to the exact time of the repeat. This way, as long * as tab/` aren't being used, the timestamp will always increase steadily * during repeats. */ di.ts = bs.m_LastInputTime + fRepeatTime; ReportButtonChange( di, IET_REPEAT ); }