Apply patch by Lilian Gimenez to support gamepad triggers in input code

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@13054 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2013-07-01 22:50:59 +00:00
parent ae0cfe90da
commit a27853a592
14 changed files with 145 additions and 58 deletions

View File

@ -47,6 +47,7 @@ irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action)
const Input::InputType type = m_bindings[action].getType();
const int id = m_bindings[action].getId();
const Input::AxisDirection dir = m_bindings[action].getDirection();
const Input::AxisRange range = m_bindings[action].getRange();
switch (type)
{
@ -60,6 +61,8 @@ irr::core::stringw DeviceConfig::getMappingIdString (const PlayerAction action)
returnString += id;
returnString += "$";
returnString += dir;
returnString += "$";
returnString += range;
break;
case Input::IT_STICKBUTTON:
@ -114,9 +117,10 @@ void DeviceConfig::setBinding ( const PlayerAction action,
const Input::InputType type,
const int id,
Input::AxisDirection direction,
Input::AxisRange range,
wchar_t character)
{
m_bindings[action].set(type, id, direction, character);
m_bindings[action].set(type, id, direction, range, character);
}
//------------------------------------------------------------------------------
@ -124,7 +128,7 @@ void DeviceConfig::setBinding ( const PlayerAction action,
// Don't call this directly unless you are KeyboardDevice or GamepadDevice
bool DeviceConfig::getGameAction(Input::InputType type,
const int id,
const int value,
int* value, /* inout */
PlayerAction* action /* out */ )
{
return doGetAction(type, id, value, PA_FIRST_GAME_ACTION, PA_LAST_GAME_ACTION, action);
@ -135,7 +139,7 @@ bool DeviceConfig::getGameAction(Input::InputType type,
// Don't call this directly unless you are KeyboardDevice or GamepadDevice
bool DeviceConfig::getMenuAction(Input::InputType type,
const int id,
const int value,
int* value,
PlayerAction* action /* out */ )
{
return doGetAction(type, id, value, PA_FIRST_MENU_ACTION, PA_LAST_MENU_ACTION, action);
@ -145,7 +149,7 @@ bool DeviceConfig::getMenuAction(Input::InputType type,
bool DeviceConfig::doGetAction(Input::InputType type,
const int id,
const int value,
int* value, /* inout */
const PlayerAction firstActionToCheck,
const PlayerAction lastActionToCheck,
PlayerAction* action /* out */ )
@ -162,13 +166,30 @@ bool DeviceConfig::doGetAction(Input::InputType type,
if (type == Input::IT_STICKMOTION)
{
if ( ((m_bindings[n].getDirection() == Input::AD_POSITIVE)
&& (value > 0)) ||
((m_bindings[n].getDirection() == Input::AD_NEGATIVE)
&& (value < 0)) )
if(m_bindings[n].getRange() == Input::AR_HALF)
{
success = true;
*action = (PlayerAction)n;
if ( ((m_bindings[n].getDirection() == Input::AD_POSITIVE)
&& (*value > 0)) ||
((m_bindings[n].getDirection() == Input::AD_NEGATIVE)
&& (*value < 0)) )
{
success = true;
*action = (PlayerAction)n;
}
}
else
{
if ( ((m_bindings[n].getDirection() == Input::AD_POSITIVE)
&& (*value != -Input::MAX_VALUE)) ||
((m_bindings[n].getDirection() == Input::AD_NEGATIVE)
&& (*value != Input::MAX_VALUE)) )
{
success = true;
*action = (PlayerAction)n;
if(m_bindings[n].getDirection() == Input::AD_NEGATIVE)
*value = -*value;
*value = (*value + Input::MAX_VALUE) / 2;
}
}
}
else

View File

@ -68,7 +68,7 @@ protected:
*/
bool doGetAction(Input::InputType type,
const int id,
const int value,
int* value, /* inout */
const PlayerAction firstActionToCheck,
const PlayerAction lastActionToCheck,
PlayerAction* action /* out */ );
@ -92,6 +92,7 @@ public:
const Input::InputType type,
const int id,
Input::AxisDirection direction = Input::AD_NEUTRAL,
Input::AxisRange range = Input::AR_HALF,
wchar_t character=0);
void setPlugged () { m_plugged++; }
@ -106,7 +107,7 @@ public:
*/
bool getGameAction (Input::InputType type,
const int id,
const int value,
int* value, /* inout */
PlayerAction* action /* out */);
/**
@ -117,7 +118,7 @@ public:
*/
bool getMenuAction (Input::InputType type,
const int id,
const int value,
int* value,
PlayerAction* action /* out */);
Binding& getBinding (int i) {return m_bindings[i];}

View File

@ -31,10 +31,11 @@ void Binding::serialize(std::ofstream& stream) const
<< "event=\"" << m_type << "\" "
<< "character=\"" << m_character << "\" ";
// Only serialize the direction for stick motions
// Only serialize the direction and the range for stick motions
if (m_type == Input::IT_STICKMOTION)
{
stream << "direction=\"" << m_dir << "\" ";
stream << "range=\"" << m_range << "\" ";
}
} // serialize
@ -44,6 +45,7 @@ bool Binding::deserialize(irr::io::IrrXMLReader* xml)
const char *id_string = xml->getAttributeValue("id");
const char *event_string = xml->getAttributeValue("event");
const char *dir_string = xml->getAttributeValue("direction");
const char *range_string = xml->getAttributeValue("range");
const char *character = xml->getAttributeValue("character");
// Proceed only if neccesary tags were found
@ -67,7 +69,18 @@ bool Binding::deserialize(irr::io::IrrXMLReader* xml)
printf("WARNING: IT_STICKMOTION without direction, ignoring.\n");
return false;
}
m_dir = (Input::AxisDirection)atoi(dir_string);
// If the action is a stick motion & a range is defined
if (range_string == NULL)
{
m_range = Input::AR_HALF;
}
else
{
m_range = (Input::AxisRange)atoi(range_string);
}
m_dir = (Input::AxisDirection)atoi(dir_string);
} // if m_type!=stickmotion
return true;
@ -263,7 +276,14 @@ irr::core::stringw Binding::getAsString() const
else
{
//I18N: to appear in input configuration screen, for gamepad axes
s = _("Axis %d %s", m_id, (m_dir == Input::AD_NEGATIVE) ? L"-" : L"+");
if (m_range == Input::AR_HALF)
s = _("Axis %d %s", m_id, (m_dir == Input::AD_NEGATIVE) ? L"-" : L"+");
else
{
irr::core::stringw inv = _("inverted");
s = _("Axis %d %s", m_id, (m_dir == Input::AD_NEGATIVE) ? inv : L"");
}
}
break;
case Input::IT_STICKBUTTON:

View File

@ -36,6 +36,7 @@ private:
Input::InputType m_type;
int m_id;
Input::AxisDirection m_dir;
Input::AxisRange m_range;
wchar_t m_character;
public:
/** Returns the type of device this binding is using. */
@ -47,12 +48,16 @@ public:
/** Returns the direction this binding is using. */
Input::AxisDirection getDirection() const {return m_dir;}
// ------------------------------------------------------------------------
/** Returns the range this binding is using. */
Input::AxisRange getRange() const {return m_range;}
// ------------------------------------------------------------------------
/** Defines all values of this binding. */
void set(Input::InputType type, int id,
Input::AxisDirection dir,
Input::AxisRange range,
wchar_t character)
{
m_type = type; m_id=id; m_dir=dir; m_character=character;
m_type = type; m_id=id; m_dir=dir; m_range=range; m_character=character;
} // set
// ------------------------------------------------------------------------

View File

@ -322,7 +322,7 @@ InputDevice *DeviceManager::mapGamepadInput( Input::InputType type,
int deviceID,
int btnID,
int axisDir,
int value,
int *value /* inout */,
InputManager::InputDriverMode mode,
StateManager::ActivePlayer **player /* out */,
PlayerAction *action /* out */)
@ -361,14 +361,14 @@ bool DeviceManager::translateInput( Input::InputType type,
int deviceID,
int btnID,
int axisDir,
int value,
int* value /* inout */,
InputManager::InputDriverMode mode,
StateManager::ActivePlayer** player /* out */,
PlayerAction* action /* out */ )
{
if (GUIEngine::getCurrentScreen() != NULL)
{
GUIEngine::getCurrentScreen()->filterInput(type, deviceID, btnID, axisDir, value);
GUIEngine::getCurrentScreen()->filterInput(type, deviceID, btnID, axisDir, *value);
}
InputDevice *device = NULL;
@ -406,7 +406,7 @@ bool DeviceManager::translateInput( Input::InputType type,
// Return true if input was successfully translated to an action and player
if (device != NULL && abs(value) > Input::MAX_VALUE/2)
if (device != NULL && abs(*value) > Input::MAX_VALUE/2)
{
m_latest_used_device = device;
}

View File

@ -74,7 +74,7 @@ private:
int deviceID,
int btnID,
int axisDir,
int value,
int* value /* inout */,
InputManager::InputDriverMode mode,
StateManager::ActivePlayer **player /* out */,
PlayerAction *action /* out */);
@ -151,7 +151,7 @@ public:
int deviceID,
int btnID,
int axisDir,
int value,
int *value /* inout */,
InputManager::InputDriverMode mode,
StateManager::ActivePlayer** player /* out */,
PlayerAction* action /* out */ );

View File

@ -51,6 +51,12 @@ struct Input
AD_NEUTRAL
};
enum AxisRange
{
AR_HALF,
AR_FULL
};
enum InputType
{
IT_NONE = 0,
@ -67,6 +73,7 @@ struct Input
int m_device_id;
int m_button_id; // or axis ID for gamepads axes
int m_axis_direction;
int m_axis_range;
wchar_t m_character;
Input()

View File

@ -162,7 +162,7 @@ void GamePadDevice::resetAxisDirection(const int axis,
// ----------------------------------------------------------------------------
bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
const int value,
int* value, /* inout */
InputManager::InputDriverMode mode,
StateManager::ActivePlayer* player,
PlayerAction* action /* out */)
@ -180,13 +180,13 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
if (player != NULL)
{
// going to negative from positive
if (value < 0 && m_prevAxisDirections[id] == Input::AD_POSITIVE)
if (*value < 0 && m_prevAxisDirections[id] == Input::AD_POSITIVE)
{
// set positive id to 0
resetAxisDirection(id, Input::AD_POSITIVE, player);
}
// going to positive from negative
else if (value > 0 &&
else if (*value > 0 &&
m_prevAxisDirections[id] == Input::AD_NEGATIVE)
{
// set negative id to 0
@ -194,17 +194,17 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
}
}
if (value > 0) m_prevAxisDirections[id] = Input::AD_POSITIVE;
else if(value < 0) m_prevAxisDirections[id] = Input::AD_NEGATIVE;
if (*value > 0) m_prevAxisDirections[id] = Input::AD_POSITIVE;
else if(*value < 0) m_prevAxisDirections[id] = Input::AD_NEGATIVE;
if (!m_axis_ok[id])
{
if (m_prevAxisValue[id] == -1)
{
// first value we get from this axis
m_prevAxisValue[id] = value;
m_prevAxisValue[id] = *value;
}
else if (m_prevAxisValue[id] != value)
else if (m_prevAxisValue[id] != *value)
{
// second different value we get from this axis, consider it OK
m_axis_ok[id] = true;
@ -212,7 +212,7 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
}
// check if within deadzone
if(value > -m_deadzone && value < m_deadzone && player != NULL)
if(*value > -m_deadzone && *value < m_deadzone && player != NULL)
{
// Axis stands still: This is reported once for digital axes and
// can be called multipled times for analog ones. Uses the
@ -247,7 +247,7 @@ bool GamePadDevice::processAndMapInput(Input::InputType type, const int id,
{
success = m_configuration->getGameAction(type, id, value, action);
}
else if (abs(value) > Input::MAX_VALUE/2)
else if (abs(*value) > Input::MAX_VALUE/2)
{
// bindings can only be accessed in game and menu modes
assert(mode == InputManager::MENU);

View File

@ -132,7 +132,7 @@ public:
* \return Whether the pressed key/button is bound with an action
*/
bool processAndMapInput(Input::InputType type, const int id,
const int value,
int* value,
InputManager::InputDriverMode mode,
StateManager::ActivePlayer* player,
PlayerAction* action);

View File

@ -379,6 +379,8 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
!= m_sensed_input_high_gamepad.end();
bool inverse_id_was_high = m_sensed_input_high_gamepad.find(-input_id)
!= m_sensed_input_high_gamepad.end();
bool id_was_zero = m_sensed_input_zero_gamepad.find(button)
!= m_sensed_input_zero_gamepad.end();
// A stick was pushed far enough (for the first time) to count as
// 'triggered' - save the axis (coded with direction in the button
@ -388,31 +390,56 @@ void InputManager::inputSensing(Input::InputType type, int deviceID,
// to register this as soon as the value is high enough.
if (!id_was_high && abs(value) > Input::MAX_VALUE*6.0f/7.0f)
{
m_sensed_input_high_gamepad.insert(input_id);
if(inverse_id_was_high && !id_was_zero) {
Input sensed_input;
sensed_input.m_type = type;
sensed_input.m_device_id = deviceID;
sensed_input.m_button_id = button;
sensed_input.m_axis_direction = (value>=0) ? Input::AD_POSITIVE
: Input::AD_NEGATIVE;
sensed_input.m_axis_range = Input::AR_FULL;
sensed_input.m_character = deviceID;
OptionsScreenInput2::getInstance()->gotSensedInput(sensed_input);
}
else m_sensed_input_high_gamepad.insert(input_id);
}
else if ( abs(value) < Input::MAX_VALUE/8.0f && id_was_high )
else if ( abs(value) < Input::MAX_VALUE/8.0f )
{
Input sensed_input;
sensed_input.m_type = type;
sensed_input.m_device_id = deviceID;
sensed_input.m_button_id = button;
sensed_input.m_axis_direction = value>=0 ? Input::AD_POSITIVE
: Input::AD_NEGATIVE;
sensed_input.m_character = deviceID;
OptionsScreenInput2::getInstance()->gotSensedInput(sensed_input);
}
else if ( abs(value) < Input::MAX_VALUE/8.0f && inverse_id_was_high )
{
Input sensed_input;
sensed_input.m_type = type;
sensed_input.m_device_id = deviceID;
sensed_input.m_button_id = button;
// Since the inverse direction was high (i.e. stick went from
// +30000 to -100), we have to inverse the sign
sensed_input.m_axis_direction = value>=0 ? Input::AD_NEGATIVE
: Input::AD_POSITIVE;
sensed_input.m_character = deviceID;
OptionsScreenInput2::getInstance()->gotSensedInput(sensed_input);
if( id_was_high )
{
Input sensed_input;
sensed_input.m_type = type;
sensed_input.m_device_id = deviceID;
sensed_input.m_button_id = button;
sensed_input.m_axis_direction = (value>=0) == id_was_zero
? Input::AD_POSITIVE
: Input::AD_NEGATIVE;
sensed_input.m_axis_range = id_was_zero ? Input::AR_HALF
: Input::AR_FULL;
sensed_input.m_character = deviceID;
OptionsScreenInput2::getInstance()->gotSensedInput(sensed_input);
}
else if( inverse_id_was_high )
{
Input sensed_input;
sensed_input.m_type = type;
sensed_input.m_device_id = deviceID;
sensed_input.m_button_id = button;
// Since the inverse direction was high (i.e. stick went from
// +30000 to -100), we have to inverse the sign
sensed_input.m_axis_direction = (value>=0) == id_was_zero
? Input::AD_NEGATIVE
: Input::AD_POSITIVE;
sensed_input.m_axis_range = id_was_zero ? Input::AR_HALF
: Input::AR_FULL;
sensed_input.m_character = deviceID;
OptionsScreenInput2::getInstance()->gotSensedInput(sensed_input);
}
else
{
m_sensed_input_zero_gamepad.insert(button);
}
}
break;
}
@ -485,7 +512,7 @@ void InputManager::dispatchInput(Input::InputType type, int deviceID,
PlayerAction action;
bool action_found = m_device_manager->translateInput(type, deviceID,
button, axisDirection,
value, m_mode,
&value, m_mode,
&player, &action);
// in menus, some keyboard keys are standard (before each player selected
@ -968,6 +995,7 @@ void InputManager::setMode(InputDriverMode new_mode)
//irr_driver->showPointer();
m_sensed_input_high_gamepad.clear();
m_sensed_input_zero_gamepad.clear();
m_sensed_input_high_kbd.clear();
// The order is deliberate just in case someone starts

View File

@ -57,6 +57,7 @@ private:
DeviceManager *m_device_manager;
std::set<int> m_sensed_input_high_gamepad;
std::set<int> m_sensed_input_high_kbd;
std::set<int> m_sensed_input_zero_gamepad;
InputDriverMode m_mode;

View File

@ -257,6 +257,7 @@ void OptionsScreenInput::filterInput(Input::InputType type,
int deviceID,
int btnID,
int axisDir,
int axisRange,
int value)
{
if (type == Input::IT_STICKMOTION || type == Input::IT_STICKBUTTON)

View File

@ -70,6 +70,7 @@ public:
int deviceID,
int btnID,
int axisDir,
int axisRange,
int value);
/** \brief implement callback from parent class GUIEngine::Screen */

View File

@ -350,6 +350,7 @@ void OptionsScreenInput2::gotSensedInput(const Input& sensed_input)
KeyboardConfig* keyboard = (KeyboardConfig*)m_config;
keyboard->setBinding(binding_to_set, Input::IT_KEYBOARD,
sensed_input.m_button_id, Input::AD_NEUTRAL,
Input::AR_HALF,
sensed_input.m_character);
// refresh display
@ -387,7 +388,8 @@ void OptionsScreenInput2::gotSensedInput(const Input& sensed_input)
GamepadConfig* config = (GamepadConfig*)m_config;
config->setBinding(binding_to_set, sensed_input.m_type,
sensed_input.m_button_id,
(Input::AxisDirection)sensed_input.m_axis_direction);
(Input::AxisDirection)sensed_input.m_axis_direction,
(Input::AxisRange)sensed_input.m_axis_range);
// refresh display
updateInputButtons();