2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2002-04-16 17:31:00 +00:00
|
|
|
#include "InputFilter.h"
|
2002-05-01 19:14:55 +00:00
|
|
|
#include "RageLog.h"
|
2002-04-16 17:31:00 +00:00
|
|
|
#include "RageInput.h"
|
2005-06-06 18:30:12 +00:00
|
|
|
#include "RageUtil.h"
|
2003-07-26 21:58:48 +00:00
|
|
|
#include "RageThreads.h"
|
2005-09-19 07:09:55 +00:00
|
|
|
#include "Preference.h"
|
2005-10-24 06:32:30 +00:00
|
|
|
#include "Foreach.h"
|
2002-06-14 22:25:22 +00:00
|
|
|
|
2005-10-24 06:32:30 +00:00
|
|
|
#include <set>
|
2005-12-28 20:41:24 +00:00
|
|
|
struct ButtonState
|
|
|
|
|
{
|
|
|
|
|
ButtonState();
|
|
|
|
|
bool m_BeingHeld; // actual current state
|
|
|
|
|
bool m_bLastReportedHeld; // last state reported by Update()
|
2006-01-22 01:00:06 +00:00
|
|
|
RString m_sComment;
|
2005-12-28 20:41:24 +00:00
|
|
|
float m_fSecsHeld;
|
|
|
|
|
|
|
|
|
|
// Timestamp of m_BeingHeld changing.
|
|
|
|
|
RageTimer m_BeingHeldTime;
|
|
|
|
|
|
|
|
|
|
// The time that we actually reported the last event (used for debouncing).
|
|
|
|
|
RageTimer m_LastReportTime;
|
2006-09-08 01:39:32 +00:00
|
|
|
|
|
|
|
|
// The timestamp of the last reported change. Unlike m_BeingHeldTime, this
|
|
|
|
|
// value is debounced along with the input state. (This is the same as
|
|
|
|
|
// m_fSecsHeld, except this isn't affected by Update scaling.)
|
|
|
|
|
RageTimer m_LastInputTime;
|
2005-12-28 20:41:24 +00:00
|
|
|
};
|
|
|
|
|
|
2005-10-24 06:32:30 +00:00
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
/* Maintain a set of all interesting buttons: buttons which are being held
|
|
|
|
|
* down, or which were held down and need a RELEASE event. We use this to
|
|
|
|
|
* optimize InputFilter::Update, so we don't have to process every button
|
|
|
|
|
* we know about when most of them aren't in use. This set is protected
|
|
|
|
|
* by queuemutex. */
|
2005-12-28 20:41:24 +00:00
|
|
|
typedef map<DeviceInput, ButtonState> ButtonStateMap;
|
|
|
|
|
ButtonStateMap g_ButtonStates;
|
2006-09-02 19:34:54 +00:00
|
|
|
ButtonState &GetButtonState( const DeviceInput &di )
|
2005-10-24 06:32:30 +00:00
|
|
|
{
|
2006-09-02 19:34:54 +00:00
|
|
|
return g_ButtonStates[di];
|
2005-10-24 06:32:30 +00:00
|
|
|
}
|
2006-09-08 04:03:14 +00:00
|
|
|
|
|
|
|
|
DeviceInputList g_CurrentState;
|
2006-09-14 20:39:54 +00:00
|
|
|
set<DeviceInput> g_DisableRepeat;
|
2005-10-24 06:32:30 +00:00
|
|
|
}
|
2005-11-06 15:24:26 +00:00
|
|
|
|
2005-09-19 07:09:55 +00:00
|
|
|
/*
|
|
|
|
|
* Some input devices require debouncing. Do this on both press and release. After
|
|
|
|
|
* reporting a change in state, don't report another for the debounce period. If a
|
|
|
|
|
* button is reported pressed, report it. If the button is immediately reported
|
|
|
|
|
* released, wait a period before reporting it; if the button is repressed during
|
|
|
|
|
* that time, the release is never reported.
|
|
|
|
|
*
|
|
|
|
|
* The detail is important: if a button is pressed for 1ms and released, we must
|
|
|
|
|
* always report it, even if the debounce period is 10ms, since it might be a coin
|
|
|
|
|
* counter with a very short signal. The only time we discard events is if a button
|
|
|
|
|
* is pressed, released and then pressed again quickly.
|
|
|
|
|
*
|
|
|
|
|
* This delay in events is ordinarily not noticable, because the we report initial
|
|
|
|
|
* presses and releases immediately. However, if a real press is ever delayed,
|
|
|
|
|
* this won't cause timing problems, because the event timestamp is preserved.
|
|
|
|
|
*/
|
|
|
|
|
static Preference<float> g_fInputDebounceTime( "InputDebounceTime", 0 );
|
2002-04-16 17:31:00 +00:00
|
|
|
|
2002-05-19 01:59:48 +00:00
|
|
|
InputFilter* INPUTFILTER = NULL; // global and accessable from anywhere in our program
|
2002-04-16 17:31:00 +00:00
|
|
|
|
2006-09-13 02:59:05 +00:00
|
|
|
static const float TIME_BEFORE_REPEATS = 0.375f;
|
2003-11-25 21:46:30 +00:00
|
|
|
|
2005-09-22 23:22:18 +00:00
|
|
|
static const float REPEATS_PER_SEC = 8;
|
2003-11-25 21:46:30 +00:00
|
|
|
|
2006-09-13 02:49:05 +00:00
|
|
|
static float g_fTimeBeforeRepeats, g_fTimeBetweenRepeats;
|
2003-07-26 21:58:48 +00:00
|
|
|
|
|
|
|
|
|
2002-09-08 06:10:23 +00:00
|
|
|
InputFilter::InputFilter()
|
2003-06-22 04:38:05 +00:00
|
|
|
{
|
2004-03-21 04:10:43 +00:00
|
|
|
queuemutex = new RageMutex("InputFilter");
|
2003-09-03 21:49:11 +00:00
|
|
|
|
2003-07-26 22:29:34 +00:00
|
|
|
Reset();
|
2003-11-25 21:46:30 +00:00
|
|
|
ResetRepeatRate();
|
2003-07-26 21:58:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InputFilter::~InputFilter()
|
|
|
|
|
{
|
|
|
|
|
delete queuemutex;
|
2005-12-28 20:41:24 +00:00
|
|
|
g_ButtonStates.clear();
|
2003-06-22 04:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InputFilter::Reset()
|
2002-09-08 06:10:23 +00:00
|
|
|
{
|
2006-09-08 18:59:57 +00:00
|
|
|
for( int i=0; i<NUM_INPUT_DEVICES; i++ )
|
|
|
|
|
ResetDevice( InputDevice(i) );
|
2002-09-08 06:10:23 +00:00
|
|
|
}
|
|
|
|
|
|
2006-09-13 03:01:51 +00:00
|
|
|
void InputFilter::SetRepeatRate( float fDelay, float fRepeatRate )
|
2003-11-25 21:46:30 +00:00
|
|
|
{
|
2006-09-13 02:49:05 +00:00
|
|
|
g_fTimeBeforeRepeats = fDelay;
|
2005-09-22 23:22:18 +00:00
|
|
|
g_fTimeBetweenRepeats = 1/fRepeatRate;
|
2003-11-25 21:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InputFilter::ResetRepeatRate()
|
|
|
|
|
{
|
2006-09-13 03:01:51 +00:00
|
|
|
SetRepeatRate( TIME_BEFORE_REPEATS, REPEATS_PER_SEC );
|
2003-11-25 21:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
2005-12-28 20:41:24 +00:00
|
|
|
ButtonState::ButtonState():
|
2005-09-19 07:09:55 +00:00
|
|
|
m_BeingHeldTime(RageZeroTimer),
|
|
|
|
|
m_LastReportTime(RageZeroTimer)
|
|
|
|
|
{
|
|
|
|
|
m_BeingHeld = false;
|
|
|
|
|
m_bLastReportedHeld = false;
|
2006-09-08 18:49:14 +00:00
|
|
|
m_fSecsHeld = 0;
|
2005-09-19 07:09:55 +00:00
|
|
|
}
|
|
|
|
|
|
2005-10-15 16:47:44 +00:00
|
|
|
void InputFilter::ButtonPressed( const DeviceInput &di, bool Down )
|
2002-09-08 06:10:23 +00:00
|
|
|
{
|
2003-09-03 21:49:11 +00:00
|
|
|
LockMut(*queuemutex);
|
|
|
|
|
|
2005-05-17 20:50:39 +00:00
|
|
|
if( di.ts.IsZero() )
|
|
|
|
|
LOG->Warn( "InputFilter::ButtonPressed: zero timestamp is invalid" );
|
|
|
|
|
|
2005-12-28 09:53:03 +00:00
|
|
|
ASSERT_M( di.device < NUM_INPUT_DEVICES, ssprintf("%i", di.device) );
|
|
|
|
|
ASSERT_M( di.button < NUM_DeviceButton, ssprintf("%i", di.button) );
|
2005-06-08 06:29:48 +00:00
|
|
|
|
2006-09-02 19:34:54 +00:00
|
|
|
ButtonState &bs = GetButtonState( di );
|
2004-09-09 22:14:33 +00:00
|
|
|
|
2005-09-19 07:09:55 +00:00
|
|
|
if( bs.m_BeingHeld != Down )
|
|
|
|
|
{
|
2005-11-06 12:14:35 +00:00
|
|
|
/* Flush any delayed input, like Update() (in case Update() isn't being called). */
|
|
|
|
|
RageTimer now;
|
|
|
|
|
CheckButtonChange( bs, di, now );
|
|
|
|
|
|
2005-09-19 07:09:55 +00:00
|
|
|
bs.m_BeingHeld = Down;
|
|
|
|
|
bs.m_BeingHeldTime = di.ts;
|
2005-11-06 12:14:35 +00:00
|
|
|
|
|
|
|
|
/* Try to report presses immediately. */
|
|
|
|
|
CheckButtonChange( bs, di, now );
|
2005-09-19 07:09:55 +00:00
|
|
|
}
|
2003-09-03 21:49:11 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void InputFilter::SetButtonComment( const DeviceInput &di, const RString &sComment )
|
2005-05-08 09:19:35 +00:00
|
|
|
{
|
|
|
|
|
LockMut(*queuemutex);
|
2006-09-02 19:34:54 +00:00
|
|
|
ButtonState &bs = GetButtonState( di );
|
2005-05-08 09:19:35 +00:00
|
|
|
bs.m_sComment = sComment;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-08 18:59:57 +00:00
|
|
|
/* Release all buttons on the given device. */
|
|
|
|
|
void InputFilter::ResetDevice( InputDevice device )
|
|
|
|
|
{
|
|
|
|
|
LockMut(*queuemutex);
|
|
|
|
|
RageTimer now;
|
|
|
|
|
|
2006-09-15 22:51:29 +00:00
|
|
|
const ButtonStateMap ButtonStates( g_ButtonStates );
|
|
|
|
|
FOREACHM_CONST( DeviceInput, ButtonState, ButtonStates, b )
|
2006-09-08 18:59:57 +00:00
|
|
|
{
|
2006-09-08 19:02:11 +00:00
|
|
|
const DeviceInput &di = b->first;
|
|
|
|
|
if( di.device == device )
|
2006-09-15 22:52:05 +00:00
|
|
|
ButtonPressed( DeviceInput(device, di.button, 0, now), false );
|
2006-09-08 18:59:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-06 12:14:35 +00:00
|
|
|
/* 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,
|
2005-11-06 15:24:26 +00:00
|
|
|
* wait a while before sending it. */
|
2005-11-06 12:14:35 +00:00
|
|
|
if( now - bs.m_LastReportTime < g_fInputDebounceTime )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bs.m_LastReportTime = now;
|
|
|
|
|
bs.m_bLastReportedHeld = bs.m_BeingHeld;
|
|
|
|
|
bs.m_fSecsHeld = 0;
|
2006-09-08 01:39:32 +00:00
|
|
|
bs.m_LastInputTime = bs.m_BeingHeldTime;
|
2005-11-06 12:14:35 +00:00
|
|
|
|
|
|
|
|
di.ts = bs.m_BeingHeldTime;
|
2006-09-08 01:11:57 +00:00
|
|
|
ReportButtonChange( di, bs.m_bLastReportedHeld? IET_FIRST_PRESS:IET_RELEASE );
|
2006-09-14 20:39:54 +00:00
|
|
|
|
|
|
|
|
if( !bs.m_bLastReportedHeld )
|
|
|
|
|
g_DisableRepeat.erase( di );
|
2006-09-08 01:11:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InputFilter::ReportButtonChange( const DeviceInput &di, InputEventType t )
|
|
|
|
|
{
|
|
|
|
|
queue.push_back( InputEvent() );
|
|
|
|
|
InputEvent &ie = queue.back();
|
|
|
|
|
ie.type = t;
|
|
|
|
|
ie.di = di;
|
2006-09-08 04:03:14 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Include a list of all buttons that were pressed at the time of this event. We
|
|
|
|
|
* can create this efficiently using g_ButtonStates. Use a vector and not a
|
|
|
|
|
* map, for efficiency; most code will not use this information. Iterating over
|
|
|
|
|
* g_ButtonStates will be in DeviceInput order, so users can binary search this
|
|
|
|
|
* list (eg. std::lower_bound).
|
|
|
|
|
*/
|
|
|
|
|
MakeButtonStateList( ie.m_ButtonState );
|
|
|
|
|
g_CurrentState = ie.m_ButtonState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InputFilter::MakeButtonStateList( vector<DeviceInput> &aInputOut ) const
|
|
|
|
|
{
|
|
|
|
|
aInputOut.reserve( g_ButtonStates.size() );
|
|
|
|
|
for( ButtonStateMap::const_iterator it = g_ButtonStates.begin(); it != g_ButtonStates.end(); ++it )
|
|
|
|
|
{
|
|
|
|
|
const DeviceInput &di = it->first;
|
|
|
|
|
const ButtonState &bs = it->second;
|
|
|
|
|
if( !bs.m_bLastReportedHeld )
|
|
|
|
|
continue;
|
|
|
|
|
aInputOut.push_back( di );
|
|
|
|
|
aInputOut.back().ts = bs.m_LastInputTime;
|
|
|
|
|
}
|
2005-11-06 12:14:35 +00:00
|
|
|
}
|
|
|
|
|
|
2005-11-06 13:00:34 +00:00
|
|
|
void InputFilter::Update( float fDeltaTime )
|
2002-04-16 17:31:00 +00:00
|
|
|
{
|
2003-09-03 21:49:11 +00:00
|
|
|
RageTimer now;
|
|
|
|
|
|
2005-12-18 22:53:47 +00:00
|
|
|
INPUTMAN->Update();
|
2002-04-16 17:31:00 +00:00
|
|
|
|
2003-07-14 06:21:12 +00:00
|
|
|
/* Make sure that nothing gets inserted while we do this, to prevent
|
|
|
|
|
* things like "key pressed, key release, key repeat". */
|
2003-07-26 21:58:48 +00:00
|
|
|
LockMut(*queuemutex);
|
2003-07-14 06:21:12 +00:00
|
|
|
|
2005-12-28 08:52:20 +00:00
|
|
|
DeviceInput di( (InputDevice)0,DeviceButton_Invalid,1.0f,now);
|
2003-10-07 05:59:58 +00:00
|
|
|
|
2005-12-28 20:41:24 +00:00
|
|
|
vector<ButtonStateMap::iterator> ButtonsToErase;
|
|
|
|
|
|
|
|
|
|
FOREACHM( DeviceInput, ButtonState, g_ButtonStates, b )
|
2002-04-16 17:31:00 +00:00
|
|
|
{
|
2005-12-28 20:41:24 +00:00
|
|
|
di.device = b->first.device;
|
|
|
|
|
di.button = b->first.button;
|
|
|
|
|
ButtonState &bs = b->second;
|
2003-10-07 05:59:58 +00:00
|
|
|
|
2005-11-06 12:14:35 +00:00
|
|
|
/* Generate IET_FIRST_PRESS and IET_RELEASE events that were delayed. */
|
|
|
|
|
CheckButtonChange( bs, di, now );
|
2005-09-19 07:09:55 +00:00
|
|
|
|
2006-09-13 02:59:05 +00:00
|
|
|
/* Generate IET_REPEAT events. */
|
2005-10-24 06:32:30 +00:00
|
|
|
if( !bs.m_bLastReportedHeld )
|
|
|
|
|
{
|
2005-12-28 20:41:24 +00:00
|
|
|
// 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 )
|
|
|
|
|
ButtonsToErase.push_back( b );
|
2005-10-24 06:32:30 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2003-09-03 21:49:11 +00:00
|
|
|
|
2006-09-14 20:39:54 +00:00
|
|
|
/* If repeats are disabled for this button, skip. */
|
|
|
|
|
if( g_DisableRepeat.find(di) != g_DisableRepeat.end() )
|
|
|
|
|
continue;
|
|
|
|
|
|
2005-10-24 06:32:30 +00:00
|
|
|
const float fOldHoldTime = bs.m_fSecsHeld;
|
|
|
|
|
bs.m_fSecsHeld += fDeltaTime;
|
|
|
|
|
const float fNewHoldTime = bs.m_fSecsHeld;
|
2002-04-16 17:31:00 +00:00
|
|
|
|
2006-09-13 03:04:04 +00:00
|
|
|
if( fNewHoldTime <= g_fTimeBeforeRepeats )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
float fRepeatTime;
|
|
|
|
|
if( fOldHoldTime < g_fTimeBeforeRepeats )
|
|
|
|
|
{
|
|
|
|
|
fRepeatTime = g_fTimeBeforeRepeats;
|
|
|
|
|
}
|
|
|
|
|
else
|
2005-10-24 06:32:30 +00:00
|
|
|
{
|
2006-09-13 03:04:04 +00:00
|
|
|
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 );
|
2002-04-16 17:31:00 +00:00
|
|
|
}
|
2006-09-13 03:04:04 +00:00
|
|
|
|
|
|
|
|
/* 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 );
|
2002-04-16 17:31:00 +00:00
|
|
|
}
|
2005-12-28 20:41:24 +00:00
|
|
|
|
|
|
|
|
FOREACH( ButtonStateMap::iterator, ButtonsToErase, it )
|
|
|
|
|
g_ButtonStates.erase( *it );
|
2003-02-16 01:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
2006-09-08 04:03:14 +00:00
|
|
|
template<typename T, typename IT>
|
|
|
|
|
const T *FindItemBinarySearch( IT begin, IT end, const T &i )
|
|
|
|
|
{
|
|
|
|
|
IT it = lower_bound( begin, end, i );
|
|
|
|
|
if( it == end || *it != i )
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return &*it;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-08 04:26:23 +00:00
|
|
|
bool InputFilter::IsBeingPressed( const DeviceInput &di, const DeviceInputList *pButtonState ) const
|
2003-02-16 01:35:48 +00:00
|
|
|
{
|
2005-12-28 20:41:24 +00:00
|
|
|
LockMut(*queuemutex);
|
2006-09-08 04:03:14 +00:00
|
|
|
if( pButtonState == NULL )
|
|
|
|
|
pButtonState = &g_CurrentState;
|
|
|
|
|
const DeviceInput *pDI = FindItemBinarySearch( pButtonState->begin(), pButtonState->end(), di );
|
|
|
|
|
return pDI != NULL;
|
2003-02-16 01:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
2006-09-08 04:26:23 +00:00
|
|
|
float InputFilter::GetSecsHeld( const DeviceInput &di, const DeviceInputList *pButtonState ) const
|
2003-02-16 01:35:48 +00:00
|
|
|
{
|
2005-12-28 20:41:24 +00:00
|
|
|
LockMut(*queuemutex);
|
2006-09-08 04:03:14 +00:00
|
|
|
if( pButtonState == NULL )
|
|
|
|
|
pButtonState = &g_CurrentState;
|
|
|
|
|
const DeviceInput *pDI = FindItemBinarySearch( pButtonState->begin(), pButtonState->end(), di );
|
|
|
|
|
if( pDI == NULL )
|
|
|
|
|
return 0;
|
|
|
|
|
return pDI->ts.Ago();
|
2003-02-16 01:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString InputFilter::GetButtonComment( const DeviceInput &di ) const
|
2005-05-08 09:19:35 +00:00
|
|
|
{
|
|
|
|
|
LockMut(*queuemutex);
|
2006-09-02 19:34:54 +00:00
|
|
|
return GetButtonState( di ).m_sComment;
|
2005-05-08 09:19:35 +00:00
|
|
|
}
|
|
|
|
|
|
2005-10-15 16:47:44 +00:00
|
|
|
void InputFilter::ResetKeyRepeat( const DeviceInput &di )
|
2003-11-25 21:46:30 +00:00
|
|
|
{
|
2005-12-28 20:41:24 +00:00
|
|
|
LockMut(*queuemutex);
|
2006-09-02 19:34:54 +00:00
|
|
|
GetButtonState( di ).m_fSecsHeld = 0;
|
2003-11-25 21:46:30 +00:00
|
|
|
}
|
|
|
|
|
|
2006-09-14 20:39:54 +00:00
|
|
|
/* Stop repeating the specified key until released. */
|
|
|
|
|
void InputFilter::RepeatStopKey( const DeviceInput &di )
|
|
|
|
|
{
|
|
|
|
|
LockMut(*queuemutex);
|
|
|
|
|
|
|
|
|
|
/* If the button is up, do nothing. */
|
|
|
|
|
ButtonState &bs = GetButtonState( di );
|
|
|
|
|
if( !bs.m_bLastReportedHeld )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_DisableRepeat.insert( di );
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-07 23:58:46 +00:00
|
|
|
void InputFilter::GetInputEvents( vector<InputEvent> &array )
|
2003-02-16 01:35:48 +00:00
|
|
|
{
|
2006-09-02 19:49:46 +00:00
|
|
|
array.clear();
|
2003-07-26 21:58:48 +00:00
|
|
|
LockMut(*queuemutex);
|
2006-09-02 19:49:46 +00:00
|
|
|
array.swap( queue );
|
2002-07-31 19:40:40 +00:00
|
|
|
}
|
2004-06-08 01:24:17 +00:00
|
|
|
|
2006-09-08 18:54:01 +00:00
|
|
|
void InputFilter::GetPressedButtons( vector<DeviceInput> &array ) const
|
2005-12-28 20:41:24 +00:00
|
|
|
{
|
|
|
|
|
LockMut(*queuemutex);
|
2006-09-08 04:26:23 +00:00
|
|
|
array = g_CurrentState;
|
2005-12-28 20:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-08 01:24:17 +00:00
|
|
|
/*
|
|
|
|
|
* (c) 2001-2004 Chris Danford
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
|
|
|
* whom the Software is furnished to do so, provided that the above
|
|
|
|
|
* copyright notice(s) and this permission notice appear in all copies of
|
|
|
|
|
* the Software and that both the above copyright notice(s) and this
|
|
|
|
|
* permission notice appear in supporting documentation.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
|
|
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
|
|
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
|
|
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*/
|