Files
itgmania212121/stepmania/src/InputFilter.cpp
T

195 lines
5.5 KiB
C++
Raw Normal View History

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"
2003-07-26 21:58:48 +00:00
#include "RageThreads.h"
2002-06-14 22:25:22 +00:00
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
static const float TIME_BEFORE_SLOW_REPEATS = 0.25f;
static const float TIME_BEFORE_FAST_REPEATS = 1.5f;
static const float SLOW_REPEATS_PER_SEC = 8;
static const float FAST_REPEATS_PER_SEC = 8;
static float g_fTimeBeforeSlow, g_fTimeBeforeFast, g_fTimeBetweenSlow, g_fTimeBetweenFast;
2003-07-26 21:58:48 +00:00
InputFilter::InputFilter()
2003-06-22 04:38:05 +00:00
{
queuemutex = new RageMutex("InputFilter");
2004-09-09 22:14:33 +00:00
memset( m_ButtonState, 0, sizeof(m_ButtonState) );
2003-09-03 21:49:11 +00:00
2003-07-26 22:29:34 +00:00
Reset();
ResetRepeatRate();
2003-07-26 21:58:48 +00:00
}
InputFilter::~InputFilter()
{
delete queuemutex;
2003-06-22 04:38:05 +00:00
}
void InputFilter::Reset()
{
for( int i=0; i<NUM_INPUT_DEVICES; i++ )
ResetDevice( InputDevice(i) );
}
void InputFilter::SetRepeatRate( float fSlowDelay, float fSlowRate, float fFastDelay, float fFastRate )
{
g_fTimeBeforeSlow = fSlowDelay;
g_fTimeBeforeFast = fFastDelay;
g_fTimeBetweenSlow = 1/fSlowRate;
g_fTimeBetweenFast = 1/fFastRate;
}
void InputFilter::ResetRepeatRate()
{
SetRepeatRate( TIME_BEFORE_SLOW_REPEATS, SLOW_REPEATS_PER_SEC, TIME_BEFORE_FAST_REPEATS, FAST_REPEATS_PER_SEC );
}
void InputFilter::ButtonPressed( DeviceInput di, bool Down )
{
2003-09-03 21:49:11 +00:00
LockMut(*queuemutex);
2004-09-09 22:14:33 +00:00
ButtonState &bs = m_ButtonState[di.device][di.button];
bs.m_Level = di.level;
if( bs.m_BeingHeld == Down )
return;
2004-09-09 22:14:33 +00:00
bs.m_BeingHeld = Down;
bs.m_fSecsHeld = 0;
2004-09-25 06:40:18 +00:00
queue.push_back( InputEvent(di,Down? IET_FIRST_PRESS:IET_RELEASE) );
2003-09-03 21:49:11 +00:00
}
2003-06-21 20:58:40 +00:00
/* Release all buttons on the given device. */
void InputFilter::ResetDevice( InputDevice dev )
{
2003-10-07 05:59:58 +00:00
for( int button = 0; button < NUM_DEVICE_BUTTONS[dev]; ++button )
2003-06-21 20:58:40 +00:00
ButtonPressed( DeviceInput(dev, button), false );
}
void InputFilter::Update(float fDeltaTime)
2002-04-16 17:31:00 +00:00
{
2003-09-03 21:49:11 +00:00
RageTimer now;
2003-09-07 19:35:32 +00:00
// Constructing the DeviceInput inside the nested loops caues terrible
// performance. So, construct it once outside the loop, then change
// .device and .button inside the loop. I have no idea what is causing
// the slowness. DeviceInput is a very small and simple structure, but
// it's constructor was being called NUM_INPUT_DEVICES*NUM_DEVICE_BUTTONS
// (>2000) times per Update().
2003-09-28 23:23:21 +00:00
/* This should be fixed: DeviceInput's ctor uses an init list, so RageTimer
* isn't initialized each time. */
// DeviceInput di( (InputDevice)0,0,now);
2003-09-07 19:35:32 +00:00
INPUTMAN->Update( fDeltaTime );
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
2003-10-07 05:59:58 +00:00
// Don't reconstruct "di" inside the loop. This line alone is
// taking 4% of the CPU on a P3-666.
2004-09-09 22:14:33 +00:00
DeviceInput di( (InputDevice)0,0,1.0f,now);
2003-10-07 05:59:58 +00:00
2002-04-16 17:31:00 +00:00
for( int d=0; d<NUM_INPUT_DEVICES; d++ ) // foreach InputDevice
{
2003-10-07 05:59:58 +00:00
di.device = (InputDevice)d;
for( int b=0; b < NUM_DEVICE_BUTTONS[d]; b++ ) // foreach button
2002-04-16 17:31:00 +00:00
{
2004-09-09 22:14:33 +00:00
ButtonState &bs = m_ButtonState[d][b];
2003-10-07 05:59:58 +00:00
di.button = b;
2004-09-09 22:14:33 +00:00
di.level = bs.m_Level;
/* Generate IET_LEVEL_CHANGED events. */
if( bs.m_LastLevel != bs.m_Level )
{
queue.push_back( InputEvent(di,IET_LEVEL_CHANGED) );
bs.m_LastLevel = bs.m_Level;
}
2003-09-03 21:49:11 +00:00
2004-09-09 22:14:33 +00:00
/* Generate IET_FAST_REPEAT and IET_SLOW_REPEAT events. */
if( !bs.m_BeingHeld )
continue;
2002-04-16 17:31:00 +00:00
2004-09-09 22:14:33 +00:00
const float fOldHoldTime = bs.m_fSecsHeld;
bs.m_fSecsHeld += fDeltaTime;
const float fNewHoldTime = bs.m_fSecsHeld;
float fTimeBetweenRepeats;
InputEventType iet;
if( fOldHoldTime > g_fTimeBeforeSlow )
2002-04-16 17:31:00 +00:00
{
if( fOldHoldTime > g_fTimeBeforeFast )
2002-04-16 17:31:00 +00:00
{
fTimeBetweenRepeats = g_fTimeBetweenFast;
iet = IET_FAST_REPEAT;
2002-04-16 17:31:00 +00:00
}
else
{
fTimeBetweenRepeats = g_fTimeBetweenSlow;
iet = IET_SLOW_REPEAT;
2002-08-21 22:49:13 +00:00
}
if( int(fOldHoldTime/fTimeBetweenRepeats) != int(fNewHoldTime/fTimeBetweenRepeats) )
2003-07-14 06:21:12 +00:00
{
queue.push_back( InputEvent(di,iet) );
}
2002-04-16 17:31:00 +00:00
}
}
}
}
bool InputFilter::IsBeingPressed( DeviceInput di )
{
2004-09-09 22:14:33 +00:00
return m_ButtonState[di.device][di.button].m_BeingHeld;
}
float InputFilter::GetSecsHeld( DeviceInput di )
{
2004-09-09 22:14:33 +00:00
return m_ButtonState[di.device][di.button].m_fSecsHeld;
}
void InputFilter::ResetKeyRepeat( DeviceInput di )
{
2004-09-09 22:14:33 +00:00
m_ButtonState[di.device][di.button].m_fSecsHeld = 0;
}
void InputFilter::GetInputEvents( InputEventArray &array )
{
2003-07-26 21:58:48 +00:00
LockMut(*queuemutex);
array = queue;
queue.clear();
}
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.
*/