Added missing file

This commit is contained in:
Ingo Ruhnke 2009-01-07 07:10:33 +01:00
parent 4a3e3973ce
commit 700529e200
2 changed files with 315 additions and 0 deletions

168
src/modifier.cpp Normal file
View 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
View 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 */