Added missing file
This commit is contained in:
parent
4a3e3973ce
commit
700529e200
2 changed files with 315 additions and 0 deletions
168
src/modifier.cpp
Normal file
168
src/modifier.cpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2008 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <stdexcept>
|
||||
#include "modifier.hpp"
|
||||
|
||||
void apply_button_map(XboxGenericMsg& msg, std::vector<ButtonMapping>& lst)
|
||||
{
|
||||
XboxGenericMsg newmsg = msg;
|
||||
|
||||
for(std::vector<ButtonMapping>::iterator i = lst.begin(); i != lst.end(); ++i)
|
||||
set_button(newmsg, i->lhs, 0);
|
||||
|
||||
for(std::vector<ButtonMapping>::iterator i = lst.begin(); i != lst.end(); ++i)
|
||||
set_button(newmsg, i->rhs, get_button(msg, i->lhs) || get_button(newmsg, i->rhs));
|
||||
|
||||
msg = newmsg;
|
||||
}
|
||||
|
||||
void apply_axis_map(XboxGenericMsg& msg, std::vector<AxisMapping>& lst)
|
||||
{
|
||||
XboxGenericMsg newmsg = msg;
|
||||
|
||||
for(std::vector<AxisMapping>::iterator i = lst.begin(); i != lst.end(); ++i)
|
||||
{
|
||||
set_axis(newmsg, i->lhs, 0);
|
||||
}
|
||||
|
||||
for(std::vector<AxisMapping>::iterator i = lst.begin(); i != lst.end(); ++i)
|
||||
{
|
||||
int lhs = get_axis(msg, i->lhs);
|
||||
int nrhs = get_axis(newmsg, i->rhs);
|
||||
|
||||
if (i->invert)
|
||||
{
|
||||
if (i->lhs == XBOX_AXIS_LT ||
|
||||
i->lhs == XBOX_AXIS_RT)
|
||||
{
|
||||
lhs = 255 - lhs;
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = -lhs;
|
||||
}
|
||||
}
|
||||
|
||||
set_axis(newmsg, i->rhs, std::max(std::min(nrhs + lhs, 32767), -32768));
|
||||
}
|
||||
msg = newmsg;
|
||||
}
|
||||
|
||||
ButtonMapping
|
||||
ButtonMapping::from_string(const std::string& str)
|
||||
{
|
||||
for(std::string::const_iterator i = str.begin(); i != str.end(); ++i)
|
||||
{
|
||||
if (*i == '=')
|
||||
{
|
||||
ButtonMapping mapping;
|
||||
mapping.lhs = string2btn(std::string(str.begin(), i));
|
||||
mapping.rhs = string2btn(std::string(i+1, str.end()));
|
||||
|
||||
if (mapping.lhs == XBOX_BTN_UNKNOWN ||
|
||||
mapping.rhs == XBOX_BTN_UNKNOWN)
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to button mapping");
|
||||
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to button mapping");
|
||||
}
|
||||
|
||||
AxisMapping
|
||||
AxisMapping::from_string(const std::string& str)
|
||||
{
|
||||
for(std::string::const_iterator i = str.begin(); i != str.end(); ++i)
|
||||
{
|
||||
if (*i == '=')
|
||||
{
|
||||
AxisMapping mapping;
|
||||
|
||||
std::string lhs(str.begin(), i);
|
||||
std::string rhs(i+1, str.end());
|
||||
|
||||
if (lhs.empty() || rhs.empty())
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to axis mapping");
|
||||
|
||||
if (lhs[0] == '-')
|
||||
{
|
||||
mapping.invert = true;
|
||||
mapping.lhs = string2axis(lhs.substr(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping.invert = false;
|
||||
mapping.lhs = string2axis(lhs);
|
||||
}
|
||||
|
||||
mapping.rhs = string2axis(rhs);
|
||||
|
||||
if (mapping.lhs == XBOX_AXIS_UNKNOWN ||
|
||||
mapping.rhs == XBOX_AXIS_UNKNOWN)
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to axis mapping");
|
||||
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to axis mapping");
|
||||
}
|
||||
|
||||
RelativeAxisMapping
|
||||
RelativeAxisMapping::from_string(const std::string& str)
|
||||
{
|
||||
/* Format of str: A={SPEED} */
|
||||
std::string::size_type i = str.find('=');
|
||||
if (i == std::string::npos)
|
||||
{
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to RelativeAxisMapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
RelativeAxisMapping mapping;
|
||||
mapping.axis = string2axis(str.substr(0, i));
|
||||
mapping.speed = boost::lexical_cast<int>(str.substr(i+1, str.size()-i));
|
||||
// FIXME: insert some error checking here
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AutoFireMapping
|
||||
AutoFireMapping::from_string(const std::string& str)
|
||||
{
|
||||
/* Format of str: A={ON-DELAY}[:{OFF-DELAY}]
|
||||
Examples: A=10 or A=10:50
|
||||
if OFF-DELAY == nil then ON-DELAY = OFF-DELAY
|
||||
*/
|
||||
std::string::size_type i = str.find_first_of('=');
|
||||
if (i == std::string::npos)
|
||||
{
|
||||
throw std::runtime_error("Couldn't convert string \"" + str + "\" to AutoFireMapping");
|
||||
}
|
||||
else
|
||||
{
|
||||
AutoFireMapping mapping;
|
||||
mapping.button = string2btn(str.substr(0, i));
|
||||
mapping.frequency = atoi(str.substr(i+1, str.size()-i).c_str())/1000.0f;
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
147
src/modifier.hpp
Normal file
147
src/modifier.hpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
** Xbox360 USB Gamepad Userspace Driver
|
||||
** Copyright (C) 2008 Ingo Ruhnke <grumbel@gmx.de>
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEADER_MODIFIER_HPP
|
||||
#define HEADER_MODIFIER_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "xboxmsg.hpp"
|
||||
|
||||
struct ButtonMapping {
|
||||
static ButtonMapping from_string(const std::string& str);
|
||||
|
||||
XboxButton lhs;
|
||||
XboxButton rhs;
|
||||
};
|
||||
|
||||
struct AxisMapping {
|
||||
static AxisMapping from_string(const std::string& str);
|
||||
|
||||
XboxAxis lhs;
|
||||
XboxAxis rhs;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
struct AutoFireMapping {
|
||||
static AutoFireMapping from_string(const std::string&);
|
||||
|
||||
XboxButton button;
|
||||
float frequency;
|
||||
};
|
||||
|
||||
struct RelativeAxisMapping {
|
||||
static RelativeAxisMapping from_string(const std::string&);
|
||||
|
||||
XboxAxis axis;
|
||||
int speed;
|
||||
};
|
||||
|
||||
|
||||
class RelativeAxisModifier
|
||||
{
|
||||
private:
|
||||
std::vector<RelativeAxisMapping> relative_axis_map;
|
||||
std::vector<int> axis_state;
|
||||
|
||||
public:
|
||||
RelativeAxisModifier(const std::vector<RelativeAxisMapping>& relative_axis_map)
|
||||
: relative_axis_map(relative_axis_map)
|
||||
{
|
||||
for(size_t i = 0; i < relative_axis_map.size(); ++i)
|
||||
{
|
||||
axis_state.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void update(float delta, XboxGenericMsg& msg)
|
||||
{
|
||||
for(size_t i = 0; i < relative_axis_map.size(); ++i)
|
||||
{
|
||||
int value = get_axis(msg, relative_axis_map[i].axis);
|
||||
if (abs(value) > 4000 ) // FIXME: add proper deadzone handling
|
||||
{
|
||||
axis_state[i] += static_cast<int>(relative_axis_map[i].speed * delta * (value/32768.0f));
|
||||
if (axis_state[i] < -32768)
|
||||
axis_state[i] = -32768;
|
||||
else if (axis_state[i] > 32767)
|
||||
axis_state[i] = 32767;
|
||||
|
||||
set_axis(msg, relative_axis_map[i].axis, axis_state[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_axis(msg, relative_axis_map[i].axis, axis_state[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class AutoFireModifier
|
||||
{
|
||||
private:
|
||||
std::vector<AutoFireMapping> autofire_map;
|
||||
std::vector<float> button_timer;
|
||||
|
||||
public:
|
||||
AutoFireModifier(const std::vector<AutoFireMapping>& autofire_map)
|
||||
: autofire_map(autofire_map)
|
||||
{
|
||||
for(std::vector<AutoFireMapping>::const_iterator i = autofire_map.begin(); i != autofire_map.end(); ++i)
|
||||
{
|
||||
button_timer.push_back(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void update(float delta, XboxGenericMsg& msg)
|
||||
{
|
||||
for(size_t i = 0; i < autofire_map.size(); ++i)
|
||||
{
|
||||
if (get_button(msg, autofire_map[i].button))
|
||||
{
|
||||
button_timer[i] += delta;
|
||||
|
||||
if (button_timer[i] > autofire_map[i].frequency)
|
||||
{
|
||||
set_button(msg, autofire_map[i].button, 1);
|
||||
button_timer[i] = 0.0f; // FIXME: we ignoring the passed time
|
||||
}
|
||||
else if (button_timer[i] > autofire_map[i].frequency/2)
|
||||
{
|
||||
set_button(msg, autofire_map[i].button, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_button(msg, autofire_map[i].button, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
button_timer[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void apply_button_map(XboxGenericMsg& msg, std::vector<ButtonMapping>& lst);
|
||||
void apply_axis_map(XboxGenericMsg& msg, std::vector<AxisMapping>& lst);
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue