mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 20:41:45 +01:00
Qt/Input: Introduce profiles
This commit is contained in:
parent
4231ea2eb6
commit
51a2b43d81
@ -10,6 +10,10 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init_config(pad_config* /*cfg*/, const std::string& /*name*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> ListDevices() override
|
std::vector<std::string> ListDevices() override
|
||||||
{
|
{
|
||||||
std::vector<std::string> nulllist;
|
std::vector<std::string> nulllist;
|
||||||
@ -17,7 +21,7 @@ public:
|
|||||||
return nulllist;
|
return nulllist;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override
|
bool bindPadToDevice(std::shared_ptr<Pad> /*pad*/, const std::string& /*device*/) override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -25,5 +29,4 @@ public:
|
|||||||
void ThreadProc() override
|
void ThreadProc() override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
288
rpcs3/Emu/Io/PadHandler.cpp
Normal file
288
rpcs3/Emu/Io/PadHandler.cpp
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "PadHandler.h"
|
||||||
|
|
||||||
|
cfg_input g_cfg_input;
|
||||||
|
|
||||||
|
PadHandlerBase::PadHandlerBase(pad_handler type) : m_type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search an unordered map for a string value and return found keycode
|
||||||
|
int PadHandlerBase::FindKeyCode(std::unordered_map<u32, std::string> map, const cfg::string& name, bool fallback)
|
||||||
|
{
|
||||||
|
std::string def = name.def;
|
||||||
|
std::string nam = name.to_string();
|
||||||
|
int def_code = -1;
|
||||||
|
|
||||||
|
for (auto it = map.begin(); it != map.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second == nam)
|
||||||
|
return it->first;
|
||||||
|
|
||||||
|
if (fallback && it->second == def)
|
||||||
|
def_code = it->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallback)
|
||||||
|
{
|
||||||
|
LOG_ERROR(HLE, "int FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
||||||
|
if (def_code < 0)
|
||||||
|
def_code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return def_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
long PadHandlerBase::FindKeyCode(std::unordered_map<u64, std::string> map, const cfg::string& name, bool fallback)
|
||||||
|
{
|
||||||
|
std::string def = name.def;
|
||||||
|
std::string nam = name.to_string();
|
||||||
|
long def_code = -1;
|
||||||
|
|
||||||
|
for (auto it = map.begin(); it != map.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second == nam)
|
||||||
|
return static_cast<long>(it->first);
|
||||||
|
|
||||||
|
if (fallback && it->second == def)
|
||||||
|
def_code = static_cast<long>(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallback)
|
||||||
|
{
|
||||||
|
LOG_ERROR(HLE, "long FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
||||||
|
if (def_code < 0)
|
||||||
|
def_code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return def_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search an unordered map for a string value and return found keycode
|
||||||
|
int PadHandlerBase::FindKeyCodeByString(std::unordered_map<u32, std::string> map, const std::string& name, bool fallback)
|
||||||
|
{
|
||||||
|
for (auto it = map.begin(); it != map.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second == name)
|
||||||
|
return it->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallback)
|
||||||
|
{
|
||||||
|
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search an unordered map for a string value and return found keycode
|
||||||
|
long PadHandlerBase::FindKeyCodeByString(std::unordered_map<u64, std::string> map, const std::string& name, bool fallback)
|
||||||
|
{
|
||||||
|
for (auto it = map.begin(); it != map.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second == name)
|
||||||
|
return static_cast<long>(it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallback)
|
||||||
|
{
|
||||||
|
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get new scaled value between 0 and 255 based on its minimum and maximum
|
||||||
|
float PadHandlerBase::ScaleStickInput(s32 raw_value, int minimum, int maximum)
|
||||||
|
{
|
||||||
|
// value based on max range converted to [0, 1]
|
||||||
|
float val = float(Clamp(static_cast<f32>(raw_value), minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
||||||
|
return 255.0f * val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get new scaled value between -255 and 255 based on its minimum and maximum
|
||||||
|
float PadHandlerBase::ScaleStickInput2(s32 raw_value, int minimum, int maximum)
|
||||||
|
{
|
||||||
|
// value based on max range converted to [0, 1]
|
||||||
|
float val = float(Clamp(static_cast<f32>(raw_value), minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
||||||
|
return (510.0f * val) - 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get normalized trigger value based on the range defined by a threshold
|
||||||
|
u16 PadHandlerBase::NormalizeTriggerInput(u16 value, int threshold)
|
||||||
|
{
|
||||||
|
if (value <= threshold || threshold >= trigger_max)
|
||||||
|
{
|
||||||
|
return static_cast<u16>(0);
|
||||||
|
}
|
||||||
|
else if (threshold <= trigger_min)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (u16)(float(trigger_max) * float(value - threshold) / float(trigger_max - threshold));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
|
||||||
|
// the input values must lie in 0+
|
||||||
|
u16 PadHandlerBase::NormalizeDirectedInput(u16 raw_value, s32 threshold, s32 maximum)
|
||||||
|
{
|
||||||
|
if (threshold >= maximum || maximum <= 0)
|
||||||
|
{
|
||||||
|
return static_cast<u16>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float val = float(Clamp(raw_value, 0, maximum)) / float(maximum); // value based on max range converted to [0, 1]
|
||||||
|
|
||||||
|
if (threshold <= 0)
|
||||||
|
{
|
||||||
|
return static_cast<u16>(255.0f * val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float thresh = float(threshold) / float(maximum); // threshold converted to [0, 1]
|
||||||
|
return static_cast<u16>(255.0f * std::min(1.0f, (val - thresh) / (1.0f - thresh)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 PadHandlerBase::NormalizeStickInput(u16 raw_value, int threshold, bool ignore_threshold)
|
||||||
|
{
|
||||||
|
if (ignore_threshold)
|
||||||
|
{
|
||||||
|
return static_cast<u16>(ScaleStickInput(raw_value, 0, thumb_max));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NormalizeDirectedInput(raw_value, threshold, thumb_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
|
||||||
|
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
|
||||||
|
// return is new x and y values in 0-255 range
|
||||||
|
std::tuple<u16, u16> PadHandlerBase::NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone)
|
||||||
|
{
|
||||||
|
const float dzRange = deadzone / float((std::abs(thumb_max) + std::abs(thumb_min)));
|
||||||
|
|
||||||
|
float X = inX / 255.0f;
|
||||||
|
float Y = inY / 255.0f;
|
||||||
|
|
||||||
|
if (dzRange > 0.f)
|
||||||
|
{
|
||||||
|
const float mag = std::min(sqrtf(X*X + Y*Y), 1.f);
|
||||||
|
|
||||||
|
if (mag <= 0)
|
||||||
|
{
|
||||||
|
return std::tuple<u16, u16>(ConvertAxis(X), ConvertAxis(Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mag > dzRange) {
|
||||||
|
float pos = lerp(0.13f, 1.f, (mag - dzRange) / (1 - dzRange));
|
||||||
|
float scale = pos / mag;
|
||||||
|
X = X * scale;
|
||||||
|
Y = Y * scale;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float pos = lerp(0.f, 0.13f, mag / dzRange);
|
||||||
|
float scale = pos / mag;
|
||||||
|
X = X * scale;
|
||||||
|
Y = Y * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::tuple<u16, u16>(ConvertAxis(X), ConvertAxis(Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get clamped value between min and max
|
||||||
|
s32 PadHandlerBase::Clamp(f32 input, s32 min, s32 max)
|
||||||
|
{
|
||||||
|
if (input > max)
|
||||||
|
return max;
|
||||||
|
else if (input < min)
|
||||||
|
return min;
|
||||||
|
else return static_cast<s32>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get clamped value between 0 and 255
|
||||||
|
u16 PadHandlerBase::Clamp0To255(f32 input)
|
||||||
|
{
|
||||||
|
return static_cast<u16>(Clamp(input, 0, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get clamped value between 0 and 1023
|
||||||
|
u16 PadHandlerBase::Clamp0To1023(f32 input)
|
||||||
|
{
|
||||||
|
return static_cast<u16>(Clamp(input, 0, 1023));
|
||||||
|
}
|
||||||
|
|
||||||
|
// input has to be [-1,1]. result will be [0,255]
|
||||||
|
u16 PadHandlerBase::ConvertAxis(float value)
|
||||||
|
{
|
||||||
|
return static_cast<u16>((value + 1.0)*(255.0 / 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
||||||
|
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
||||||
|
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
|
||||||
|
// This function assumes inX and inY is already in 0-255
|
||||||
|
std::tuple<u16, u16> PadHandlerBase::ConvertToSquirclePoint(u16 inX, u16 inY, int squircle_factor)
|
||||||
|
{
|
||||||
|
// convert inX and Y to a (-1, 1) vector;
|
||||||
|
const f32 x = ((f32)inX - 127.5f) / 127.5f;
|
||||||
|
const f32 y = ((f32)inY - 127.5f) / 127.5f;
|
||||||
|
|
||||||
|
// compute angle and len of given point to be used for squircle radius
|
||||||
|
const f32 angle = std::atan2(y, x);
|
||||||
|
const f32 r = std::sqrt(std::pow(x, 2.f) + std::pow(y, 2.f));
|
||||||
|
|
||||||
|
// now find len/point on the given squircle from our current angle and radius in polar coords
|
||||||
|
// https://thatsmaths.com/2016/07/14/squircles/
|
||||||
|
const f32 newLen = (1 + std::pow(std::sin(2 * angle), 2.f) / (float(squircle_factor) / 1000.f)) * r;
|
||||||
|
|
||||||
|
// we now have len and angle, convert to cartisian
|
||||||
|
const int newX = Clamp0To255(((newLen * std::cos(angle)) + 1) * 127.5f);
|
||||||
|
const int newY = Clamp0To255(((newLen * std::sin(angle)) + 1) * 127.5f);
|
||||||
|
return std::tuple<u16, u16>(newX, newY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PadHandlerBase::has_config()
|
||||||
|
{
|
||||||
|
return b_has_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PadHandlerBase::has_rumble()
|
||||||
|
{
|
||||||
|
return b_has_rumble;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PadHandlerBase::has_deadzones()
|
||||||
|
{
|
||||||
|
return b_has_deadzones;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PadHandlerBase::get_config_dir(pad_handler type)
|
||||||
|
{
|
||||||
|
return fs::get_config_dir() + "/InputConfigs/" + fmt::format("%s", type) + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PadHandlerBase::get_config_filename(int i)
|
||||||
|
{
|
||||||
|
return fs::get_config_dir() + "/InputConfigs/" + g_cfg_input.player[i]->handler.to_string() + "/" + g_cfg_input.player[i]->profile.to_string() + ".yml";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PadHandlerBase::init_configs()
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
|
{
|
||||||
|
if (g_cfg_input.player[i]->handler == m_type)
|
||||||
|
{
|
||||||
|
init_config(&m_pad_configs[index], get_config_filename(i));
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "../../Utilities/Config.h"
|
#include "../../Utilities/Config.h"
|
||||||
#include "../../Utilities/types.h"
|
#include "../../Utilities/types.h"
|
||||||
|
#include "Emu/System.h"
|
||||||
|
|
||||||
// TODO: HLE info (constants, structs, etc.) should not be available here
|
// TODO: HLE info (constants, structs, etc.) should not be available here
|
||||||
|
|
||||||
@ -248,9 +249,50 @@ struct Pad
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pad_config : cfg::node
|
struct cfg_player final : cfg::node
|
||||||
|
{
|
||||||
|
pad_handler def_handler = pad_handler::null;
|
||||||
|
cfg_player(node* owner, const std::string& name, pad_handler type) : cfg::node(owner, name), def_handler(type) {};
|
||||||
|
|
||||||
|
cfg::_enum<pad_handler> handler{ this, "Handler", def_handler };
|
||||||
|
cfg::string device{ this, "Device", handler.to_string() };
|
||||||
|
cfg::string profile{ this, "Profile", "Default Profile" };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cfg_input final : cfg::node
|
||||||
|
{
|
||||||
|
const std::string cfg_name = fs::get_config_dir() + "/config_input.yml";
|
||||||
|
|
||||||
|
cfg_player player1{ this, "Player 1 Input", pad_handler::keyboard };
|
||||||
|
cfg_player player2{ this, "Player 2 Input", pad_handler::null };
|
||||||
|
cfg_player player3{ this, "Player 3 Input", pad_handler::null };
|
||||||
|
cfg_player player4{ this, "Player 4 Input", pad_handler::null };
|
||||||
|
cfg_player player5{ this, "Player 5 Input", pad_handler::null };
|
||||||
|
cfg_player player6{ this, "Player 6 Input", pad_handler::null };
|
||||||
|
cfg_player player7{ this, "Player 7 Input", pad_handler::null };
|
||||||
|
|
||||||
|
cfg_player *player[7]{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
|
||||||
|
|
||||||
|
bool load()
|
||||||
|
{
|
||||||
|
if (fs::file cfg_file{ cfg_name, fs::read })
|
||||||
|
{
|
||||||
|
return from_string(cfg_file.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void save()
|
||||||
|
{
|
||||||
|
fs::file(cfg_name, fs::rewrite).write(to_string());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern cfg_input g_cfg_input;
|
||||||
|
|
||||||
|
struct pad_config final : cfg::node
|
||||||
{
|
{
|
||||||
std::string cfg_type = "";
|
|
||||||
std::string cfg_name = "";
|
std::string cfg_name = "";
|
||||||
|
|
||||||
cfg::string ls_left { this, "Left Stick Left", "" };
|
cfg::string ls_left { this, "Left Stick Left", "" };
|
||||||
@ -327,7 +369,7 @@ protected:
|
|||||||
bool b_has_deadzones = false;
|
bool b_has_deadzones = false;
|
||||||
bool b_has_rumble = false;
|
bool b_has_rumble = false;
|
||||||
bool b_has_config = false;
|
bool b_has_config = false;
|
||||||
pad_config m_pad_config;
|
std::array<pad_config, MAX_GAMEPADS> m_pad_configs;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T lerp(T v0, T v1, T t) {
|
T lerp(T v0, T v1, T t) {
|
||||||
@ -335,245 +377,52 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search an unordered map for a string value and return found keycode
|
// Search an unordered map for a string value and return found keycode
|
||||||
int FindKeyCode(std::unordered_map<u32, std::string> map, const cfg::string& name, bool fallback = true)
|
int FindKeyCode(std::unordered_map<u32, std::string> map, const cfg::string& name, bool fallback = true);
|
||||||
{
|
|
||||||
std::string def = name.def;
|
|
||||||
std::string nam = name.to_string();
|
|
||||||
int def_code = -1;
|
|
||||||
|
|
||||||
for (auto it = map.begin(); it != map.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->second == nam)
|
|
||||||
return it->first;
|
|
||||||
|
|
||||||
if (fallback && it->second == def)
|
|
||||||
def_code = it->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fallback)
|
|
||||||
{
|
|
||||||
LOG_ERROR(HLE, "int FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
|
||||||
if (def_code < 0)
|
|
||||||
def_code = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return def_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
long FindKeyCode(std::unordered_map<u64, std::string> map, const cfg::string& name, bool fallback = true)
|
|
||||||
{
|
|
||||||
std::string def = name.def;
|
|
||||||
std::string nam = name.to_string();
|
|
||||||
int def_code = -1;
|
|
||||||
|
|
||||||
for (auto it = map.begin(); it != map.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->second == nam)
|
|
||||||
return it->first;
|
|
||||||
|
|
||||||
if (fallback && it->second == def)
|
|
||||||
def_code = it->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fallback)
|
|
||||||
{
|
|
||||||
LOG_ERROR(HLE, "long FindKeyCode for [name = %s] returned with [def_code = %d] for [def = %s]", nam, def_code, def);
|
|
||||||
if (def_code < 0)
|
|
||||||
def_code = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return def_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Search an unordered map for a string value and return found keycode
|
// Search an unordered map for a string value and return found keycode
|
||||||
int FindKeyCodeByString(std::unordered_map<u32, std::string> map, const std::string& name, bool fallback = true)
|
long FindKeyCode(std::unordered_map<u64, std::string> map, const cfg::string& name, bool fallback = true);
|
||||||
{
|
|
||||||
for (auto it = map.begin(); it != map.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->second == name)
|
|
||||||
return it->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fallback)
|
|
||||||
{
|
|
||||||
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Search an unordered map for a string value and return found keycode
|
// Search an unordered map for a string value and return found keycode
|
||||||
long FindKeyCodeByString(std::unordered_map<u64, std::string> map, const std::string& name, bool fallback = true)
|
int FindKeyCodeByString(std::unordered_map<u32, std::string> map, const std::string& name, bool fallback = true);
|
||||||
{
|
|
||||||
for (auto it = map.begin(); it != map.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->second == name)
|
|
||||||
return it->first;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fallback)
|
// Search an unordered map for a string value and return found keycode
|
||||||
{
|
long FindKeyCodeByString(std::unordered_map<u64, std::string> map, const std::string& name, bool fallback = true);
|
||||||
LOG_ERROR(HLE, "long FindKeyCodeByString fohr [name = %s] returned with 0", name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get normalized trigger value based on the range defined by a threshold
|
|
||||||
u16 NormalizeTriggerInput(u16 value, int threshold)
|
|
||||||
{
|
|
||||||
if (value <= threshold || threshold >= trigger_max)
|
|
||||||
{
|
|
||||||
return static_cast<u16>(0);
|
|
||||||
}
|
|
||||||
else if (threshold <= trigger_min)
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (u16)(float(trigger_max) * float(value - threshold) / float(trigger_max - threshold));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get new scaled value between 0 and 255 based on its minimum and maximum
|
// Get new scaled value between 0 and 255 based on its minimum and maximum
|
||||||
float ScaleStickInput(s32 raw_value, int minimum, int maximum)
|
float ScaleStickInput(s32 raw_value, int minimum, int maximum);
|
||||||
{
|
|
||||||
// value based on max range converted to [0, 1]
|
|
||||||
float val = float(Clamp(raw_value, minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
|
||||||
return 255.0f * val;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get new scaled value between -255 and 255 based on its minimum and maximum
|
// Get new scaled value between -255 and 255 based on its minimum and maximum
|
||||||
float ScaleStickInput2(s32 raw_value, int minimum, int maximum)
|
float ScaleStickInput2(s32 raw_value, int minimum, int maximum);
|
||||||
{
|
|
||||||
// value based on max range converted to [0, 1]
|
// Get normalized trigger value based on the range defined by a threshold
|
||||||
float val = float(Clamp(raw_value, minimum, maximum) - minimum) / float(abs(maximum) + abs(minimum));
|
u16 NormalizeTriggerInput(u16 value, int threshold);
|
||||||
return (510.0f * val) - 255.0f;
|
|
||||||
};
|
|
||||||
|
|
||||||
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
|
// normalizes a directed input, meaning it will correspond to a single "button" and not an axis with two directions
|
||||||
// the input values must lie in 0+
|
// the input values must lie in 0+
|
||||||
u16 NormalizeDirectedInput(u16 raw_value, float threshold, float maximum)
|
u16 NormalizeDirectedInput(u16 raw_value, s32 threshold, s32 maximum);
|
||||||
{
|
|
||||||
if (threshold >= maximum || maximum <= 0)
|
|
||||||
{
|
|
||||||
return static_cast<u16>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
float val = float(Clamp(raw_value, 0, maximum)) / maximum; // value based on max range converted to [0, 1]
|
u16 NormalizeStickInput(u16 raw_value, int threshold, bool ignore_threshold = false);
|
||||||
|
|
||||||
if (threshold <= 0)
|
|
||||||
{
|
|
||||||
return static_cast<u16>(255.0f * val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float thresh = threshold / maximum; // threshold converted to [0, 1]
|
|
||||||
return static_cast<u16>(255.0f * std::min(1.0f, (val - thresh) / (1.0f - thresh)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
u16 NormalizeStickInput(s32 raw_value, int threshold, bool ignore_threshold = false)
|
|
||||||
{
|
|
||||||
if (ignore_threshold)
|
|
||||||
{
|
|
||||||
return static_cast<u16>(ScaleStickInput(raw_value, 0, thumb_max));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NormalizeDirectedInput(raw_value, threshold, thumb_max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
|
// This function normalizes stick deadzone based on the DS3's deadzone, which is ~13%
|
||||||
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
|
// X and Y is expected to be in (-255) to 255 range, deadzone should be in terms of thumb stick range
|
||||||
// return is new x and y values in 0-255 range
|
// return is new x and y values in 0-255 range
|
||||||
std::tuple<u16, u16> NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone)
|
std::tuple<u16, u16> NormalizeStickDeadzone(s32 inX, s32 inY, u32 deadzone);
|
||||||
{
|
|
||||||
const float dzRange = deadzone / float((std::abs(thumb_max) + std::abs(thumb_min)));
|
|
||||||
|
|
||||||
float X = inX / 255.0f;
|
|
||||||
float Y = inY / 255.0f;
|
|
||||||
|
|
||||||
if (dzRange > 0.f)
|
|
||||||
{
|
|
||||||
const float mag = std::min(sqrtf(X*X + Y*Y), 1.f);
|
|
||||||
|
|
||||||
if (mag <= 0)
|
|
||||||
{
|
|
||||||
return std::tuple<u16, u16>(ConvertAxis(X), ConvertAxis(Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mag > dzRange) {
|
|
||||||
float pos = lerp(0.13f, 1.f, (mag - dzRange) / (1 - dzRange));
|
|
||||||
float scale = pos / mag;
|
|
||||||
X = X * scale;
|
|
||||||
Y = Y * scale;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
float pos = lerp(0.f, 0.13f, mag / dzRange);
|
|
||||||
float scale = pos / mag;
|
|
||||||
X = X * scale;
|
|
||||||
Y = Y * scale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::tuple<u16, u16>( ConvertAxis(X), ConvertAxis(Y) );
|
|
||||||
};
|
|
||||||
|
|
||||||
// get clamped value between min and max
|
// get clamped value between min and max
|
||||||
s32 Clamp(f32 input, s32 min, s32 max)
|
s32 Clamp(f32 input, s32 min, s32 max);
|
||||||
{
|
|
||||||
if (input > max)
|
|
||||||
return max;
|
|
||||||
else if (input < min)
|
|
||||||
return min;
|
|
||||||
else return static_cast<s32>(input);
|
|
||||||
};
|
|
||||||
|
|
||||||
// get clamped value between 0 and 255
|
// get clamped value between 0 and 255
|
||||||
u16 Clamp0To255(f32 input)
|
u16 Clamp0To255(f32 input);
|
||||||
{
|
|
||||||
return static_cast<u16>(Clamp(input, 0, 255));
|
|
||||||
};
|
|
||||||
|
|
||||||
// get clamped value between 0 and 1023
|
// get clamped value between 0 and 1023
|
||||||
u16 Clamp0To1023(f32 input)
|
u16 Clamp0To1023(f32 input);
|
||||||
{
|
|
||||||
return static_cast<u16>(Clamp(input, 0, 1023));
|
|
||||||
}
|
|
||||||
|
|
||||||
// input has to be [-1,1]. result will be [0,255]
|
// input has to be [-1,1]. result will be [0,255]
|
||||||
u16 ConvertAxis(float value)
|
u16 ConvertAxis(float value);
|
||||||
{
|
|
||||||
return static_cast<u16>((value + 1.0)*(255.0 / 2.0));
|
|
||||||
};
|
|
||||||
|
|
||||||
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
||||||
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
||||||
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
|
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
|
||||||
// This function assumes inX and inY is already in 0-255
|
// This function assumes inX and inY is already in 0-255
|
||||||
std::tuple<u16, u16> ConvertToSquirclePoint(u16 inX, u16 inY, float squircle_factor)
|
std::tuple<u16, u16> ConvertToSquirclePoint(u16 inX, u16 inY, int squircle_factor);
|
||||||
{
|
|
||||||
// convert inX and Y to a (-1, 1) vector;
|
|
||||||
const f32 x = ((f32)inX - 127.5f) / 127.5f;
|
|
||||||
const f32 y = ((f32)inY - 127.5f) / 127.5f;
|
|
||||||
|
|
||||||
// compute angle and len of given point to be used for squircle radius
|
|
||||||
const f32 angle = std::atan2(y, x);
|
|
||||||
const f32 r = std::sqrt(std::pow(x, 2.f) + std::pow(y, 2.f));
|
|
||||||
|
|
||||||
// now find len/point on the given squircle from our current angle and radius in polar coords
|
|
||||||
// https://thatsmaths.com/2016/07/14/squircles/
|
|
||||||
const f32 newLen = (1 + std::pow(std::sin(2 * angle), 2.f) / (squircle_factor / 1000.f)) * r;
|
|
||||||
|
|
||||||
// we now have len and angle, convert to cartisian
|
|
||||||
const int newX = Clamp0To255(((newLen * std::cos(angle)) + 1) * 127.5f);
|
|
||||||
const int newY = Clamp0To255(((newLen * std::sin(angle)) + 1) * 127.5f);
|
|
||||||
return std::tuple<u16, u16>(newX, newY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
s32 thumb_min = 0;
|
s32 thumb_min = 0;
|
||||||
@ -584,24 +433,32 @@ public:
|
|||||||
s32 vibration_max = 255;
|
s32 vibration_max = 255;
|
||||||
u32 connected = 0;
|
u32 connected = 0;
|
||||||
|
|
||||||
virtual bool Init() { return true; };
|
pad_handler m_type = pad_handler::null;
|
||||||
virtual ~PadHandlerBase() = default;
|
|
||||||
|
|
||||||
//Does it have GUI Config?
|
bool has_config();
|
||||||
bool has_config() { return b_has_config; };
|
bool has_rumble();
|
||||||
bool has_rumble() { return b_has_rumble; };
|
bool has_deadzones();
|
||||||
bool has_deadzones() { return b_has_deadzones; };
|
|
||||||
pad_config* GetConfig() { return &m_pad_config; };
|
static std::string get_config_dir(pad_handler type);
|
||||||
|
static std::string get_config_filename(int i);
|
||||||
|
|
||||||
|
virtual bool Init() { return true; };
|
||||||
|
PadHandlerBase(pad_handler type = pad_handler::null);
|
||||||
|
virtual ~PadHandlerBase() = default;
|
||||||
//Sets window to config the controller(optional)
|
//Sets window to config the controller(optional)
|
||||||
virtual void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) {};
|
virtual void GetNextButtonPress(const std::string& /*padId*/, const std::function<void(u16, std::string, int[])>& /*callback*/, bool /*get_blacklist*/ = false, std::vector<std::string> /*buttons*/ = {}) {};
|
||||||
virtual void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) {};
|
virtual void TestVibration(const std::string& /*padId*/, u32 /*largeMotor*/, u32 /*smallMotor*/) {};
|
||||||
//Return list of devices for that handler
|
//Return list of devices for that handler
|
||||||
virtual std::vector<std::string> ListDevices() = 0;
|
virtual std::vector<std::string> ListDevices() = 0;
|
||||||
//Callback called during pad_thread::ThreadFunc
|
//Callback called during pad_thread::ThreadFunc
|
||||||
virtual void ThreadProc() = 0;
|
virtual void ThreadProc() = 0;
|
||||||
//Binds a Pad to a device
|
//Binds a Pad to a device
|
||||||
virtual bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) = 0;
|
virtual bool bindPadToDevice(std::shared_ptr<Pad> /*pad*/, const std::string& /*device*/) = 0;
|
||||||
|
virtual void init_config(pad_config* /*cfg*/, const std::string& /*name*/) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) {};
|
virtual void TranslateButtonPress(u64 /*keyCode*/, bool& /*pressed*/, u16& /*val*/, bool /*ignore_threshold*/ = false) {};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void init_configs();
|
||||||
};
|
};
|
||||||
|
@ -145,7 +145,6 @@ void fmt_class_string<video_aspect>::format(std::string& out, u64 arg)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fmt_class_string<keyboard_handler>::format(std::string& out, u64 arg)
|
void fmt_class_string<keyboard_handler>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
#include "stdafx.h"
|
|
||||||
#include "Emu/System.h"
|
|
||||||
#include "ds4_pad_handler.h"
|
#include "ds4_pad_handler.h"
|
||||||
#include "rpcs3qt/pad_settings_dialog.h"
|
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@ -82,8 +79,10 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ds4_pad_handler::ds4_pad_handler() : is_init(false)
|
ds4_pad_handler::ds4_pad_handler() : PadHandlerBase(pad_handler::ds4)
|
||||||
{
|
{
|
||||||
|
init_configs();
|
||||||
|
|
||||||
// Define border values
|
// Define border values
|
||||||
thumb_min = 0;
|
thumb_min = 0;
|
||||||
thumb_max = 255;
|
thumb_max = 255;
|
||||||
@ -92,52 +91,6 @@ ds4_pad_handler::ds4_pad_handler() : is_init(false)
|
|||||||
vibration_min = 0;
|
vibration_min = 0;
|
||||||
vibration_max = 255;
|
vibration_max = 255;
|
||||||
|
|
||||||
// Set this handler's type and save location
|
|
||||||
m_pad_config.cfg_type = "ds4";
|
|
||||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_ds4.yml";
|
|
||||||
|
|
||||||
// Set default button mapping
|
|
||||||
m_pad_config.ls_left.def = button_list.at(DS4KeyCodes::LSXNeg);
|
|
||||||
m_pad_config.ls_down.def = button_list.at(DS4KeyCodes::LSYNeg);
|
|
||||||
m_pad_config.ls_right.def = button_list.at(DS4KeyCodes::LSXPos);
|
|
||||||
m_pad_config.ls_up.def = button_list.at(DS4KeyCodes::LSYPos);
|
|
||||||
m_pad_config.rs_left.def = button_list.at(DS4KeyCodes::RSXNeg);
|
|
||||||
m_pad_config.rs_down.def = button_list.at(DS4KeyCodes::RSYNeg);
|
|
||||||
m_pad_config.rs_right.def = button_list.at(DS4KeyCodes::RSXPos);
|
|
||||||
m_pad_config.rs_up.def = button_list.at(DS4KeyCodes::RSYPos);
|
|
||||||
m_pad_config.start.def = button_list.at(DS4KeyCodes::Options);
|
|
||||||
m_pad_config.select.def = button_list.at(DS4KeyCodes::Share);
|
|
||||||
m_pad_config.ps.def = button_list.at(DS4KeyCodes::PSButton);
|
|
||||||
m_pad_config.square.def = button_list.at(DS4KeyCodes::Square);
|
|
||||||
m_pad_config.cross.def = button_list.at(DS4KeyCodes::Cross);
|
|
||||||
m_pad_config.circle.def = button_list.at(DS4KeyCodes::Circle);
|
|
||||||
m_pad_config.triangle.def = button_list.at(DS4KeyCodes::Triangle);
|
|
||||||
m_pad_config.left.def = button_list.at(DS4KeyCodes::Left);
|
|
||||||
m_pad_config.down.def = button_list.at(DS4KeyCodes::Down);
|
|
||||||
m_pad_config.right.def = button_list.at(DS4KeyCodes::Right);
|
|
||||||
m_pad_config.up.def = button_list.at(DS4KeyCodes::Up);
|
|
||||||
m_pad_config.r1.def = button_list.at(DS4KeyCodes::R1);
|
|
||||||
m_pad_config.r2.def = button_list.at(DS4KeyCodes::R2);
|
|
||||||
m_pad_config.r3.def = button_list.at(DS4KeyCodes::R3);
|
|
||||||
m_pad_config.l1.def = button_list.at(DS4KeyCodes::L1);
|
|
||||||
m_pad_config.l2.def = button_list.at(DS4KeyCodes::L2);
|
|
||||||
m_pad_config.l3.def = button_list.at(DS4KeyCodes::L3);
|
|
||||||
|
|
||||||
// Set default misc variables
|
|
||||||
m_pad_config.lstickdeadzone.def = 40; // between 0 and 255
|
|
||||||
m_pad_config.rstickdeadzone.def = 40; // between 0 and 255
|
|
||||||
m_pad_config.ltriggerthreshold.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.rtriggerthreshold.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.padsquircling.def = 8000;
|
|
||||||
|
|
||||||
// Set color value
|
|
||||||
m_pad_config.colorR.def = 0;
|
|
||||||
m_pad_config.colorG.def = 0;
|
|
||||||
m_pad_config.colorB.def = 20;
|
|
||||||
|
|
||||||
// apply defaults
|
|
||||||
m_pad_config.from_default();
|
|
||||||
|
|
||||||
// set capabilities
|
// set capabilities
|
||||||
b_has_config = true;
|
b_has_config = true;
|
||||||
b_has_rumble = true;
|
b_has_rumble = true;
|
||||||
@ -147,6 +100,54 @@ ds4_pad_handler::ds4_pad_handler() : is_init(false)
|
|||||||
m_thumb_threshold = thumb_max / 2;
|
m_thumb_threshold = thumb_max / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ds4_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||||
|
{
|
||||||
|
// Set this profile's save location
|
||||||
|
cfg->cfg_name = name;
|
||||||
|
|
||||||
|
// Set default button mapping
|
||||||
|
cfg->ls_left.def = button_list.at(DS4KeyCodes::LSXNeg);
|
||||||
|
cfg->ls_down.def = button_list.at(DS4KeyCodes::LSYNeg);
|
||||||
|
cfg->ls_right.def = button_list.at(DS4KeyCodes::LSXPos);
|
||||||
|
cfg->ls_up.def = button_list.at(DS4KeyCodes::LSYPos);
|
||||||
|
cfg->rs_left.def = button_list.at(DS4KeyCodes::RSXNeg);
|
||||||
|
cfg->rs_down.def = button_list.at(DS4KeyCodes::RSYNeg);
|
||||||
|
cfg->rs_right.def = button_list.at(DS4KeyCodes::RSXPos);
|
||||||
|
cfg->rs_up.def = button_list.at(DS4KeyCodes::RSYPos);
|
||||||
|
cfg->start.def = button_list.at(DS4KeyCodes::Options);
|
||||||
|
cfg->select.def = button_list.at(DS4KeyCodes::Share);
|
||||||
|
cfg->ps.def = button_list.at(DS4KeyCodes::PSButton);
|
||||||
|
cfg->square.def = button_list.at(DS4KeyCodes::Square);
|
||||||
|
cfg->cross.def = button_list.at(DS4KeyCodes::Cross);
|
||||||
|
cfg->circle.def = button_list.at(DS4KeyCodes::Circle);
|
||||||
|
cfg->triangle.def = button_list.at(DS4KeyCodes::Triangle);
|
||||||
|
cfg->left.def = button_list.at(DS4KeyCodes::Left);
|
||||||
|
cfg->down.def = button_list.at(DS4KeyCodes::Down);
|
||||||
|
cfg->right.def = button_list.at(DS4KeyCodes::Right);
|
||||||
|
cfg->up.def = button_list.at(DS4KeyCodes::Up);
|
||||||
|
cfg->r1.def = button_list.at(DS4KeyCodes::R1);
|
||||||
|
cfg->r2.def = button_list.at(DS4KeyCodes::R2);
|
||||||
|
cfg->r3.def = button_list.at(DS4KeyCodes::R3);
|
||||||
|
cfg->l1.def = button_list.at(DS4KeyCodes::L1);
|
||||||
|
cfg->l2.def = button_list.at(DS4KeyCodes::L2);
|
||||||
|
cfg->l3.def = button_list.at(DS4KeyCodes::L3);
|
||||||
|
|
||||||
|
// Set default misc variables
|
||||||
|
cfg->lstickdeadzone.def = 40; // between 0 and 255
|
||||||
|
cfg->rstickdeadzone.def = 40; // between 0 and 255
|
||||||
|
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->padsquircling.def = 8000;
|
||||||
|
|
||||||
|
// Set color value
|
||||||
|
cfg->colorR.def = 0;
|
||||||
|
cfg->colorG.def = 0;
|
||||||
|
cfg->colorB.def = 20;
|
||||||
|
|
||||||
|
// apply defaults
|
||||||
|
cfg->from_default();
|
||||||
|
}
|
||||||
|
|
||||||
void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist, std::vector<std::string> buttons)
|
void ds4_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist, std::vector<std::string> buttons)
|
||||||
{
|
{
|
||||||
if (get_blacklist)
|
if (get_blacklist)
|
||||||
@ -227,6 +228,21 @@ void ds4_pad_handler::TestVibration(const std::string& padId, u32 largeMotor, u3
|
|||||||
device->largeVibrate = largeMotor;
|
device->largeVibrate = largeMotor;
|
||||||
device->smallVibrate = smallMotor;
|
device->smallVibrate = smallMotor;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||||
|
{
|
||||||
|
if (g_cfg_input.player[i]->handler == pad_handler::ds4)
|
||||||
|
{
|
||||||
|
if (g_cfg_input.player[i]->device.to_string() == padId)
|
||||||
|
{
|
||||||
|
m_pad_configs[index].load();
|
||||||
|
device->config = &m_pad_configs[index];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start/Stop the engines :)
|
// Start/Stop the engines :)
|
||||||
SendVibrateData(device);
|
SendVibrateData(device);
|
||||||
}
|
}
|
||||||
@ -259,29 +275,30 @@ void ds4_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val,
|
|||||||
{
|
{
|
||||||
// Update the pad button values based on their type and thresholds.
|
// Update the pad button values based on their type and thresholds.
|
||||||
// With this you can use axis or triggers as buttons or vice versa
|
// With this you can use axis or triggers as buttons or vice versa
|
||||||
|
auto p_profile = m_dev->config;
|
||||||
switch (keyCode)
|
switch (keyCode)
|
||||||
{
|
{
|
||||||
case DS4KeyCodes::L2:
|
case DS4KeyCodes::L2:
|
||||||
pressed = val > m_pad_config.ltriggerthreshold;
|
pressed = val > p_profile->ltriggerthreshold;
|
||||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0;
|
val = pressed ? NormalizeTriggerInput(val, p_profile->ltriggerthreshold) : 0;
|
||||||
break;
|
break;
|
||||||
case DS4KeyCodes::R2:
|
case DS4KeyCodes::R2:
|
||||||
pressed = val > m_pad_config.rtriggerthreshold;
|
pressed = val > p_profile->rtriggerthreshold;
|
||||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0;
|
val = pressed ? NormalizeTriggerInput(val, p_profile->rtriggerthreshold) : 0;
|
||||||
break;
|
break;
|
||||||
case DS4KeyCodes::LSXNeg:
|
case DS4KeyCodes::LSXNeg:
|
||||||
case DS4KeyCodes::LSXPos:
|
case DS4KeyCodes::LSXPos:
|
||||||
case DS4KeyCodes::LSYNeg:
|
case DS4KeyCodes::LSYNeg:
|
||||||
case DS4KeyCodes::LSYPos:
|
case DS4KeyCodes::LSYPos:
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
pressed = val > (ignore_threshold ? 0 : p_profile->lstickdeadzone);
|
||||||
val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
val = pressed ? NormalizeStickInput(val, p_profile->lstickdeadzone, ignore_threshold) : 0;
|
||||||
break;
|
break;
|
||||||
case DS4KeyCodes::RSXNeg:
|
case DS4KeyCodes::RSXNeg:
|
||||||
case DS4KeyCodes::RSXPos:
|
case DS4KeyCodes::RSXPos:
|
||||||
case DS4KeyCodes::RSYNeg:
|
case DS4KeyCodes::RSYNeg:
|
||||||
case DS4KeyCodes::RSYPos:
|
case DS4KeyCodes::RSYPos:
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
pressed = val > (ignore_threshold ? 0 : p_profile->rstickdeadzone);
|
||||||
val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
val = pressed ? NormalizeStickInput(val, p_profile->rstickdeadzone, ignore_threshold) : 0;
|
||||||
break;
|
break;
|
||||||
default: // normal button (should in theory also support sensitive buttons)
|
default: // normal button (should in theory also support sensitive buttons)
|
||||||
pressed = val > 0;
|
pressed = val > 0;
|
||||||
@ -406,8 +423,8 @@ void ds4_pad_handler::ProcessDataToPad(const std::shared_ptr<DS4Device>& device,
|
|||||||
pad->m_cable_state = device->cableState;
|
pad->m_cable_state = device->cableState;
|
||||||
|
|
||||||
auto buf = device->padData;
|
auto buf = device->padData;
|
||||||
|
|
||||||
auto button_values = GetButtonValues(device);
|
auto button_values = GetButtonValues(device);
|
||||||
|
auto p_profile = device->config;
|
||||||
|
|
||||||
// Translate any corresponding keycodes to our normal DS3 buttons and triggers
|
// Translate any corresponding keycodes to our normal DS3 buttons and triggers
|
||||||
for (auto & btn : pad->m_buttons)
|
for (auto & btn : pad->m_buttons)
|
||||||
@ -428,7 +445,7 @@ void ds4_pad_handler::ProcessDataToPad(const std::shared_ptr<DS4Device>& device,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// used to get the absolute value of an axis
|
// used to get the absolute value of an axis
|
||||||
float stick_val[4];
|
s32 stick_val[4];
|
||||||
|
|
||||||
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
||||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||||
@ -452,13 +469,13 @@ void ds4_pad_handler::ProcessDataToPad(const std::shared_ptr<DS4Device>& device,
|
|||||||
u16 lx, ly, rx, ry;
|
u16 lx, ly, rx, ry;
|
||||||
|
|
||||||
// Normalize our two stick's axis based on the thresholds
|
// Normalize our two stick's axis based on the thresholds
|
||||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], m_pad_config.lstickdeadzone);
|
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], p_profile->lstickdeadzone);
|
||||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], m_pad_config.rstickdeadzone);
|
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], p_profile->rstickdeadzone);
|
||||||
|
|
||||||
if (m_pad_config.padsquircling != 0)
|
if (p_profile->padsquircling != 0)
|
||||||
{
|
{
|
||||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, p_profile->padsquircling);
|
||||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, p_profile->padsquircling);
|
||||||
}
|
}
|
||||||
|
|
||||||
ly = 255 - ly;
|
ly = 255 - ly;
|
||||||
@ -654,6 +671,10 @@ ds4_pad_handler::~ds4_pad_handler()
|
|||||||
|
|
||||||
int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
||||||
{
|
{
|
||||||
|
auto p_profile = device->config;
|
||||||
|
if (p_profile == nullptr)
|
||||||
|
return -2; // hid_write and hid_write_control return -1 on error
|
||||||
|
|
||||||
std::array<u8, 78> outputBuf{0};
|
std::array<u8, 78> outputBuf{0};
|
||||||
// write rumble state
|
// write rumble state
|
||||||
if (device->btCon)
|
if (device->btCon)
|
||||||
@ -663,9 +684,9 @@ int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
|||||||
outputBuf[3] = 0x07;
|
outputBuf[3] = 0x07;
|
||||||
outputBuf[6] = device->smallVibrate;
|
outputBuf[6] = device->smallVibrate;
|
||||||
outputBuf[7] = device->largeVibrate;
|
outputBuf[7] = device->largeVibrate;
|
||||||
outputBuf[8] = m_pad_config.colorR; // red
|
outputBuf[8] = p_profile->colorR; // red
|
||||||
outputBuf[9] = m_pad_config.colorG; // green
|
outputBuf[9] = p_profile->colorG; // green
|
||||||
outputBuf[10] = m_pad_config.colorB; // blue
|
outputBuf[10] = p_profile->colorB; // blue
|
||||||
|
|
||||||
// alternating blink states with values 0-255: only setting both to zero disables blinking
|
// alternating blink states with values 0-255: only setting both to zero disables blinking
|
||||||
// 255 is roughly 2 seconds, so setting both values to 255 results in a 4 second interval
|
// 255 is roughly 2 seconds, so setting both values to 255 results in a 4 second interval
|
||||||
@ -690,9 +711,9 @@ int ds4_pad_handler::SendVibrateData(const std::shared_ptr<DS4Device>& device)
|
|||||||
outputBuf[1] = 0x07;
|
outputBuf[1] = 0x07;
|
||||||
outputBuf[4] = device->smallVibrate;
|
outputBuf[4] = device->smallVibrate;
|
||||||
outputBuf[5] = device->largeVibrate;
|
outputBuf[5] = device->largeVibrate;
|
||||||
outputBuf[6] = m_pad_config.colorR; // red
|
outputBuf[6] = p_profile->colorR; // red
|
||||||
outputBuf[7] = m_pad_config.colorG; // green
|
outputBuf[7] = p_profile->colorG; // green
|
||||||
outputBuf[8] = m_pad_config.colorB; // blue
|
outputBuf[8] = p_profile->colorB; // blue
|
||||||
outputBuf[9] = device->led_delay_on;
|
outputBuf[9] = device->led_delay_on;
|
||||||
outputBuf[10] = device->led_delay_off;
|
outputBuf[10] = device->led_delay_off;
|
||||||
|
|
||||||
@ -734,10 +755,6 @@ bool ds4_pad_handler::Init()
|
|||||||
else
|
else
|
||||||
LOG_SUCCESS(HLE, "[DS4] Controllers found: %d", controllers.size());
|
LOG_SUCCESS(HLE, "[DS4] Controllers found: %d", controllers.size());
|
||||||
|
|
||||||
m_pad_config.load();
|
|
||||||
if (!m_pad_config.exist())
|
|
||||||
m_pad_config.save();
|
|
||||||
|
|
||||||
is_init = true;
|
is_init = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -763,7 +780,12 @@ bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::strin
|
|||||||
if (ds4device == nullptr || ds4device->hidDevice == nullptr)
|
if (ds4device == nullptr || ds4device->hidDevice == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pad_config.load();
|
int index = static_cast<int>(bindings.size());
|
||||||
|
m_pad_configs[index].load();
|
||||||
|
ds4device->config = &m_pad_configs[index];
|
||||||
|
pad_config* p_profile = ds4device->config;
|
||||||
|
if (p_profile == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
pad->Init
|
pad->Init
|
||||||
(
|
(
|
||||||
@ -774,34 +796,34 @@ bool ds4_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::strin
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 'keycode' here is just 0 as we have to manually calculate this
|
// 'keycode' here is just 0 as we have to manually calculate this
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l2), CELL_PAD_CTRL_L2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l2), CELL_PAD_CTRL_L2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r2), CELL_PAD_CTRL_R2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r2), CELL_PAD_CTRL_R2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.up), CELL_PAD_CTRL_UP);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->up), CELL_PAD_CTRL_UP);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l1), CELL_PAD_CTRL_L1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l1), CELL_PAD_CTRL_L1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r1), CELL_PAD_CTRL_R1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r1), CELL_PAD_CTRL_R1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.start), CELL_PAD_CTRL_START);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->start), CELL_PAD_CTRL_START);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.l3), CELL_PAD_CTRL_L3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->l3), CELL_PAD_CTRL_L3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.r3), CELL_PAD_CTRL_R3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->r3), CELL_PAD_CTRL_R3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||||
|
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Z, 512);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Z, 512);
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_G, 512);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_G, 512);
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, m_pad_config.ls_left), FindKeyCode(button_list, m_pad_config.ls_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, p_profile->ls_left), FindKeyCode(button_list, p_profile->ls_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, m_pad_config.ls_down), FindKeyCode(button_list, m_pad_config.ls_up));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, p_profile->ls_down), FindKeyCode(button_list, p_profile->ls_up));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, m_pad_config.rs_left), FindKeyCode(button_list, m_pad_config.rs_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, p_profile->rs_left), FindKeyCode(button_list, p_profile->rs_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, m_pad_config.rs_down), FindKeyCode(button_list, m_pad_config.rs_up));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, p_profile->rs_down), FindKeyCode(button_list, p_profile->rs_up));
|
||||||
|
|
||||||
pad->m_vibrateMotors.emplace_back(true, 0);
|
pad->m_vibrateMotors.emplace_back(true, 0);
|
||||||
pad->m_vibrateMotors.emplace_back(false, 0);
|
pad->m_vibrateMotors.emplace_back(false, 0);
|
||||||
@ -815,13 +837,14 @@ void ds4_pad_handler::ThreadProc()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < static_cast<int>(bindings.size()); i++)
|
for (int i = 0; i < static_cast<int>(bindings.size()); i++)
|
||||||
{
|
{
|
||||||
std::shared_ptr<DS4Device> device = bindings[i].first;
|
m_dev = bindings[i].first;
|
||||||
auto thepad = bindings[i].second;
|
auto thepad = bindings[i].second;
|
||||||
|
auto profile = m_dev->config;
|
||||||
|
|
||||||
if (device->hidDevice == nullptr)
|
if (m_dev->hidDevice == nullptr)
|
||||||
{
|
{
|
||||||
// try to reconnect
|
// try to reconnect
|
||||||
hid_device* dev = hid_open_path(device->path.c_str());
|
hid_device* dev = hid_open_path(m_dev->path.c_str());
|
||||||
if (dev)
|
if (dev)
|
||||||
{
|
{
|
||||||
if (last_connection_status[i] == false)
|
if (last_connection_status[i] == false)
|
||||||
@ -831,10 +854,10 @@ void ds4_pad_handler::ThreadProc()
|
|||||||
connected++;
|
connected++;
|
||||||
}
|
}
|
||||||
hid_set_nonblocking(dev, 1);
|
hid_set_nonblocking(dev, 1);
|
||||||
device->hidDevice = dev;
|
m_dev->hidDevice = dev;
|
||||||
thepad->m_port_status = CELL_PAD_STATUS_CONNECTED|CELL_PAD_STATUS_ASSIGN_CHANGES;
|
thepad->m_port_status = CELL_PAD_STATUS_CONNECTED|CELL_PAD_STATUS_ASSIGN_CHANGES;
|
||||||
if (!device->hasCalibData)
|
if (!m_dev->hasCalibData)
|
||||||
device->hasCalibData = GetCalibrationData(device);
|
m_dev->hasCalibData = GetCalibrationData(m_dev);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -856,53 +879,53 @@ void ds4_pad_handler::ThreadProc()
|
|||||||
connected++;
|
connected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
DS4DataStatus status = GetRawData(device);
|
DS4DataStatus status = GetRawData(m_dev);
|
||||||
|
|
||||||
if (status == DS4DataStatus::ReadError)
|
if (status == DS4DataStatus::ReadError)
|
||||||
{
|
{
|
||||||
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
||||||
hid_close(device->hidDevice);
|
hid_close(m_dev->hidDevice);
|
||||||
device->hidDevice = nullptr;
|
m_dev->hidDevice = nullptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to send rumble no matter what
|
// Attempt to send rumble no matter what
|
||||||
int idx_l = m_pad_config.switch_vibration_motors ? 1 : 0;
|
int idx_l = profile->switch_vibration_motors ? 1 : 0;
|
||||||
int idx_s = m_pad_config.switch_vibration_motors ? 0 : 1;
|
int idx_s = profile->switch_vibration_motors ? 0 : 1;
|
||||||
|
|
||||||
int speed_large = m_pad_config.enable_vibration_motor_large ? thepad->m_vibrateMotors[idx_l].m_value : vibration_min;
|
int speed_large = profile->enable_vibration_motor_large ? thepad->m_vibrateMotors[idx_l].m_value : vibration_min;
|
||||||
int speed_small = m_pad_config.enable_vibration_motor_small ? thepad->m_vibrateMotors[idx_s].m_value : vibration_min;
|
int speed_small = profile->enable_vibration_motor_small ? thepad->m_vibrateMotors[idx_s].m_value : vibration_min;
|
||||||
|
|
||||||
bool wireless = device->cableState < 1;
|
bool wireless = m_dev->cableState < 1;
|
||||||
bool lowBattery = device->batteryLevel < 2;
|
bool lowBattery = m_dev->batteryLevel < 2;
|
||||||
bool isBlinking = device->led_delay_on > 0 || device->led_delay_off > 0;
|
bool isBlinking = m_dev->led_delay_on > 0 || m_dev->led_delay_off > 0;
|
||||||
bool newBlinkData = false;
|
bool newBlinkData = false;
|
||||||
|
|
||||||
// we are now wired or have okay battery level -> stop blinking
|
// we are now wired or have okay battery level -> stop blinking
|
||||||
if (isBlinking && !(wireless && lowBattery))
|
if (isBlinking && !(wireless && lowBattery))
|
||||||
{
|
{
|
||||||
device->led_delay_on = 0;
|
m_dev->led_delay_on = 0;
|
||||||
device->led_delay_off = 0;
|
m_dev->led_delay_off = 0;
|
||||||
newBlinkData = true;
|
newBlinkData = true;
|
||||||
}
|
}
|
||||||
// we are now wireless and low on battery -> blink
|
// we are now wireless and low on battery -> blink
|
||||||
if (!isBlinking && wireless && lowBattery)
|
if (!isBlinking && wireless && lowBattery)
|
||||||
{
|
{
|
||||||
device->led_delay_on = 100;
|
m_dev->led_delay_on = 100;
|
||||||
device->led_delay_off = 100;
|
m_dev->led_delay_off = 100;
|
||||||
newBlinkData = true;
|
newBlinkData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->newVibrateData = device->newVibrateData || device->largeVibrate != speed_large || device->smallVibrate != speed_small || newBlinkData;
|
m_dev->newVibrateData = m_dev->newVibrateData || m_dev->largeVibrate != speed_large || m_dev->smallVibrate != speed_small || newBlinkData;
|
||||||
|
|
||||||
device->largeVibrate = speed_large;
|
m_dev->largeVibrate = speed_large;
|
||||||
device->smallVibrate = speed_small;
|
m_dev->smallVibrate = speed_small;
|
||||||
|
|
||||||
if (device->newVibrateData)
|
if (m_dev->newVibrateData)
|
||||||
{
|
{
|
||||||
if (SendVibrateData(device) >= 0)
|
if (SendVibrateData(m_dev) >= 0)
|
||||||
{
|
{
|
||||||
device->newVibrateData = false;
|
m_dev->newVibrateData = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +934,7 @@ void ds4_pad_handler::ThreadProc()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
else if (status == DS4DataStatus::NewData)
|
else if (status == DS4DataStatus::NewData)
|
||||||
ProcessDataToPad(device, thepad);
|
ProcessDataToPad(m_dev, thepad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ class ds4_pad_handler final : public PadHandlerBase
|
|||||||
struct DS4Device
|
struct DS4Device
|
||||||
{
|
{
|
||||||
hid_device* hidDevice{ nullptr };
|
hid_device* hidDevice{ nullptr };
|
||||||
|
pad_config* config{ nullptr };
|
||||||
std::string path{ "" };
|
std::string path{ "" };
|
||||||
bool btCon{ false };
|
bool btCon{ false };
|
||||||
bool hasCalibData{ false };
|
bool hasCalibData{ false };
|
||||||
@ -143,12 +144,14 @@ public:
|
|||||||
void ThreadProc() override;
|
void ThreadProc() override;
|
||||||
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& buttonCallback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& buttonCallback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
||||||
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
|
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
|
||||||
|
void init_config(pad_config* cfg, const std::string& name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_init;
|
bool is_init = false;
|
||||||
|
|
||||||
std::vector<u32> blacklist;
|
std::vector<u32> blacklist;
|
||||||
std::vector<std::pair<std::shared_ptr<DS4Device>, std::shared_ptr<Pad>>> bindings;
|
std::vector<std::pair<std::shared_ptr<DS4Device>, std::shared_ptr<Pad>>> bindings;
|
||||||
|
std::shared_ptr<DS4Device> m_dev;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<DS4Device> GetDevice(const std::string& padId);
|
std::shared_ptr<DS4Device> GetDevice(const std::string& padId);
|
||||||
|
@ -123,6 +123,7 @@
|
|||||||
<ClCompile Include="Emu\CPU\CPUTranslator.cpp">
|
<ClCompile Include="Emu\CPU\CPUTranslator.cpp">
|
||||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\Io\PadHandler.cpp" />
|
||||||
<ClCompile Include="Emu\PSP2\ARMv7Module.cpp" />
|
<ClCompile Include="Emu\PSP2\ARMv7Module.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\lv2\lv2.cpp" />
|
<ClCompile Include="Emu\Cell\lv2\lv2.cpp" />
|
||||||
<ClCompile Include="Emu\Cell\lv2\sys_cond.cpp" />
|
<ClCompile Include="Emu\Cell\lv2\sys_cond.cpp" />
|
||||||
|
@ -935,6 +935,9 @@
|
|||||||
<ClCompile Include="Emu\Cell\lv2\sys_net.cpp">
|
<ClCompile Include="Emu\Cell\lv2\sys_net.cpp">
|
||||||
<Filter>Emu\Cell\lv2</Filter>
|
<Filter>Emu\Cell\lv2</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\Io\PadHandler.cpp">
|
||||||
|
<Filter>Emu\Io</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Crypto\aes.h">
|
<ClInclude Include="Crypto\aes.h">
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
evdev_joystick_handler::evdev_joystick_handler()
|
evdev_joystick_handler::evdev_joystick_handler() : PadHandlerBase(pad_handler::evdev)
|
||||||
{
|
{
|
||||||
|
init_configs();
|
||||||
|
|
||||||
// Define border values
|
// Define border values
|
||||||
thumb_min = 0;
|
thumb_min = 0;
|
||||||
thumb_max = 255;
|
thumb_max = 255;
|
||||||
@ -27,47 +29,6 @@ evdev_joystick_handler::evdev_joystick_handler()
|
|||||||
vibration_min = 0;
|
vibration_min = 0;
|
||||||
vibration_max = 65535;
|
vibration_max = 65535;
|
||||||
|
|
||||||
// Set this handler's type and save location
|
|
||||||
m_pad_config.cfg_type = "evdev";
|
|
||||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_evdev.yml";
|
|
||||||
|
|
||||||
// Set default button mapping
|
|
||||||
m_pad_config.ls_left.def = rev_axis_list.at(ABS_X);
|
|
||||||
m_pad_config.ls_down.def = axis_list.at(ABS_Y);
|
|
||||||
m_pad_config.ls_right.def = axis_list.at(ABS_X);
|
|
||||||
m_pad_config.ls_up.def = rev_axis_list.at(ABS_Y);
|
|
||||||
m_pad_config.rs_left.def = rev_axis_list.at(ABS_RX);
|
|
||||||
m_pad_config.rs_down.def = axis_list.at(ABS_RY);
|
|
||||||
m_pad_config.rs_right.def = axis_list.at(ABS_RX);
|
|
||||||
m_pad_config.rs_up.def = rev_axis_list.at(ABS_RY);
|
|
||||||
m_pad_config.start.def = button_list.at(BTN_START);
|
|
||||||
m_pad_config.select.def = button_list.at(BTN_SELECT);
|
|
||||||
m_pad_config.ps.def = button_list.at(BTN_MODE);
|
|
||||||
m_pad_config.square.def = button_list.at(BTN_X);
|
|
||||||
m_pad_config.cross.def = button_list.at(BTN_A);
|
|
||||||
m_pad_config.circle.def = button_list.at(BTN_B);
|
|
||||||
m_pad_config.triangle.def = button_list.at(BTN_Y);
|
|
||||||
m_pad_config.left.def = rev_axis_list.at(ABS_HAT0X);
|
|
||||||
m_pad_config.down.def = axis_list.at(ABS_HAT0Y);
|
|
||||||
m_pad_config.right.def = axis_list.at(ABS_HAT0X);
|
|
||||||
m_pad_config.up.def = rev_axis_list.at(ABS_HAT0Y);
|
|
||||||
m_pad_config.r1.def = button_list.at(BTN_TR);
|
|
||||||
m_pad_config.r2.def = axis_list.at(ABS_RZ);
|
|
||||||
m_pad_config.r3.def = button_list.at(BTN_THUMBR);
|
|
||||||
m_pad_config.l1.def = button_list.at(BTN_TL);
|
|
||||||
m_pad_config.l2.def = axis_list.at(ABS_Z);
|
|
||||||
m_pad_config.l3.def = button_list.at(BTN_THUMBL);
|
|
||||||
|
|
||||||
// Set default misc variables
|
|
||||||
m_pad_config.lstickdeadzone.def = 30; // between 0 and 255
|
|
||||||
m_pad_config.rstickdeadzone.def = 30; // between 0 and 255
|
|
||||||
m_pad_config.ltriggerthreshold.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.rtriggerthreshold.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.padsquircling.def = 5000;
|
|
||||||
|
|
||||||
// apply defaults
|
|
||||||
m_pad_config.from_default();
|
|
||||||
|
|
||||||
// set capabilities
|
// set capabilities
|
||||||
b_has_config = true;
|
b_has_config = true;
|
||||||
b_has_rumble = true;
|
b_has_rumble = true;
|
||||||
@ -82,12 +43,54 @@ evdev_joystick_handler::~evdev_joystick_handler()
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void evdev_joystick_handler::init_config(pad_config* cfg, const std::string& name)
|
||||||
|
{
|
||||||
|
// Set this profile's save location
|
||||||
|
cfg->cfg_name = name;
|
||||||
|
|
||||||
|
// Set default button mapping
|
||||||
|
cfg->ls_left.def = rev_axis_list.at(ABS_X);
|
||||||
|
cfg->ls_down.def = axis_list.at(ABS_Y);
|
||||||
|
cfg->ls_right.def = axis_list.at(ABS_X);
|
||||||
|
cfg->ls_up.def = rev_axis_list.at(ABS_Y);
|
||||||
|
cfg->rs_left.def = rev_axis_list.at(ABS_RX);
|
||||||
|
cfg->rs_down.def = axis_list.at(ABS_RY);
|
||||||
|
cfg->rs_right.def = axis_list.at(ABS_RX);
|
||||||
|
cfg->rs_up.def = rev_axis_list.at(ABS_RY);
|
||||||
|
cfg->start.def = button_list.at(BTN_START);
|
||||||
|
cfg->select.def = button_list.at(BTN_SELECT);
|
||||||
|
cfg->ps.def = button_list.at(BTN_MODE);
|
||||||
|
cfg->square.def = button_list.at(BTN_X);
|
||||||
|
cfg->cross.def = button_list.at(BTN_A);
|
||||||
|
cfg->circle.def = button_list.at(BTN_B);
|
||||||
|
cfg->triangle.def = button_list.at(BTN_Y);
|
||||||
|
cfg->left.def = rev_axis_list.at(ABS_HAT0X);
|
||||||
|
cfg->down.def = axis_list.at(ABS_HAT0Y);
|
||||||
|
cfg->right.def = axis_list.at(ABS_HAT0X);
|
||||||
|
cfg->up.def = rev_axis_list.at(ABS_HAT0Y);
|
||||||
|
cfg->r1.def = button_list.at(BTN_TR);
|
||||||
|
cfg->r2.def = axis_list.at(ABS_RZ);
|
||||||
|
cfg->r3.def = button_list.at(BTN_THUMBR);
|
||||||
|
cfg->l1.def = button_list.at(BTN_TL);
|
||||||
|
cfg->l2.def = axis_list.at(ABS_Z);
|
||||||
|
cfg->l3.def = button_list.at(BTN_THUMBL);
|
||||||
|
|
||||||
|
// Set default misc variables
|
||||||
|
cfg->lstickdeadzone.def = 30; // between 0 and 255
|
||||||
|
cfg->rstickdeadzone.def = 30; // between 0 and 255
|
||||||
|
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->padsquircling.def = 5000;
|
||||||
|
|
||||||
|
// apply defaults
|
||||||
|
cfg->from_default();
|
||||||
|
}
|
||||||
|
|
||||||
bool evdev_joystick_handler::Init()
|
bool evdev_joystick_handler::Init()
|
||||||
{
|
{
|
||||||
if (m_is_init)
|
if (m_is_init)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
m_pad_config.load();
|
|
||||||
m_pos_axis_config.load();
|
m_pos_axis_config.load();
|
||||||
|
|
||||||
if (!m_pos_axis_config.exist())
|
if (!m_pos_axis_config.exist())
|
||||||
@ -498,6 +501,7 @@ void evdev_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u1
|
|||||||
{
|
{
|
||||||
// Update the pad button values based on their type and thresholds.
|
// Update the pad button values based on their type and thresholds.
|
||||||
// With this you can use axis or triggers as buttons or vice versa
|
// With this you can use axis or triggers as buttons or vice versa
|
||||||
|
auto profile = m_dev.config;
|
||||||
u32 code = static_cast<u32>(keyCode);
|
u32 code = static_cast<u32>(keyCode);
|
||||||
auto checkButton = [&](const EvdevButton& b)
|
auto checkButton = [&](const EvdevButton& b)
|
||||||
{
|
{
|
||||||
@ -510,23 +514,23 @@ void evdev_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u1
|
|||||||
|
|
||||||
if (checkButton(m_dev.trigger_left))
|
if (checkButton(m_dev.trigger_left))
|
||||||
{
|
{
|
||||||
pressed = value > m_pad_config.ltriggerthreshold;
|
pressed = value > profile->ltriggerthreshold;
|
||||||
value = pressed ? NormalizeTriggerInput(value, m_pad_config.ltriggerthreshold) : 0;
|
value = pressed ? NormalizeTriggerInput(value, profile->ltriggerthreshold) : 0;
|
||||||
}
|
}
|
||||||
else if (checkButton(m_dev.trigger_right))
|
else if (checkButton(m_dev.trigger_right))
|
||||||
{
|
{
|
||||||
pressed = value > m_pad_config.rtriggerthreshold;
|
pressed = value > profile->rtriggerthreshold;
|
||||||
value = pressed ? NormalizeTriggerInput(value, m_pad_config.rtriggerthreshold) : 0;
|
value = pressed ? NormalizeTriggerInput(value, profile->rtriggerthreshold) : 0;
|
||||||
}
|
}
|
||||||
else if (checkButtons(m_dev.axis_left))
|
else if (checkButtons(m_dev.axis_left))
|
||||||
{
|
{
|
||||||
pressed = value > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
pressed = value > (ignore_threshold ? 0 : profile->lstickdeadzone);
|
||||||
value = pressed ? NormalizeStickInput(value, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
value = pressed ? NormalizeStickInput(value, profile->lstickdeadzone, ignore_threshold) : 0;
|
||||||
}
|
}
|
||||||
else if (checkButtons(m_dev.axis_right))
|
else if (checkButtons(m_dev.axis_right))
|
||||||
{
|
{
|
||||||
pressed = value > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
pressed = value > (ignore_threshold ? 0 : profile->rstickdeadzone);
|
||||||
value = pressed ? NormalizeStickInput(value, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
value = pressed ? NormalizeStickInput(value, profile->rstickdeadzone, ignore_threshold) : 0;
|
||||||
}
|
}
|
||||||
else // normal button (should in theory also support sensitive buttons)
|
else // normal button (should in theory also support sensitive buttons)
|
||||||
{
|
{
|
||||||
@ -608,7 +612,7 @@ std::vector<std::string> evdev_joystick_handler::ListDevices()
|
|||||||
libevdev_has_event_code(dev, EV_ABS, ABS_Y))
|
libevdev_has_event_code(dev, EV_ABS, ABS_Y))
|
||||||
{
|
{
|
||||||
// It's a joystick.
|
// It's a joystick.
|
||||||
evdev_joystick_list.push_back(libevdev_get_name(dev));
|
evdev_joystick_list.push_back(et.name + ": " + libevdev_get_name(dev));
|
||||||
}
|
}
|
||||||
libevdev_free(dev);
|
libevdev_free(dev);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -643,7 +647,7 @@ int evdev_joystick_handler::add_device(const std::string& device, bool in_settin
|
|||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const std::string name = libevdev_get_name(dev);
|
const std::string name = et.name + ": " + libevdev_get_name(dev);
|
||||||
if (libevdev_has_event_type(dev, EV_KEY) &&
|
if (libevdev_has_event_type(dev, EV_KEY) &&
|
||||||
libevdev_has_event_code(dev, EV_ABS, ABS_X) &&
|
libevdev_has_event_code(dev, EV_ABS, ABS_X) &&
|
||||||
libevdev_has_event_code(dev, EV_ABS, ABS_Y) &&
|
libevdev_has_event_code(dev, EV_ABS, ABS_Y) &&
|
||||||
@ -680,6 +684,7 @@ void evdev_joystick_handler::ThreadProc()
|
|||||||
for (auto& device : devices)
|
for (auto& device : devices)
|
||||||
{
|
{
|
||||||
m_dev = device;
|
m_dev = device;
|
||||||
|
auto profile = device.config;
|
||||||
auto pad = device.pad;
|
auto pad = device.pad;
|
||||||
auto axis_orientations = device.axis_orientations;
|
auto axis_orientations = device.axis_orientations;
|
||||||
auto& dev = device.device;
|
auto& dev = device.device;
|
||||||
@ -704,10 +709,10 @@ void evdev_joystick_handler::ThreadProc()
|
|||||||
padnum++;
|
padnum++;
|
||||||
|
|
||||||
// Handle vibration
|
// Handle vibration
|
||||||
int idx_l = m_pad_config.switch_vibration_motors ? 1 : 0;
|
int idx_l = profile->switch_vibration_motors ? 1 : 0;
|
||||||
int idx_s = m_pad_config.switch_vibration_motors ? 0 : 1;
|
int idx_s = profile->switch_vibration_motors ? 0 : 1;
|
||||||
u16 force_large = m_pad_config.enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
u16 force_large = profile->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
||||||
u16 force_small = m_pad_config.enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
u16 force_small = profile->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
||||||
SetRumble(&device, force_large, force_small);
|
SetRumble(&device, force_large, force_small);
|
||||||
|
|
||||||
// Try to query the latest event from the joystick.
|
// Try to query the latest event from the joystick.
|
||||||
@ -832,13 +837,13 @@ void evdev_joystick_handler::ThreadProc()
|
|||||||
u16 lx, ly, rx, ry;
|
u16 lx, ly, rx, ry;
|
||||||
|
|
||||||
// Normalize our two stick's axis based on the thresholds
|
// Normalize our two stick's axis based on the thresholds
|
||||||
std::tie(lx, ly) = NormalizeStickDeadzone(device.stick_val[0], device.stick_val[1], m_pad_config.lstickdeadzone);
|
std::tie(lx, ly) = NormalizeStickDeadzone(device.stick_val[0], device.stick_val[1], profile->lstickdeadzone);
|
||||||
std::tie(rx, ry) = NormalizeStickDeadzone(device.stick_val[2], device.stick_val[3], m_pad_config.rstickdeadzone);
|
std::tie(rx, ry) = NormalizeStickDeadzone(device.stick_val[2], device.stick_val[3], profile->rstickdeadzone);
|
||||||
|
|
||||||
if (m_pad_config.padsquircling != 0)
|
if (profile->padsquircling != 0)
|
||||||
{
|
{
|
||||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, profile->padsquircling);
|
||||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, profile->padsquircling);
|
||||||
}
|
}
|
||||||
|
|
||||||
pad->m_sticks[0].m_value = lx;
|
pad->m_sticks[0].m_value = lx;
|
||||||
@ -866,6 +871,13 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std
|
|||||||
int i = 0; // increment to know the axis location (17-24). Be careful if you ever add more find_key() calls in here (BUTTON_COUNT = 17)
|
int i = 0; // increment to know the axis location (17-24). Be careful if you ever add more find_key() calls in here (BUTTON_COUNT = 17)
|
||||||
int last_type = EV_ABS;
|
int last_type = EV_ABS;
|
||||||
|
|
||||||
|
int index = static_cast<int>(devices.size());
|
||||||
|
m_pad_configs[index].load();
|
||||||
|
m_dev.config = &m_pad_configs[index];
|
||||||
|
pad_config* p_profile = m_dev.config;
|
||||||
|
if (p_profile == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
auto find_key = [&](const cfg::string& name)
|
auto find_key = [&](const cfg::string& name)
|
||||||
{
|
{
|
||||||
int type = EV_ABS;
|
int type = EV_ABS;
|
||||||
@ -909,38 +921,38 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std
|
|||||||
CELL_PAD_DEV_TYPE_STANDARD
|
CELL_PAD_DEV_TYPE_STANDARD
|
||||||
);
|
);
|
||||||
|
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||||
|
|
||||||
m_dev.trigger_left = evdevbutton(m_pad_config.l2);
|
m_dev.trigger_left = evdevbutton(p_profile->l2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_left.code, CELL_PAD_CTRL_L2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_left.code, CELL_PAD_CTRL_L2);
|
||||||
|
|
||||||
m_dev.trigger_right = evdevbutton(m_pad_config.r2);
|
m_dev.trigger_right = evdevbutton(p_profile->r2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_right.code, CELL_PAD_CTRL_R2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, m_dev.trigger_right.code, CELL_PAD_CTRL_R2);
|
||||||
|
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l1), CELL_PAD_CTRL_L1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r1), CELL_PAD_CTRL_R1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->start), CELL_PAD_CTRL_START);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.l3), CELL_PAD_CTRL_L3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->l3), CELL_PAD_CTRL_L3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.r3), CELL_PAD_CTRL_R3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->r3), CELL_PAD_CTRL_R3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.up), CELL_PAD_CTRL_UP);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->up), CELL_PAD_CTRL_UP);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||||
|
|
||||||
m_dev.axis_left[0] = evdevbutton(m_pad_config.ls_right);
|
m_dev.axis_left[0] = evdevbutton(p_profile->ls_right);
|
||||||
m_dev.axis_left[1] = evdevbutton(m_pad_config.ls_left);
|
m_dev.axis_left[1] = evdevbutton(p_profile->ls_left);
|
||||||
m_dev.axis_left[2] = evdevbutton(m_pad_config.ls_up);
|
m_dev.axis_left[2] = evdevbutton(p_profile->ls_up);
|
||||||
m_dev.axis_left[3] = evdevbutton(m_pad_config.ls_down);
|
m_dev.axis_left[3] = evdevbutton(p_profile->ls_down);
|
||||||
m_dev.axis_right[0] = evdevbutton(m_pad_config.rs_right);
|
m_dev.axis_right[0] = evdevbutton(p_profile->rs_right);
|
||||||
m_dev.axis_right[1] = evdevbutton(m_pad_config.rs_left);
|
m_dev.axis_right[1] = evdevbutton(p_profile->rs_left);
|
||||||
m_dev.axis_right[2] = evdevbutton(m_pad_config.rs_up);
|
m_dev.axis_right[2] = evdevbutton(p_profile->rs_up);
|
||||||
m_dev.axis_right[3] = evdevbutton(m_pad_config.rs_down);
|
m_dev.axis_right[3] = evdevbutton(p_profile->rs_down);
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, m_dev.axis_left[1].code, m_dev.axis_left[0].code);
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, m_dev.axis_left[1].code, m_dev.axis_left[0].code);
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, m_dev.axis_left[3].code, m_dev.axis_left[2].code);
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, m_dev.axis_left[3].code, m_dev.axis_left[2].code);
|
||||||
|
@ -302,11 +302,12 @@ class evdev_joystick_handler final : public PadHandlerBase
|
|||||||
|
|
||||||
struct EvdevDevice
|
struct EvdevDevice
|
||||||
{
|
{
|
||||||
libevdev* device = nullptr;
|
libevdev* device{ nullptr };
|
||||||
|
pad_config* config{ nullptr };
|
||||||
std::string path;
|
std::string path;
|
||||||
std::shared_ptr<Pad> pad;
|
std::shared_ptr<Pad> pad;
|
||||||
std::unordered_map<int, bool> axis_orientations; // value is true if key was found in rev_axis_list
|
std::unordered_map<int, bool> axis_orientations; // value is true if key was found in rev_axis_list
|
||||||
float stick_val[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
s32 stick_val[4] = { 0, 0, 0, 0 };
|
||||||
u16 val_min[4] = { 0, 0, 0, 0 };
|
u16 val_min[4] = { 0, 0, 0, 0 };
|
||||||
u16 val_max[4] = { 0, 0, 0, 0 };
|
u16 val_max[4] = { 0, 0, 0, 0 };
|
||||||
EvdevButton trigger_left = { 0, 0, 0 };
|
EvdevButton trigger_left = { 0, 0, 0 };
|
||||||
@ -328,6 +329,7 @@ public:
|
|||||||
evdev_joystick_handler();
|
evdev_joystick_handler();
|
||||||
~evdev_joystick_handler();
|
~evdev_joystick_handler();
|
||||||
|
|
||||||
|
void init_config(pad_config* cfg, const std::string& name) override;
|
||||||
bool Init() override;
|
bool Init() override;
|
||||||
std::vector<std::string> ListDevices() override;
|
std::vector<std::string> ListDevices() override;
|
||||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "keyboard_pad_handler.h"
|
||||||
|
|
||||||
#include "keyboard_pad_handler.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
#include "rpcs3qt/pad_settings_dialog.h"
|
|
||||||
|
|
||||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
|
|
||||||
@ -14,46 +10,50 @@ bool keyboard_pad_handler::Init()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard_pad_handler::keyboard_pad_handler() : QObject()
|
keyboard_pad_handler::keyboard_pad_handler() : PadHandlerBase(pad_handler::keyboard), QObject()
|
||||||
{
|
{
|
||||||
// Set this handler's type and save location
|
init_configs();
|
||||||
m_pad_config.cfg_type = "keyboard";
|
|
||||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_kbpad_qt.yml";
|
|
||||||
|
|
||||||
// Set default button mapping
|
|
||||||
m_pad_config.ls_left.def = GetKeyName(Qt::Key_A);
|
|
||||||
m_pad_config.ls_down.def = GetKeyName(Qt::Key_S);
|
|
||||||
m_pad_config.ls_right.def = GetKeyName(Qt::Key_D);
|
|
||||||
m_pad_config.ls_up.def = GetKeyName(Qt::Key_W);
|
|
||||||
m_pad_config.rs_left.def = GetKeyName(Qt::Key_Home);
|
|
||||||
m_pad_config.rs_down.def = GetKeyName(Qt::Key_PageDown);
|
|
||||||
m_pad_config.rs_right.def = GetKeyName(Qt::Key_End);
|
|
||||||
m_pad_config.rs_up.def = GetKeyName(Qt::Key_PageUp);
|
|
||||||
m_pad_config.start.def = GetKeyName(Qt::Key_Return);
|
|
||||||
m_pad_config.select.def = GetKeyName(Qt::Key_Space);
|
|
||||||
m_pad_config.ps.def = GetKeyName(Qt::Key_Backspace);
|
|
||||||
m_pad_config.square.def = GetKeyName(Qt::Key_Z);
|
|
||||||
m_pad_config.cross.def = GetKeyName(Qt::Key_X);
|
|
||||||
m_pad_config.circle.def = GetKeyName(Qt::Key_C);
|
|
||||||
m_pad_config.triangle.def = GetKeyName(Qt::Key_V);
|
|
||||||
m_pad_config.left.def = GetKeyName(Qt::Key_Left);
|
|
||||||
m_pad_config.down.def = GetKeyName(Qt::Key_Down);
|
|
||||||
m_pad_config.right.def = GetKeyName(Qt::Key_Right);
|
|
||||||
m_pad_config.up.def = GetKeyName(Qt::Key_Up);
|
|
||||||
m_pad_config.r1.def = GetKeyName(Qt::Key_E);
|
|
||||||
m_pad_config.r2.def = GetKeyName(Qt::Key_T);
|
|
||||||
m_pad_config.r3.def = GetKeyName(Qt::Key_G);
|
|
||||||
m_pad_config.l1.def = GetKeyName(Qt::Key_Q);
|
|
||||||
m_pad_config.l2.def = GetKeyName(Qt::Key_R);
|
|
||||||
m_pad_config.l3.def = GetKeyName(Qt::Key_F);
|
|
||||||
|
|
||||||
// apply defaults
|
|
||||||
m_pad_config.from_default();
|
|
||||||
|
|
||||||
// set capabilities
|
// set capabilities
|
||||||
b_has_config = true;
|
b_has_config = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void keyboard_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||||
|
{
|
||||||
|
// Set this profile's save location
|
||||||
|
cfg->cfg_name = name;
|
||||||
|
|
||||||
|
// Set default button mapping
|
||||||
|
cfg->ls_left.def = GetKeyName(Qt::Key_A);
|
||||||
|
cfg->ls_down.def = GetKeyName(Qt::Key_S);
|
||||||
|
cfg->ls_right.def = GetKeyName(Qt::Key_D);
|
||||||
|
cfg->ls_up.def = GetKeyName(Qt::Key_W);
|
||||||
|
cfg->rs_left.def = GetKeyName(Qt::Key_Home);
|
||||||
|
cfg->rs_down.def = GetKeyName(Qt::Key_PageDown);
|
||||||
|
cfg->rs_right.def = GetKeyName(Qt::Key_End);
|
||||||
|
cfg->rs_up.def = GetKeyName(Qt::Key_PageUp);
|
||||||
|
cfg->start.def = GetKeyName(Qt::Key_Return);
|
||||||
|
cfg->select.def = GetKeyName(Qt::Key_Space);
|
||||||
|
cfg->ps.def = GetKeyName(Qt::Key_Backspace);
|
||||||
|
cfg->square.def = GetKeyName(Qt::Key_Z);
|
||||||
|
cfg->cross.def = GetKeyName(Qt::Key_X);
|
||||||
|
cfg->circle.def = GetKeyName(Qt::Key_C);
|
||||||
|
cfg->triangle.def = GetKeyName(Qt::Key_V);
|
||||||
|
cfg->left.def = GetKeyName(Qt::Key_Left);
|
||||||
|
cfg->down.def = GetKeyName(Qt::Key_Down);
|
||||||
|
cfg->right.def = GetKeyName(Qt::Key_Right);
|
||||||
|
cfg->up.def = GetKeyName(Qt::Key_Up);
|
||||||
|
cfg->r1.def = GetKeyName(Qt::Key_E);
|
||||||
|
cfg->r2.def = GetKeyName(Qt::Key_T);
|
||||||
|
cfg->r3.def = GetKeyName(Qt::Key_G);
|
||||||
|
cfg->l1.def = GetKeyName(Qt::Key_Q);
|
||||||
|
cfg->l2.def = GetKeyName(Qt::Key_R);
|
||||||
|
cfg->l3.def = GetKeyName(Qt::Key_F);
|
||||||
|
|
||||||
|
// apply defaults
|
||||||
|
cfg->from_default();
|
||||||
|
}
|
||||||
|
|
||||||
void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
|
void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
|
||||||
{
|
{
|
||||||
value = Clamp0To255(value);
|
value = Clamp0To255(value);
|
||||||
@ -65,30 +65,23 @@ void keyboard_pad_handler::Key(const u32 code, bool pressed, u16 value)
|
|||||||
if (button.m_keyCode != code)
|
if (button.m_keyCode != code)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//Todo: Is this flush necessary once games hit decent speeds?
|
button.m_pressed = pressed;
|
||||||
if (button.m_pressed && !pressed)
|
button.m_value = pressed ? value : 0;
|
||||||
{
|
|
||||||
button.m_flush = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
button.m_pressed = pressed;
|
|
||||||
if (pressed)
|
|
||||||
button.m_value = value;
|
|
||||||
else
|
|
||||||
button.m_value = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||||
{
|
{
|
||||||
if (pad->m_sticks[i].m_keyCodeMax == code)
|
bool is_max = pad->m_sticks[i].m_keyCodeMax == code;
|
||||||
|
bool is_min = pad->m_sticks[i].m_keyCodeMin == code;
|
||||||
|
|
||||||
|
if (is_max)
|
||||||
m_stick_max[i] = pressed ? 255 : 128;
|
m_stick_max[i] = pressed ? 255 : 128;
|
||||||
|
|
||||||
if (pad->m_sticks[i].m_keyCodeMin == code)
|
if (is_min)
|
||||||
m_stick_min[i] = pressed ? 128 : 0;
|
m_stick_min[i] = pressed ? 128 : 0;
|
||||||
|
|
||||||
pad->m_sticks[i].m_value = m_stick_max[i] - m_stick_min[i];
|
if (is_max || is_min)
|
||||||
|
pad->m_sticks[i].m_value = m_stick_max[i] - m_stick_min[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,7 +379,11 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::
|
|||||||
if (device != "Keyboard")
|
if (device != "Keyboard")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pad_config.load();
|
int index = static_cast<int>(bindings.size());
|
||||||
|
m_pad_configs[index].load();
|
||||||
|
pad_config* p_profile = &m_pad_configs[index];
|
||||||
|
if (p_profile == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
auto find_key = [&](const cfg::string& name)
|
auto find_key = [&](const cfg::string& name)
|
||||||
{
|
{
|
||||||
@ -407,29 +404,29 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::
|
|||||||
CELL_PAD_DEV_TYPE_STANDARD
|
CELL_PAD_DEV_TYPE_STANDARD
|
||||||
);
|
);
|
||||||
|
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.up), CELL_PAD_CTRL_UP);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->up), CELL_PAD_CTRL_UP);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->start), CELL_PAD_CTRL_START);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.r3), CELL_PAD_CTRL_R3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->r3), CELL_PAD_CTRL_R3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.l3), CELL_PAD_CTRL_L3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->l3), CELL_PAD_CTRL_L3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r1), CELL_PAD_CTRL_R1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l1), CELL_PAD_CTRL_L1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r2), CELL_PAD_CTRL_R2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r2), CELL_PAD_CTRL_R2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l2), CELL_PAD_CTRL_L2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l2), CELL_PAD_CTRL_L2);
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_key(m_pad_config.ls_left), find_key(m_pad_config.ls_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, find_key(p_profile->ls_left), find_key(p_profile->ls_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_key(m_pad_config.ls_up), find_key(m_pad_config.ls_down));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, find_key(p_profile->ls_up), find_key(p_profile->ls_down));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_key(m_pad_config.rs_left), find_key(m_pad_config.rs_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, find_key(p_profile->rs_left), find_key(p_profile->rs_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_key(m_pad_config.rs_up), find_key(m_pad_config.rs_down));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, find_key(p_profile->rs_up), find_key(p_profile->rs_down));
|
||||||
|
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "Utilities/Config.h"
|
#include "Utilities/Config.h"
|
||||||
#include "Emu/Io/PadHandler.h"
|
#include "Emu/Io/PadHandler.h"
|
||||||
#include "stdafx.h"
|
|
||||||
#include "Emu/System.h"
|
|
||||||
|
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
@ -57,6 +55,7 @@ public:
|
|||||||
|
|
||||||
bool eventFilter(QObject* obj, QEvent* ev) override;
|
bool eventFilter(QObject* obj, QEvent* ev) override;
|
||||||
|
|
||||||
|
void init_config(pad_config* cfg, const std::string& name) override;
|
||||||
std::vector<std::string> ListDevices() override;
|
std::vector<std::string> ListDevices() override;
|
||||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
||||||
void ThreadProc() override;
|
void ThreadProc() override;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include "stdafx.h"
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "mm_joystick_handler.h"
|
#include "mm_joystick_handler.h"
|
||||||
|
|
||||||
mm_joystick_handler::mm_joystick_handler() : is_init(false)
|
mm_joystick_handler::mm_joystick_handler() : PadHandlerBase(pad_handler::mm)
|
||||||
{
|
{
|
||||||
|
init_configs();
|
||||||
|
|
||||||
// Define border values
|
// Define border values
|
||||||
thumb_min = 0;
|
thumb_min = 0;
|
||||||
thumb_max = 255;
|
thumb_max = 255;
|
||||||
@ -12,47 +13,6 @@ mm_joystick_handler::mm_joystick_handler() : is_init(false)
|
|||||||
vibration_min = 0;
|
vibration_min = 0;
|
||||||
vibration_max = 65535;
|
vibration_max = 65535;
|
||||||
|
|
||||||
// Set this handler's type and save location
|
|
||||||
m_pad_config.cfg_type = "mmjoystick";
|
|
||||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_mmjoystick.yml";
|
|
||||||
|
|
||||||
// Set default button mapping
|
|
||||||
m_pad_config.ls_left.def = axis_list.at(mmjoy_axis::joy_x_neg);
|
|
||||||
m_pad_config.ls_down.def = axis_list.at(mmjoy_axis::joy_y_neg);
|
|
||||||
m_pad_config.ls_right.def = axis_list.at(mmjoy_axis::joy_x_pos);
|
|
||||||
m_pad_config.ls_up.def = axis_list.at(mmjoy_axis::joy_y_pos);
|
|
||||||
m_pad_config.rs_left.def = axis_list.at(mmjoy_axis::joy_z_neg);
|
|
||||||
m_pad_config.rs_down.def = axis_list.at(mmjoy_axis::joy_r_neg);
|
|
||||||
m_pad_config.rs_right.def = axis_list.at(mmjoy_axis::joy_z_pos);
|
|
||||||
m_pad_config.rs_up.def = axis_list.at(mmjoy_axis::joy_r_pos);
|
|
||||||
m_pad_config.start.def = button_list.at(JOY_BUTTON9);
|
|
||||||
m_pad_config.select.def = button_list.at(JOY_BUTTON10);
|
|
||||||
m_pad_config.ps.def = button_list.at(JOY_BUTTON17);
|
|
||||||
m_pad_config.square.def = button_list.at(JOY_BUTTON4);
|
|
||||||
m_pad_config.cross.def = button_list.at(JOY_BUTTON3);
|
|
||||||
m_pad_config.circle.def = button_list.at(JOY_BUTTON2);
|
|
||||||
m_pad_config.triangle.def = button_list.at(JOY_BUTTON1);
|
|
||||||
m_pad_config.left.def = pov_list.at(JOY_POVLEFT);
|
|
||||||
m_pad_config.down.def = pov_list.at(JOY_POVBACKWARD);
|
|
||||||
m_pad_config.right.def = pov_list.at(JOY_POVRIGHT);
|
|
||||||
m_pad_config.up.def = pov_list.at(JOY_POVFORWARD);
|
|
||||||
m_pad_config.r1.def = button_list.at(JOY_BUTTON8);
|
|
||||||
m_pad_config.r2.def = button_list.at(JOY_BUTTON6);
|
|
||||||
m_pad_config.r3.def = button_list.at(JOY_BUTTON12);
|
|
||||||
m_pad_config.l1.def = button_list.at(JOY_BUTTON7);
|
|
||||||
m_pad_config.l2.def = button_list.at(JOY_BUTTON5);
|
|
||||||
m_pad_config.l3.def = button_list.at(JOY_BUTTON11);
|
|
||||||
|
|
||||||
// Set default misc variables
|
|
||||||
m_pad_config.lstickdeadzone.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.rstickdeadzone.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.ltriggerthreshold.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.rtriggerthreshold.def = 0; // between 0 and 255
|
|
||||||
m_pad_config.padsquircling.def = 8000;
|
|
||||||
|
|
||||||
// apply defaults
|
|
||||||
m_pad_config.from_default();
|
|
||||||
|
|
||||||
// set capabilities
|
// set capabilities
|
||||||
b_has_config = true;
|
b_has_config = true;
|
||||||
b_has_rumble = true;
|
b_has_rumble = true;
|
||||||
@ -66,24 +26,66 @@ mm_joystick_handler::~mm_joystick_handler()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mm_joystick_handler::init_config(pad_config* cfg, const std::string& name)
|
||||||
|
{
|
||||||
|
// Set this profile's save location
|
||||||
|
cfg->cfg_name = name;
|
||||||
|
|
||||||
|
// Set default button mapping
|
||||||
|
cfg->ls_left.def = axis_list.at(mmjoy_axis::joy_x_neg);
|
||||||
|
cfg->ls_down.def = axis_list.at(mmjoy_axis::joy_y_neg);
|
||||||
|
cfg->ls_right.def = axis_list.at(mmjoy_axis::joy_x_pos);
|
||||||
|
cfg->ls_up.def = axis_list.at(mmjoy_axis::joy_y_pos);
|
||||||
|
cfg->rs_left.def = axis_list.at(mmjoy_axis::joy_z_neg);
|
||||||
|
cfg->rs_down.def = axis_list.at(mmjoy_axis::joy_r_neg);
|
||||||
|
cfg->rs_right.def = axis_list.at(mmjoy_axis::joy_z_pos);
|
||||||
|
cfg->rs_up.def = axis_list.at(mmjoy_axis::joy_r_pos);
|
||||||
|
cfg->start.def = button_list.at(JOY_BUTTON9);
|
||||||
|
cfg->select.def = button_list.at(JOY_BUTTON10);
|
||||||
|
cfg->ps.def = button_list.at(JOY_BUTTON17);
|
||||||
|
cfg->square.def = button_list.at(JOY_BUTTON4);
|
||||||
|
cfg->cross.def = button_list.at(JOY_BUTTON3);
|
||||||
|
cfg->circle.def = button_list.at(JOY_BUTTON2);
|
||||||
|
cfg->triangle.def = button_list.at(JOY_BUTTON1);
|
||||||
|
cfg->left.def = pov_list.at(JOY_POVLEFT);
|
||||||
|
cfg->down.def = pov_list.at(JOY_POVBACKWARD);
|
||||||
|
cfg->right.def = pov_list.at(JOY_POVRIGHT);
|
||||||
|
cfg->up.def = pov_list.at(JOY_POVFORWARD);
|
||||||
|
cfg->r1.def = button_list.at(JOY_BUTTON8);
|
||||||
|
cfg->r2.def = button_list.at(JOY_BUTTON6);
|
||||||
|
cfg->r3.def = button_list.at(JOY_BUTTON12);
|
||||||
|
cfg->l1.def = button_list.at(JOY_BUTTON7);
|
||||||
|
cfg->l2.def = button_list.at(JOY_BUTTON5);
|
||||||
|
cfg->l3.def = button_list.at(JOY_BUTTON11);
|
||||||
|
|
||||||
|
// Set default misc variables
|
||||||
|
cfg->lstickdeadzone.def = 0; // between 0 and 255
|
||||||
|
cfg->rstickdeadzone.def = 0; // between 0 and 255
|
||||||
|
cfg->ltriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->rtriggerthreshold.def = 0; // between 0 and 255
|
||||||
|
cfg->padsquircling.def = 8000;
|
||||||
|
|
||||||
|
// apply defaults
|
||||||
|
cfg->from_default();
|
||||||
|
}
|
||||||
|
|
||||||
bool mm_joystick_handler::Init()
|
bool mm_joystick_handler::Init()
|
||||||
{
|
{
|
||||||
if (is_init) return true;
|
if (is_init)
|
||||||
|
return true;
|
||||||
|
|
||||||
m_devices.clear();
|
m_devices.clear();
|
||||||
supportedJoysticks = joyGetNumDevs();
|
m_supported_joysticks = joyGetNumDevs();
|
||||||
|
|
||||||
if (supportedJoysticks > 0)
|
if (m_supported_joysticks <= 0)
|
||||||
{
|
{
|
||||||
LOG_NOTICE(GENERAL, "Driver supports %u joysticks", supportedJoysticks);
|
LOG_ERROR(GENERAL, "mmjoy: Driver doesn't support Joysticks");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR(GENERAL, "Driver doesn't support Joysticks");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < supportedJoysticks; i++)
|
LOG_NOTICE(GENERAL, "mmjoy: Driver supports %u joysticks", m_supported_joysticks);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_supported_joysticks; i++)
|
||||||
{
|
{
|
||||||
MMJOYDevice dev;
|
MMJOYDevice dev;
|
||||||
|
|
||||||
@ -93,7 +95,6 @@ bool mm_joystick_handler::Init()
|
|||||||
m_devices.emplace(i, dev);
|
m_devices.emplace(i, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pad_config.load();
|
|
||||||
is_init = true;
|
is_init = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -102,7 +103,8 @@ std::vector<std::string> mm_joystick_handler::ListDevices()
|
|||||||
{
|
{
|
||||||
std::vector<std::string> devices;
|
std::vector<std::string> devices;
|
||||||
|
|
||||||
if (!Init()) return devices;
|
if (!Init())
|
||||||
|
return devices;
|
||||||
|
|
||||||
for (auto dev : m_devices)
|
for (auto dev : m_devices)
|
||||||
{
|
{
|
||||||
@ -123,6 +125,13 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::s
|
|||||||
|
|
||||||
std::shared_ptr<MMJOYDevice> joy_device = std::make_shared<MMJOYDevice>(m_devices.at(id));
|
std::shared_ptr<MMJOYDevice> joy_device = std::make_shared<MMJOYDevice>(m_devices.at(id));
|
||||||
|
|
||||||
|
int index = static_cast<int>(bindings.size());
|
||||||
|
m_pad_configs[index].load();
|
||||||
|
joy_device->config = &m_pad_configs[index];
|
||||||
|
pad_config* p_profile = joy_device->config;
|
||||||
|
if (p_profile == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
auto find_key = [=](const cfg::string& name)
|
auto find_key = [=](const cfg::string& name)
|
||||||
{
|
{
|
||||||
long key = FindKeyCode(button_list, name, false);
|
long key = FindKeyCode(button_list, name, false);
|
||||||
@ -141,34 +150,34 @@ bool mm_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::s
|
|||||||
CELL_PAD_DEV_TYPE_STANDARD
|
CELL_PAD_DEV_TYPE_STANDARD
|
||||||
);
|
);
|
||||||
|
|
||||||
joy_device->trigger_left = find_key(m_pad_config.l2);
|
joy_device->trigger_left = find_key(p_profile->l2);
|
||||||
joy_device->trigger_right = find_key(m_pad_config.r2);
|
joy_device->trigger_right = find_key(p_profile->r2);
|
||||||
joy_device->axis_left[0] = find_key(m_pad_config.ls_left);
|
joy_device->axis_left[0] = find_key(p_profile->ls_left);
|
||||||
joy_device->axis_left[1] = find_key(m_pad_config.ls_right);
|
joy_device->axis_left[1] = find_key(p_profile->ls_right);
|
||||||
joy_device->axis_left[2] = find_key(m_pad_config.ls_down);
|
joy_device->axis_left[2] = find_key(p_profile->ls_down);
|
||||||
joy_device->axis_left[3] = find_key(m_pad_config.ls_up);
|
joy_device->axis_left[3] = find_key(p_profile->ls_up);
|
||||||
joy_device->axis_right[0] = find_key(m_pad_config.rs_left);
|
joy_device->axis_right[0] = find_key(p_profile->rs_left);
|
||||||
joy_device->axis_right[1] = find_key(m_pad_config.rs_right);
|
joy_device->axis_right[1] = find_key(p_profile->rs_right);
|
||||||
joy_device->axis_right[2] = find_key(m_pad_config.rs_down);
|
joy_device->axis_right[2] = find_key(p_profile->rs_down);
|
||||||
joy_device->axis_right[3] = find_key(m_pad_config.rs_up);
|
joy_device->axis_right[3] = find_key(p_profile->rs_up);
|
||||||
|
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_left, CELL_PAD_CTRL_L2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_left, CELL_PAD_CTRL_L2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_right, CELL_PAD_CTRL_R2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, joy_device->trigger_right, CELL_PAD_CTRL_R2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.l1), CELL_PAD_CTRL_L1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->l1), CELL_PAD_CTRL_L1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.r1), CELL_PAD_CTRL_R1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->r1), CELL_PAD_CTRL_R1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.start), CELL_PAD_CTRL_START);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->start), CELL_PAD_CTRL_START);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.l3), CELL_PAD_CTRL_L3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->l3), CELL_PAD_CTRL_L3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.r3), CELL_PAD_CTRL_R3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->r3), CELL_PAD_CTRL_R3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.up), CELL_PAD_CTRL_UP);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->up), CELL_PAD_CTRL_UP);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, joy_device->axis_left[0], joy_device->axis_left[1]);
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, joy_device->axis_left[0], joy_device->axis_left[1]);
|
||||||
@ -197,6 +206,7 @@ void mm_joystick_handler::ThreadProc()
|
|||||||
{
|
{
|
||||||
m_dev = bindings[i].first;
|
m_dev = bindings[i].first;
|
||||||
auto pad = bindings[i].second;
|
auto pad = bindings[i].second;
|
||||||
|
auto profile = m_dev->config;
|
||||||
status = joyGetPosEx(m_dev->device_id, &m_dev->device_info);
|
status = joyGetPosEx(m_dev->device_id, &m_dev->device_info);
|
||||||
|
|
||||||
if (status != JOYERR_NOERROR)
|
if (status != JOYERR_NOERROR)
|
||||||
@ -232,7 +242,7 @@ void mm_joystick_handler::ThreadProc()
|
|||||||
TranslateButtonPress(btn.m_keyCode, btn.m_pressed, btn.m_value);
|
TranslateButtonPress(btn.m_keyCode, btn.m_pressed, btn.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
float stick_val[4];
|
s32 stick_val[4];
|
||||||
|
|
||||||
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
||||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||||
@ -256,13 +266,13 @@ void mm_joystick_handler::ThreadProc()
|
|||||||
u16 lx, ly, rx, ry;
|
u16 lx, ly, rx, ry;
|
||||||
|
|
||||||
// Normalize our two stick's axis based on the thresholds
|
// Normalize our two stick's axis based on the thresholds
|
||||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], m_pad_config.lstickdeadzone);
|
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], profile->lstickdeadzone);
|
||||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], m_pad_config.rstickdeadzone);
|
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], profile->rstickdeadzone);
|
||||||
|
|
||||||
if (m_pad_config.padsquircling != 0)
|
if (profile->padsquircling != 0)
|
||||||
{
|
{
|
||||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, profile->padsquircling);
|
||||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, profile->padsquircling);
|
||||||
}
|
}
|
||||||
|
|
||||||
pad->m_sticks[0].m_value = lx;
|
pad->m_sticks[0].m_value = lx;
|
||||||
@ -415,26 +425,27 @@ void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16&
|
|||||||
{
|
{
|
||||||
// Update the pad button values based on their type and thresholds.
|
// Update the pad button values based on their type and thresholds.
|
||||||
// With this you can use axis or triggers as buttons or vice versa
|
// With this you can use axis or triggers as buttons or vice versa
|
||||||
|
auto p_profile = m_dev->config;
|
||||||
|
|
||||||
if (keyCode == m_dev->trigger_left)
|
if (keyCode == m_dev->trigger_left)
|
||||||
{
|
{
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.ltriggerthreshold);
|
pressed = val > (ignore_threshold ? 0 : p_profile->ltriggerthreshold);
|
||||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0;
|
val = pressed ? NormalizeTriggerInput(val, p_profile->ltriggerthreshold) : 0;
|
||||||
}
|
}
|
||||||
else if (keyCode == m_dev->trigger_right)
|
else if (keyCode == m_dev->trigger_right)
|
||||||
{
|
{
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rtriggerthreshold);
|
pressed = val > (ignore_threshold ? 0 : p_profile->rtriggerthreshold);
|
||||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0;
|
val = pressed ? NormalizeTriggerInput(val, p_profile->rtriggerthreshold) : 0;
|
||||||
}
|
}
|
||||||
else if (std::find(m_dev->axis_left.begin(), m_dev->axis_left.end(), keyCode) != m_dev->axis_left.end())
|
else if (std::find(m_dev->axis_left.begin(), m_dev->axis_left.end(), keyCode) != m_dev->axis_left.end())
|
||||||
{
|
{
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
pressed = val > (ignore_threshold ? 0 : p_profile->lstickdeadzone);
|
||||||
val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
val = pressed ? NormalizeStickInput(val, p_profile->lstickdeadzone, ignore_threshold) : 0;
|
||||||
}
|
}
|
||||||
else if (std::find(m_dev->axis_right.begin(), m_dev->axis_right.end(), keyCode) != m_dev->axis_right.end())
|
else if (std::find(m_dev->axis_right.begin(), m_dev->axis_right.end(), keyCode) != m_dev->axis_right.end())
|
||||||
{
|
{
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
pressed = val > (ignore_threshold ? 0 : p_profile->rstickdeadzone);
|
||||||
val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
val = pressed ? NormalizeStickInput(val, p_profile->rstickdeadzone, ignore_threshold) : 0;
|
||||||
}
|
}
|
||||||
else // normal button (should in theory also support sensitive buttons)
|
else // normal button (should in theory also support sensitive buttons)
|
||||||
{
|
{
|
||||||
@ -486,9 +497,9 @@ std::unordered_map<u64, u16> mm_joystick_handler::GetButtonValues(const JOYINFOE
|
|||||||
}
|
}
|
||||||
else if (js_caps.wCaps & JOYCAPS_POV4DIR)
|
else if (js_caps.wCaps & JOYCAPS_POV4DIR)
|
||||||
{
|
{
|
||||||
u64 val = js_info.dwPOV;
|
int val = static_cast<int>(js_info.dwPOV);
|
||||||
|
|
||||||
auto emplacePOV = [&button_values, &val](u64 pov)
|
auto emplacePOV = [&button_values, &val](int pov)
|
||||||
{
|
{
|
||||||
int cw = pov + 4500, ccw = pov - 4500;
|
int cw = pov + 4500, ccw = pov - 4500;
|
||||||
bool pressed = (val == pov) || (val == cw) || (ccw < 0 ? val == 36000 - std::abs(ccw) : val == ccw);
|
bool pressed = (val == pov) || (val == cw) || (ccw < 0 ? val == 36000 - std::abs(ccw) : val == ccw);
|
||||||
@ -540,9 +551,7 @@ int mm_joystick_handler::GetIDByName(const std::string& name)
|
|||||||
for (auto dev : m_devices)
|
for (auto dev : m_devices)
|
||||||
{
|
{
|
||||||
if (dev.second.device_name == name)
|
if (dev.second.device_name == name)
|
||||||
{
|
|
||||||
return dev.first;
|
return dev.first;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ class mm_joystick_handler final : public PadHandlerBase
|
|||||||
{
|
{
|
||||||
u32 device_id{ 0 };
|
u32 device_id{ 0 };
|
||||||
std::string device_name{ "" };
|
std::string device_name{ "" };
|
||||||
|
pad_config* config{ nullptr };
|
||||||
JOYINFOEX device_info;
|
JOYINFOEX device_info;
|
||||||
JOYCAPS device_caps;
|
JOYCAPS device_caps;
|
||||||
u64 trigger_left = 0;
|
u64 trigger_left = 0;
|
||||||
@ -108,6 +109,7 @@ public:
|
|||||||
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
bool bindPadToDevice(std::shared_ptr<Pad> pad, const std::string& device) override;
|
||||||
void ThreadProc() override;
|
void ThreadProc() override;
|
||||||
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
||||||
|
void init_config(pad_config* cfg, const std::string& name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
|
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
|
||||||
@ -116,7 +118,7 @@ private:
|
|||||||
bool GetMMJOYDevice(int index, MMJOYDevice& dev);
|
bool GetMMJOYDevice(int index, MMJOYDevice& dev);
|
||||||
|
|
||||||
bool is_init = false;
|
bool is_init = false;
|
||||||
u32 supportedJoysticks = 0;
|
u32 m_supported_joysticks = 0;
|
||||||
|
|
||||||
std::vector<u64> blacklist;
|
std::vector<u64> blacklist;
|
||||||
std::unordered_map<int, MMJOYDevice> m_devices;
|
std::unordered_map<int, MMJOYDevice> m_devices;
|
||||||
|
@ -30,7 +30,7 @@ void pad_thread::Init(const u32 max_connect)
|
|||||||
m_info.max_connect = std::min(max_connect, (u32)7); // max 7 pads
|
m_info.max_connect = std::min(max_connect, (u32)7); // max 7 pads
|
||||||
m_info.now_connect = 0;
|
m_info.now_connect = 0;
|
||||||
|
|
||||||
input_cfg.load();
|
g_cfg_input.load();
|
||||||
|
|
||||||
std::shared_ptr<keyboard_pad_handler> keyptr;
|
std::shared_ptr<keyboard_pad_handler> keyptr;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ void pad_thread::Init(const u32 max_connect)
|
|||||||
{
|
{
|
||||||
std::shared_ptr<PadHandlerBase> cur_pad_handler;
|
std::shared_ptr<PadHandlerBase> cur_pad_handler;
|
||||||
|
|
||||||
const auto &handler_type = input_cfg.player_input[i];
|
const auto &handler_type = g_cfg_input.player[i]->handler;
|
||||||
|
|
||||||
if (handlers.count(handler_type) != 0)
|
if (handlers.count(handler_type) != 0)
|
||||||
{
|
{
|
||||||
@ -87,11 +87,11 @@ void pad_thread::Init(const u32 max_connect)
|
|||||||
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_ACTUATOR,
|
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_ACTUATOR,
|
||||||
CELL_PAD_DEV_TYPE_STANDARD));
|
CELL_PAD_DEV_TYPE_STANDARD));
|
||||||
|
|
||||||
if (cur_pad_handler->bindPadToDevice(m_pads.back(), input_cfg.player_device[i]->to_string()) == false)
|
if (cur_pad_handler->bindPadToDevice(m_pads.back(), g_cfg_input.player[i]->device.to_string()) == false)
|
||||||
{
|
{
|
||||||
//Failed to bind the device to cur_pad_handler so binds to NullPadHandler
|
//Failed to bind the device to cur_pad_handler so binds to NullPadHandler
|
||||||
LOG_ERROR(GENERAL, "Failed to bind device %s to handler %s", input_cfg.player_device[i]->to_string(), handler_type.to_string());
|
LOG_ERROR(GENERAL, "Failed to bind device %s to handler %s", g_cfg_input.player[i]->device.to_string(), handler_type.to_string());
|
||||||
nullpad->bindPadToDevice(m_pads.back(), input_cfg.player_device[i]->to_string());
|
nullpad->bindPadToDevice(m_pads.back(), g_cfg_input.player[i]->device.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "Emu/System.h"
|
|
||||||
#include "../Utilities/types.h"
|
#include "../Utilities/types.h"
|
||||||
#include "Emu/Io/PadHandler.h"
|
#include "Emu/Io/PadHandler.h"
|
||||||
|
|
||||||
|
@ -10,16 +10,42 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "../keyboard_pad_handler.h"
|
#include "../keyboard_pad_handler.h"
|
||||||
#include "../Emu/Io/Null/NullPadHandler.h"
|
#include "../Emu/Io/Null/NullPadHandler.h"
|
||||||
#include "../Emu/System.h"
|
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QInputDialog>
|
||||||
input_config input_cfg;
|
#include <QMessageBox>
|
||||||
|
|
||||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
|
|
||||||
|
inline bool CreateConfigFile(const QString& dir, const QString& name)
|
||||||
|
{
|
||||||
|
QString input_dir = qstr(fs::get_config_dir()) + "/InputConfigs/";
|
||||||
|
if (!QDir().mkdir(input_dir) && !QDir().exists(input_dir))
|
||||||
|
{
|
||||||
|
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(input_dir));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!QDir().mkdir(dir) && !QDir().exists(dir))
|
||||||
|
{
|
||||||
|
LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(dir));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString filename = dir + name + ".yml";
|
||||||
|
QFile new_file(filename);
|
||||||
|
|
||||||
|
if (!new_file.open(QIODevice::WriteOnly))
|
||||||
|
{
|
||||||
|
LOG_ERROR(GENERAL, "Failed to create file %s", sstr(filename));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_file.close();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// taken from https://stackoverflow.com/a/30818424/8353754
|
// taken from https://stackoverflow.com/a/30818424/8353754
|
||||||
// because size policies won't work as expected (see similar bugs in Qt bugtracker)
|
// because size policies won't work as expected (see similar bugs in Qt bugtracker)
|
||||||
inline void resizeComboBoxView(QComboBox* combo)
|
inline void resizeComboBoxView(QComboBox* combo)
|
||||||
@ -55,8 +81,8 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||||||
QVBoxLayout *dialog_layout = new QVBoxLayout();
|
QVBoxLayout *dialog_layout = new QVBoxLayout();
|
||||||
QHBoxLayout *all_players = new QHBoxLayout();
|
QHBoxLayout *all_players = new QHBoxLayout();
|
||||||
|
|
||||||
input_cfg.from_default();
|
g_cfg_input.from_default();
|
||||||
input_cfg.load();
|
g_cfg_input.load();
|
||||||
|
|
||||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||||
{
|
{
|
||||||
@ -80,20 +106,27 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||||||
co_deviceID[i]->view()->setTextElideMode(Qt::ElideNone);
|
co_deviceID[i]->view()->setTextElideMode(Qt::ElideNone);
|
||||||
ppad_layout->addWidget(co_deviceID[i]);
|
ppad_layout->addWidget(co_deviceID[i]);
|
||||||
|
|
||||||
|
co_profile[i] = new QComboBox();
|
||||||
|
co_profile[i]->setEnabled(false);
|
||||||
|
co_profile[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||||
|
co_profile[i]->view()->setTextElideMode(Qt::ElideNone);
|
||||||
|
ppad_layout->addWidget(co_profile[i]);
|
||||||
|
|
||||||
QHBoxLayout *button_layout = new QHBoxLayout();
|
QHBoxLayout *button_layout = new QHBoxLayout();
|
||||||
bu_config[i] = new QPushButton(tr("Config"));
|
bu_new_profile[i] = new QPushButton(tr("Add Profile"));
|
||||||
|
bu_new_profile[i]->setEnabled(false);
|
||||||
|
bu_config[i] = new QPushButton(tr("Configure"));
|
||||||
bu_config[i]->setEnabled(false);
|
bu_config[i]->setEnabled(false);
|
||||||
bu_config[i]->setFixedSize(bu_config[i]->sizeHint());
|
button_layout->setContentsMargins(0,0,0,0);
|
||||||
button_layout->addSpacing(bu_config[i]->sizeHint().width()*0.50f);
|
|
||||||
button_layout->addWidget(bu_config[i]);
|
button_layout->addWidget(bu_config[i]);
|
||||||
button_layout->addSpacing(bu_config[i]->sizeHint().width()*0.50f);
|
button_layout->addWidget(bu_new_profile[i]);
|
||||||
ppad_layout->addLayout(button_layout);
|
ppad_layout->addLayout(button_layout);
|
||||||
|
|
||||||
grp_player->setLayout(ppad_layout);
|
grp_player->setLayout(ppad_layout);
|
||||||
grp_player->setFixedSize(grp_player->sizeHint());
|
grp_player->setFixedSize(grp_player->sizeHint());
|
||||||
|
|
||||||
// fill comboboxes after setting the groupbox's size to prevent stretch
|
// fill comboboxes after setting the groupbox's size to prevent stretch
|
||||||
std::vector<std::string> str_inputs = input_cfg.player_input[0].to_list();
|
std::vector<std::string> str_inputs = g_cfg_input.player[0]->handler.to_list();
|
||||||
for (int index = 0; index < str_inputs.size(); index++)
|
for (int index = 0; index < str_inputs.size(); index++)
|
||||||
{
|
{
|
||||||
co_inputtype[i]->addItem(qstr(str_inputs[index]));
|
co_inputtype[i]->addItem(qstr(str_inputs[index]));
|
||||||
@ -132,7 +165,7 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||||
{
|
{
|
||||||
// No extra loops are necessary because setCurrentText does it for us
|
// No extra loops are necessary because setCurrentText does it for us
|
||||||
co_inputtype[i]->setCurrentText(qstr(input_cfg.player_input[i].to_string()));
|
co_inputtype[i]->setCurrentText(qstr(g_cfg_input.player[i]->handler.to_string()));
|
||||||
// Device will be empty on some rare occasions, so fill them by force
|
// Device will be empty on some rare occasions, so fill them by force
|
||||||
ChangeInputType(i);
|
ChangeInputType(i);
|
||||||
}
|
}
|
||||||
@ -140,18 +173,67 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
|||||||
|
|
||||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||||
{
|
{
|
||||||
connect(co_inputtype[i], &QComboBox::currentTextChanged, [=] { ChangeInputType(i); });
|
connect(co_inputtype[i], &QComboBox::currentTextChanged, [=]
|
||||||
|
{
|
||||||
|
ChangeInputType(i);
|
||||||
|
});
|
||||||
connect(co_deviceID[i], &QComboBox::currentTextChanged, [=](const QString& dev)
|
connect(co_deviceID[i], &QComboBox::currentTextChanged, [=](const QString& dev)
|
||||||
{
|
{
|
||||||
std::string device = sstr(dev);
|
std::string device = sstr(dev);
|
||||||
if (!input_cfg.player_device[i]->from_string(device))
|
if (!g_cfg_input.player[i]->device.from_string(device))
|
||||||
{
|
{
|
||||||
//Something went wrong
|
//Something went wrong
|
||||||
LOG_ERROR(GENERAL, "Failed to convert device string: %s", device);
|
LOG_ERROR(GENERAL, "Failed to convert device string: %s", device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(bu_config[i], &QAbstractButton::clicked, [=] { ClickConfigButton(i); });
|
connect(co_profile[i], &QComboBox::currentTextChanged, [=](const QString& prof)
|
||||||
|
{
|
||||||
|
std::string profile = sstr(prof);
|
||||||
|
if (!g_cfg_input.player[i]->profile.from_string(profile))
|
||||||
|
{
|
||||||
|
//Something went wrong
|
||||||
|
LOG_ERROR(GENERAL, "Failed to convert profile string: %s", profile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(bu_config[i], &QAbstractButton::clicked, [=]
|
||||||
|
{
|
||||||
|
ClickConfigButton(i);
|
||||||
|
});
|
||||||
|
connect(bu_new_profile[i], &QAbstractButton::clicked, [=]
|
||||||
|
{
|
||||||
|
QInputDialog* dialog = new QInputDialog(this);
|
||||||
|
dialog->setWindowTitle(tr("Choose a unique name"));
|
||||||
|
dialog->setLabelText(tr("Profile Name: "));
|
||||||
|
dialog->setFixedSize(500, 100);
|
||||||
|
|
||||||
|
while (dialog->exec() != QDialog::Rejected)
|
||||||
|
{
|
||||||
|
QString friendlyName = dialog->textValue();
|
||||||
|
if (friendlyName == "")
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Error"), tr("Name cannot be empty"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (friendlyName.contains("."))
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Error"), tr("Must choose a name without '.'"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (co_profile[i]->findText(friendlyName) != -1)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Error"), tr("Please choose a non-existing name"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (CreateConfigFile(qstr(PadHandlerBase::get_config_dir(g_cfg_input.player[i]->handler)), friendlyName))
|
||||||
|
{
|
||||||
|
co_profile[i]->addItem(friendlyName);
|
||||||
|
co_profile[i]->setCurrentText(friendlyName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
connect(ok_button, &QPushButton::pressed, this, &gamepads_settings_dialog::SaveExit);
|
connect(ok_button, &QPushButton::pressed, this, &gamepads_settings_dialog::SaveExit);
|
||||||
connect(cancel_button, &QPushButton::pressed, this, &gamepads_settings_dialog::CancelExit);
|
connect(cancel_button, &QPushButton::pressed, this, &gamepads_settings_dialog::CancelExit);
|
||||||
@ -167,12 +249,13 @@ void gamepads_settings_dialog::SaveExit()
|
|||||||
{
|
{
|
||||||
if (co_deviceID[i]->currentData() == -1)
|
if (co_deviceID[i]->currentData() == -1)
|
||||||
{
|
{
|
||||||
input_cfg.player_input[i].from_default();
|
g_cfg_input.player[i]->handler.from_default();
|
||||||
input_cfg.player_device[i]->from_default();
|
g_cfg_input.player[i]->device.from_default();
|
||||||
|
g_cfg_input.player[i]->profile.from_default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input_cfg.save();
|
g_cfg_input.save();
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
@ -180,8 +263,8 @@ void gamepads_settings_dialog::SaveExit()
|
|||||||
void gamepads_settings_dialog::CancelExit()
|
void gamepads_settings_dialog::CancelExit()
|
||||||
{
|
{
|
||||||
//Reloads config from file or defaults
|
//Reloads config from file or defaults
|
||||||
input_cfg.from_default();
|
g_cfg_input.from_default();
|
||||||
input_cfg.load();
|
g_cfg_input.load();
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
@ -224,10 +307,11 @@ std::shared_ptr<PadHandlerBase> gamepads_settings_dialog::GetHandler(pad_handler
|
|||||||
void gamepads_settings_dialog::ChangeInputType(int player)
|
void gamepads_settings_dialog::ChangeInputType(int player)
|
||||||
{
|
{
|
||||||
std::string handler = sstr(co_inputtype[player]->currentText());
|
std::string handler = sstr(co_inputtype[player]->currentText());
|
||||||
std::string device = input_cfg.player_device[player]->to_string();
|
std::string device = g_cfg_input.player[player]->device.to_string();
|
||||||
|
std::string profile = g_cfg_input.player[player]->profile.to_string();
|
||||||
|
|
||||||
// Change this player's current handler
|
// Change this player's current handler
|
||||||
if (!input_cfg.player_input[player].from_string(handler))
|
if (!g_cfg_input.player[player]->handler.from_string(handler))
|
||||||
{
|
{
|
||||||
//Something went wrong
|
//Something went wrong
|
||||||
LOG_ERROR(GENERAL, "Failed to convert input string:%s", handler);
|
LOG_ERROR(GENERAL, "Failed to convert input string:%s", handler);
|
||||||
@ -235,7 +319,7 @@ void gamepads_settings_dialog::ChangeInputType(int player)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get this player's current handler and it's currently available devices
|
// Get this player's current handler and it's currently available devices
|
||||||
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(input_cfg.player_input[player]);
|
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(g_cfg_input.player[player]->handler);
|
||||||
std::vector<std::string> list_devices = cur_pad_handler->ListDevices();
|
std::vector<std::string> list_devices = cur_pad_handler->ListDevices();
|
||||||
|
|
||||||
// Refill the device combobox with currently available devices
|
// Refill the device combobox with currently available devices
|
||||||
@ -258,19 +342,60 @@ void gamepads_settings_dialog::ChangeInputType(int player)
|
|||||||
co_deviceID[player]->addItem(tr("No Device Detected"), -1);
|
co_deviceID[player]->addItem(tr("No Device Detected"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update view and enable configuration if possible
|
bool config_enabled = device_found && cur_pad_handler->has_config();
|
||||||
|
co_profile[player]->clear();
|
||||||
|
|
||||||
|
// update profile list if possible
|
||||||
|
if (config_enabled)
|
||||||
|
{
|
||||||
|
QString s_profile_dir = qstr(PadHandlerBase::get_config_dir(cur_pad_handler->m_type));
|
||||||
|
QStringList profiles = gui_settings::GetDirEntries(QDir(s_profile_dir), QStringList() << "*.yml");
|
||||||
|
|
||||||
|
if (profiles.isEmpty())
|
||||||
|
{
|
||||||
|
QString def_name = "Default Profile";
|
||||||
|
if (!CreateConfigFile(s_profile_dir, def_name))
|
||||||
|
{
|
||||||
|
config_enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
co_profile[player]->addItem(def_name);
|
||||||
|
co_profile[player]->setCurrentText(def_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto& prof : profiles)
|
||||||
|
{
|
||||||
|
co_profile[player]->addItem(prof);
|
||||||
|
}
|
||||||
|
co_profile[player]->setCurrentText(qstr(profile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config_enabled)
|
||||||
|
co_profile[player]->addItem(tr("No Profiles"));
|
||||||
|
|
||||||
|
// enable configuration and profile list if possible
|
||||||
|
bu_config[player]->setEnabled(config_enabled);
|
||||||
|
bu_new_profile[player]->setEnabled(config_enabled);
|
||||||
|
co_profile[player]->setEnabled(config_enabled);
|
||||||
|
|
||||||
|
// update view
|
||||||
resizeComboBoxView(co_deviceID[player]);
|
resizeComboBoxView(co_deviceID[player]);
|
||||||
bu_config[player]->setEnabled(device_found && cur_pad_handler->has_config());
|
resizeComboBoxView(co_profile[player]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gamepads_settings_dialog::ClickConfigButton(int player)
|
void gamepads_settings_dialog::ClickConfigButton(int player)
|
||||||
{
|
{
|
||||||
// Get this player's current handler and open its pad settings dialog
|
// Get this player's current handler and open its pad settings dialog
|
||||||
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(input_cfg.player_input[player]);
|
std::shared_ptr<PadHandlerBase> cur_pad_handler = GetHandler(g_cfg_input.player[player]->handler);
|
||||||
if (cur_pad_handler->has_config())
|
if (cur_pad_handler->has_config())
|
||||||
{
|
{
|
||||||
std::string device = sstr(co_deviceID[player]->currentText());
|
std::string device = sstr(co_deviceID[player]->currentText());
|
||||||
pad_settings_dialog dlg(device, cur_pad_handler);
|
std::string profile = sstr(co_profile[player]->currentText());
|
||||||
|
pad_settings_dialog dlg(device, profile, cur_pad_handler);
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,52 +12,6 @@
|
|||||||
#include "../../Utilities/File.h"
|
#include "../../Utilities/File.h"
|
||||||
#include "../Emu/Io/PadHandler.h"
|
#include "../Emu/Io/PadHandler.h"
|
||||||
|
|
||||||
struct input_config final : cfg::node
|
|
||||||
{
|
|
||||||
const std::string cfg_name = fs::get_config_dir() + "/config_input.yml";
|
|
||||||
|
|
||||||
cfg::_enum<pad_handler> player_input[7]{
|
|
||||||
{ this, "Player 1 Input", pad_handler::keyboard },
|
|
||||||
{ this, "Player 2 Input", pad_handler::null },
|
|
||||||
{ this, "Player 3 Input", pad_handler::null },
|
|
||||||
{ this, "Player 4 Input", pad_handler::null },
|
|
||||||
{ this, "Player 5 Input", pad_handler::null },
|
|
||||||
{ this, "Player 6 Input", pad_handler::null },
|
|
||||||
{ this, "Player 7 Input", pad_handler::null } };
|
|
||||||
|
|
||||||
cfg::string player1{ this, "Player 1 Device", "Keyboard" };
|
|
||||||
cfg::string player2{ this, "Player 2 Device", "Default Null Device" };
|
|
||||||
cfg::string player3{ this, "Player 3 Device", "Default Null Device" };
|
|
||||||
cfg::string player4{ this, "Player 4 Device", "Default Null Device" };
|
|
||||||
cfg::string player5{ this, "Player 5 Device", "Default Null Device" };
|
|
||||||
cfg::string player6{ this, "Player 6 Device", "Default Null Device" };
|
|
||||||
cfg::string player7{ this, "Player 7 Device", "Default Null Device" };
|
|
||||||
|
|
||||||
cfg::string *player_device[7]{ &player1, &player2, &player3, &player4, &player5, &player6, &player7 }; // Thanks gcc!
|
|
||||||
|
|
||||||
bool load()
|
|
||||||
{
|
|
||||||
if (fs::file cfg_file{ cfg_name, fs::read })
|
|
||||||
{
|
|
||||||
return from_string(cfg_file.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void save()
|
|
||||||
{
|
|
||||||
fs::file(cfg_name, fs::rewrite).write(to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool exist()
|
|
||||||
{
|
|
||||||
return fs::is_file(cfg_name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern input_config input_cfg;
|
|
||||||
|
|
||||||
class gamepads_settings_dialog : public QDialog
|
class gamepads_settings_dialog : public QDialog
|
||||||
{
|
{
|
||||||
const int MAX_PLAYERS = 7;
|
const int MAX_PLAYERS = 7;
|
||||||
@ -72,7 +26,9 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
QComboBox *co_inputtype[7];
|
QComboBox *co_inputtype[7];
|
||||||
QComboBox *co_deviceID[7];
|
QComboBox *co_deviceID[7];
|
||||||
|
QComboBox *co_profile[7];
|
||||||
QPushButton *bu_config[7];
|
QPushButton *bu_config[7];
|
||||||
|
QPushButton *bu_new_profile[7];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
gamepads_settings_dialog(QWidget* parent);
|
gamepads_settings_dialog(QWidget* parent);
|
||||||
|
@ -321,6 +321,17 @@ QStringList gui_settings::GetConfigEntries()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList gui_settings::GetDirEntries(const QDir& dir, const QStringList& nameFilters)
|
||||||
|
{
|
||||||
|
QFileInfoList entries = dir.entryInfoList(nameFilters, QDir::Files);
|
||||||
|
QStringList res;
|
||||||
|
for (const QFileInfo &entry : entries)
|
||||||
|
{
|
||||||
|
res.append(entry.baseName());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void gui_settings::BackupSettingsToTarget(const QString& friendlyName)
|
void gui_settings::BackupSettingsToTarget(const QString& friendlyName)
|
||||||
{
|
{
|
||||||
QSettings target(ComputeSettingsDir() + friendlyName + ".ini", QSettings::Format::IniFormat);
|
QSettings target(ComputeSettingsDir() + friendlyName + ".ini", QSettings::Format::IniFormat);
|
||||||
|
@ -231,6 +231,7 @@ public:
|
|||||||
bool GetGamelistColVisibility(int col);
|
bool GetGamelistColVisibility(int col);
|
||||||
QColor GetCustomColor(int col);
|
QColor GetCustomColor(int col);
|
||||||
QStringList GetConfigEntries();
|
QStringList GetConfigEntries();
|
||||||
|
static QStringList GetDirEntries(const QDir& dir, const QStringList& nameFilters);
|
||||||
QString GetCurrentStylesheetPath();
|
QString GetCurrentStylesheetPath();
|
||||||
QStringList GetStylesheetEntries();
|
QStringList GetStylesheetEntries();
|
||||||
QStringList GetGameListCategoryFilters();
|
QStringList GetGameListCategoryFilters();
|
||||||
|
@ -13,11 +13,9 @@
|
|||||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||||
constexpr auto qstr = QString::fromStdString;
|
constexpr auto qstr = QString::fromStdString;
|
||||||
|
|
||||||
pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_ptr<PadHandlerBase> handler, QWidget *parent)
|
pad_settings_dialog::pad_settings_dialog(const std::string& device, const std::string& profile, std::shared_ptr<PadHandlerBase> handler, QWidget *parent)
|
||||||
: QDialog(parent), ui(new Ui::pad_settings_dialog), m_handler_cfg(handler->GetConfig()), m_device_name(device), m_handler(handler)
|
: QDialog(parent), ui(new Ui::pad_settings_dialog), m_device_name(device), m_handler(handler), m_handler_type(handler->m_type)
|
||||||
{
|
{
|
||||||
m_handler_cfg->load();
|
|
||||||
|
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
@ -28,37 +26,47 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||||||
m_padButtons = new QButtonGroup(this);
|
m_padButtons = new QButtonGroup(this);
|
||||||
m_palette = ui->b_left->palette(); // save normal palette
|
m_palette = ui->b_left->palette(); // save normal palette
|
||||||
|
|
||||||
ui->chb_vibration_large->setChecked((bool)m_handler_cfg->enable_vibration_motor_large);
|
std::string cfg_name = PadHandlerBase::get_config_dir(m_handler_type) + profile + ".yml";
|
||||||
ui->chb_vibration_small->setChecked((bool)m_handler_cfg->enable_vibration_motor_small);
|
|
||||||
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg->switch_vibration_motors);
|
|
||||||
|
|
||||||
// Adjust to the different pad handlers
|
// Adjust to the different pad handlers
|
||||||
if (m_handler_cfg->cfg_type == "keyboard")
|
if (m_handler_type == pad_handler::keyboard)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Configure Keyboard"));
|
setWindowTitle(tr("Configure Keyboard"));
|
||||||
m_handler_type = handler_type::handler_type_keyboard;
|
|
||||||
ui->b_blacklist->setEnabled(false);
|
ui->b_blacklist->setEnabled(false);
|
||||||
|
((keyboard_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||||
}
|
}
|
||||||
else if (m_handler_cfg->cfg_type == "xinput")
|
else if (m_handler_type == pad_handler::ds4)
|
||||||
{
|
|
||||||
setWindowTitle(tr("Configure XInput"));
|
|
||||||
m_handler_type = handler_type::handler_type_xinput;
|
|
||||||
}
|
|
||||||
else if (m_handler_cfg->cfg_type == "ds4")
|
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Configure DS4"));
|
setWindowTitle(tr("Configure DS4"));
|
||||||
m_handler_type = handler_type::handler_type_ds4;
|
((ds4_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||||
}
|
}
|
||||||
else if (m_handler_cfg->cfg_type == "mmjoystick")
|
#ifdef _MSC_VER
|
||||||
|
else if (m_handler_type == pad_handler::xinput)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Configure XInput"));
|
||||||
|
((xinput_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
else if (m_handler_type == pad_handler::mm)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Configure MMJoystick"));
|
setWindowTitle(tr("Configure MMJoystick"));
|
||||||
m_handler_type = handler_type::handler_type_mmjoy;
|
((mm_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||||
}
|
}
|
||||||
else if (m_handler_cfg->cfg_type == "evdev")
|
#endif
|
||||||
|
#ifdef HAVE_LIBEVDEV
|
||||||
|
else if (m_handler_type == pad_handler::evdev)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("Configure evdev"));
|
setWindowTitle(tr("Configure evdev"));
|
||||||
m_handler_type = handler_type::handler_type_evdev;
|
((evdev_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_handler_cfg.load();
|
||||||
|
|
||||||
|
ui->chb_vibration_large->setChecked((bool)m_handler_cfg.enable_vibration_motor_large);
|
||||||
|
ui->chb_vibration_small->setChecked((bool)m_handler_cfg.enable_vibration_motor_small);
|
||||||
|
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg.switch_vibration_motors);
|
||||||
|
|
||||||
// Enable Button Remapping
|
// Enable Button Remapping
|
||||||
if (m_handler->has_config())
|
if (m_handler->has_config())
|
||||||
@ -85,7 +93,7 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||||||
|
|
||||||
if (val <= 0) return;
|
if (val <= 0) return;
|
||||||
|
|
||||||
LOG_NOTICE(HLE, "GetNextButtonPress: %s button %s pressed with value %d", m_handler_cfg->cfg_type, name, val);
|
LOG_NOTICE(HLE, "GetNextButtonPress: %s button %s pressed with value %d", m_handler_type, name, val);
|
||||||
if (m_button_id > button_ids::id_pad_begin && m_button_id < button_ids::id_pad_end)
|
if (m_button_id > button_ids::id_pad_begin && m_button_id < button_ids::id_pad_end)
|
||||||
{
|
{
|
||||||
m_cfg_entries[m_button_id].key = name;
|
m_cfg_entries[m_button_id].key = name;
|
||||||
@ -185,14 +193,14 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Enable Trigger Thresholds
|
// Enable Trigger Thresholds
|
||||||
initSlider(ui->slider_trigger_left, m_handler_cfg->ltriggerthreshold, 0, m_handler->trigger_max);
|
initSlider(ui->slider_trigger_left, m_handler_cfg.ltriggerthreshold, 0, m_handler->trigger_max);
|
||||||
initSlider(ui->slider_trigger_right, m_handler_cfg->rtriggerthreshold, 0, m_handler->trigger_max);
|
initSlider(ui->slider_trigger_right, m_handler_cfg.rtriggerthreshold, 0, m_handler->trigger_max);
|
||||||
ui->preview_trigger_left->setRange(0, m_handler->trigger_max);
|
ui->preview_trigger_left->setRange(0, m_handler->trigger_max);
|
||||||
ui->preview_trigger_right->setRange(0, m_handler->trigger_max);
|
ui->preview_trigger_right->setRange(0, m_handler->trigger_max);
|
||||||
|
|
||||||
// Enable Stick Deadzones
|
// Enable Stick Deadzones
|
||||||
initSlider(ui->slider_stick_left, m_handler_cfg->lstickdeadzone, 0, m_handler->thumb_max);
|
initSlider(ui->slider_stick_left, m_handler_cfg.lstickdeadzone, 0, m_handler->thumb_max);
|
||||||
initSlider(ui->slider_stick_right, m_handler_cfg->rstickdeadzone, 0, m_handler->thumb_max);
|
initSlider(ui->slider_stick_right, m_handler_cfg.rstickdeadzone, 0, m_handler->thumb_max);
|
||||||
|
|
||||||
RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->sizeHint().width(), lx, ly);
|
RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->sizeHint().width(), lx, ly);
|
||||||
connect(ui->slider_stick_left, &QSlider::valueChanged, [&](int value)
|
connect(ui->slider_stick_left, &QSlider::valueChanged, [&](int value)
|
||||||
@ -224,37 +232,37 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, std::shared_
|
|||||||
button->installEventFilter(this);
|
button->installEventFilter(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_lstick_left, ui->b_lstick_left, &m_handler_cfg->ls_left);
|
insertButton(button_ids::id_pad_lstick_left, ui->b_lstick_left, &m_handler_cfg.ls_left);
|
||||||
insertButton(button_ids::id_pad_lstick_down, ui->b_lstick_down, &m_handler_cfg->ls_down);
|
insertButton(button_ids::id_pad_lstick_down, ui->b_lstick_down, &m_handler_cfg.ls_down);
|
||||||
insertButton(button_ids::id_pad_lstick_right, ui->b_lstick_right, &m_handler_cfg->ls_right);
|
insertButton(button_ids::id_pad_lstick_right, ui->b_lstick_right, &m_handler_cfg.ls_right);
|
||||||
insertButton(button_ids::id_pad_lstick_up, ui->b_lstick_up, &m_handler_cfg->ls_up);
|
insertButton(button_ids::id_pad_lstick_up, ui->b_lstick_up, &m_handler_cfg.ls_up);
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_left, ui->b_left, &m_handler_cfg->left);
|
insertButton(button_ids::id_pad_left, ui->b_left, &m_handler_cfg.left);
|
||||||
insertButton(button_ids::id_pad_down, ui->b_down, &m_handler_cfg->down);
|
insertButton(button_ids::id_pad_down, ui->b_down, &m_handler_cfg.down);
|
||||||
insertButton(button_ids::id_pad_right, ui->b_right, &m_handler_cfg->right);
|
insertButton(button_ids::id_pad_right, ui->b_right, &m_handler_cfg.right);
|
||||||
insertButton(button_ids::id_pad_up, ui->b_up, &m_handler_cfg->up);
|
insertButton(button_ids::id_pad_up, ui->b_up, &m_handler_cfg.up);
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_l1, ui->b_shift_l1, &m_handler_cfg->l1);
|
insertButton(button_ids::id_pad_l1, ui->b_shift_l1, &m_handler_cfg.l1);
|
||||||
insertButton(button_ids::id_pad_l2, ui->b_shift_l2, &m_handler_cfg->l2);
|
insertButton(button_ids::id_pad_l2, ui->b_shift_l2, &m_handler_cfg.l2);
|
||||||
insertButton(button_ids::id_pad_l3, ui->b_shift_l3, &m_handler_cfg->l3);
|
insertButton(button_ids::id_pad_l3, ui->b_shift_l3, &m_handler_cfg.l3);
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_start, ui->b_start, &m_handler_cfg->start);
|
insertButton(button_ids::id_pad_start, ui->b_start, &m_handler_cfg.start);
|
||||||
insertButton(button_ids::id_pad_select, ui->b_select, &m_handler_cfg->select);
|
insertButton(button_ids::id_pad_select, ui->b_select, &m_handler_cfg.select);
|
||||||
insertButton(button_ids::id_pad_ps, ui->b_ps, &m_handler_cfg->ps);
|
insertButton(button_ids::id_pad_ps, ui->b_ps, &m_handler_cfg.ps);
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_r1, ui->b_shift_r1, &m_handler_cfg->r1);
|
insertButton(button_ids::id_pad_r1, ui->b_shift_r1, &m_handler_cfg.r1);
|
||||||
insertButton(button_ids::id_pad_r2, ui->b_shift_r2, &m_handler_cfg->r2);
|
insertButton(button_ids::id_pad_r2, ui->b_shift_r2, &m_handler_cfg.r2);
|
||||||
insertButton(button_ids::id_pad_r3, ui->b_shift_r3, &m_handler_cfg->r3);
|
insertButton(button_ids::id_pad_r3, ui->b_shift_r3, &m_handler_cfg.r3);
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_square, ui->b_square, &m_handler_cfg->square);
|
insertButton(button_ids::id_pad_square, ui->b_square, &m_handler_cfg.square);
|
||||||
insertButton(button_ids::id_pad_cross, ui->b_cross, &m_handler_cfg->cross);
|
insertButton(button_ids::id_pad_cross, ui->b_cross, &m_handler_cfg.cross);
|
||||||
insertButton(button_ids::id_pad_circle, ui->b_circle, &m_handler_cfg->circle);
|
insertButton(button_ids::id_pad_circle, ui->b_circle, &m_handler_cfg.circle);
|
||||||
insertButton(button_ids::id_pad_triangle, ui->b_triangle, &m_handler_cfg->triangle);
|
insertButton(button_ids::id_pad_triangle, ui->b_triangle, &m_handler_cfg.triangle);
|
||||||
|
|
||||||
insertButton(button_ids::id_pad_rstick_left, ui->b_rstick_left, &m_handler_cfg->rs_left);
|
insertButton(button_ids::id_pad_rstick_left, ui->b_rstick_left, &m_handler_cfg.rs_left);
|
||||||
insertButton(button_ids::id_pad_rstick_down, ui->b_rstick_down, &m_handler_cfg->rs_down);
|
insertButton(button_ids::id_pad_rstick_down, ui->b_rstick_down, &m_handler_cfg.rs_down);
|
||||||
insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg->rs_right);
|
insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg.rs_right);
|
||||||
insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg->rs_up);
|
insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg.rs_up);
|
||||||
|
|
||||||
m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters);
|
m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters);
|
||||||
m_padButtons->addButton(ui->b_blacklist, button_ids::id_blacklist);
|
m_padButtons->addButton(ui->b_blacklist, button_ids::id_blacklist);
|
||||||
@ -345,7 +353,7 @@ void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int dz, int w, int x, i
|
|||||||
|
|
||||||
void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
|
void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
|
||||||
{
|
{
|
||||||
if (m_handler_type != handler_type::handler_type_keyboard)
|
if (m_handler_type != pad_handler::keyboard)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -370,7 +378,7 @@ void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
|
|||||||
|
|
||||||
void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
|
void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
if (m_handler_type != handler_type::handler_type_keyboard)
|
if (m_handler_type != pad_handler::keyboard)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -407,17 +415,17 @@ void pad_settings_dialog::UpdateLabel(bool is_reset)
|
|||||||
{
|
{
|
||||||
if (m_handler->has_rumble())
|
if (m_handler->has_rumble())
|
||||||
{
|
{
|
||||||
ui->chb_vibration_large->setChecked((bool)m_handler_cfg->enable_vibration_motor_large);
|
ui->chb_vibration_large->setChecked((bool)m_handler_cfg.enable_vibration_motor_large);
|
||||||
ui->chb_vibration_small->setChecked((bool)m_handler_cfg->enable_vibration_motor_small);
|
ui->chb_vibration_small->setChecked((bool)m_handler_cfg.enable_vibration_motor_small);
|
||||||
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg->switch_vibration_motors);
|
ui->chb_vibration_switch->setChecked((bool)m_handler_cfg.switch_vibration_motors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_handler->has_deadzones())
|
if (m_handler->has_deadzones())
|
||||||
{
|
{
|
||||||
ui->slider_trigger_left->setValue(m_handler_cfg->ltriggerthreshold);
|
ui->slider_trigger_left->setValue(m_handler_cfg.ltriggerthreshold);
|
||||||
ui->slider_trigger_right->setValue(m_handler_cfg->rtriggerthreshold);
|
ui->slider_trigger_right->setValue(m_handler_cfg.rtriggerthreshold);
|
||||||
ui->slider_stick_left->setValue(m_handler_cfg->lstickdeadzone);
|
ui->slider_stick_left->setValue(m_handler_cfg.lstickdeadzone);
|
||||||
ui->slider_stick_right->setValue(m_handler_cfg->rstickdeadzone);
|
ui->slider_stick_right->setValue(m_handler_cfg.rstickdeadzone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,20 +458,20 @@ void pad_settings_dialog::SaveConfig()
|
|||||||
|
|
||||||
if (m_handler->has_rumble())
|
if (m_handler->has_rumble())
|
||||||
{
|
{
|
||||||
m_handler_cfg->enable_vibration_motor_large.set(ui->chb_vibration_large->isChecked());
|
m_handler_cfg.enable_vibration_motor_large.set(ui->chb_vibration_large->isChecked());
|
||||||
m_handler_cfg->enable_vibration_motor_small.set(ui->chb_vibration_small->isChecked());
|
m_handler_cfg.enable_vibration_motor_small.set(ui->chb_vibration_small->isChecked());
|
||||||
m_handler_cfg->switch_vibration_motors.set(ui->chb_vibration_switch->isChecked());
|
m_handler_cfg.switch_vibration_motors.set(ui->chb_vibration_switch->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_handler->has_deadzones())
|
if (m_handler->has_deadzones())
|
||||||
{
|
{
|
||||||
m_handler_cfg->ltriggerthreshold.set(ui->slider_trigger_left->value());
|
m_handler_cfg.ltriggerthreshold.set(ui->slider_trigger_left->value());
|
||||||
m_handler_cfg->rtriggerthreshold.set(ui->slider_trigger_right->value());
|
m_handler_cfg.rtriggerthreshold.set(ui->slider_trigger_right->value());
|
||||||
m_handler_cfg->lstickdeadzone.set(ui->slider_stick_left->value());
|
m_handler_cfg.lstickdeadzone.set(ui->slider_stick_left->value());
|
||||||
m_handler_cfg->rstickdeadzone.set(ui->slider_stick_right->value());
|
m_handler_cfg.rstickdeadzone.set(ui->slider_stick_right->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_handler_cfg->save();
|
m_handler_cfg.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pad_settings_dialog::OnPadButtonClicked(int id)
|
void pad_settings_dialog::OnPadButtonClicked(int id)
|
||||||
@ -476,7 +484,7 @@ void pad_settings_dialog::OnPadButtonClicked(int id)
|
|||||||
return;
|
return;
|
||||||
case button_ids::id_reset_parameters:
|
case button_ids::id_reset_parameters:
|
||||||
ReactivateButtons();
|
ReactivateButtons();
|
||||||
m_handler_cfg->from_default();
|
m_handler_cfg.from_default();
|
||||||
UpdateLabel(true);
|
UpdateLabel(true);
|
||||||
return;
|
return;
|
||||||
case button_ids::id_blacklist:
|
case button_ids::id_blacklist:
|
||||||
|
@ -17,6 +17,12 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "xinput_pad_handler.h"
|
#include "xinput_pad_handler.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include "mm_joystick_handler.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIBEVDEV
|
||||||
|
#include "evdev_joystick_handler.h"
|
||||||
|
#endif
|
||||||
#include "ds4_pad_handler.h"
|
#include "ds4_pad_handler.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
@ -72,15 +78,6 @@ class pad_settings_dialog : public QDialog
|
|||||||
id_cancel
|
id_cancel
|
||||||
};
|
};
|
||||||
|
|
||||||
enum handler_type
|
|
||||||
{
|
|
||||||
handler_type_keyboard,
|
|
||||||
handler_type_xinput,
|
|
||||||
handler_type_ds4,
|
|
||||||
handler_type_mmjoy,
|
|
||||||
handler_type_evdev
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pad_button
|
struct pad_button
|
||||||
{
|
{
|
||||||
cfg::string* cfg_name;
|
cfg::string* cfg_name;
|
||||||
@ -109,9 +106,9 @@ private:
|
|||||||
QPalette m_palette;
|
QPalette m_palette;
|
||||||
|
|
||||||
// Pad Handlers
|
// Pad Handlers
|
||||||
|
pad_handler m_handler_type;
|
||||||
std::shared_ptr<PadHandlerBase> m_handler;
|
std::shared_ptr<PadHandlerBase> m_handler;
|
||||||
handler_type m_handler_type;
|
pad_config m_handler_cfg;
|
||||||
pad_config* m_handler_cfg;
|
|
||||||
std::string m_device_name;
|
std::string m_device_name;
|
||||||
|
|
||||||
// Remap Timer
|
// Remap Timer
|
||||||
@ -129,7 +126,7 @@ private:
|
|||||||
void RepaintPreviewLabel(QLabel* l, int dz, int w, int x, int y);
|
void RepaintPreviewLabel(QLabel* l, int dz, int w, int x, int y);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit pad_settings_dialog(const std::string& device, std::shared_ptr<PadHandlerBase> handler, QWidget *parent = nullptr);
|
explicit pad_settings_dialog(const std::string& device, const std::string& profile, std::shared_ptr<PadHandlerBase> handler, QWidget *parent = nullptr);
|
||||||
~pad_settings_dialog();
|
~pad_settings_dialog();
|
||||||
|
|
||||||
/** Handle keyboard handler input */
|
/** Handle keyboard handler input */
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include "xinput_pad_handler.h"
|
#include "xinput_pad_handler.h"
|
||||||
#include "rpcs3qt/pad_settings_dialog.h"
|
|
||||||
|
|
||||||
xinput_pad_handler::xinput_pad_handler() :
|
xinput_pad_handler::xinput_pad_handler() : PadHandlerBase(pad_handler::xinput)
|
||||||
library(nullptr), xinputGetState(nullptr), xinputEnable(nullptr),
|
|
||||||
xinputSetState(nullptr), xinputGetBatteryInformation(nullptr), is_init(false)
|
|
||||||
{
|
{
|
||||||
|
init_configs();
|
||||||
|
|
||||||
// Define border values
|
// Define border values
|
||||||
thumb_min = -32768;
|
thumb_min = -32768;
|
||||||
thumb_max = 32767;
|
thumb_max = 32767;
|
||||||
@ -15,47 +14,6 @@ xinput_pad_handler::xinput_pad_handler() :
|
|||||||
vibration_min = 0;
|
vibration_min = 0;
|
||||||
vibration_max = 65535;
|
vibration_max = 65535;
|
||||||
|
|
||||||
// Set this handler's type and save location
|
|
||||||
m_pad_config.cfg_type = "xinput";
|
|
||||||
m_pad_config.cfg_name = fs::get_config_dir() + "/config_xinput.yml";
|
|
||||||
|
|
||||||
// Set default button mapping
|
|
||||||
m_pad_config.ls_left.def = button_list.at(XInputKeyCodes::LSXNeg);
|
|
||||||
m_pad_config.ls_down.def = button_list.at(XInputKeyCodes::LSYNeg);
|
|
||||||
m_pad_config.ls_right.def = button_list.at(XInputKeyCodes::LSXPos);
|
|
||||||
m_pad_config.ls_up.def = button_list.at(XInputKeyCodes::LSYPos);
|
|
||||||
m_pad_config.rs_left.def = button_list.at(XInputKeyCodes::RSXNeg);
|
|
||||||
m_pad_config.rs_down.def = button_list.at(XInputKeyCodes::RSYNeg);
|
|
||||||
m_pad_config.rs_right.def = button_list.at(XInputKeyCodes::RSXPos);
|
|
||||||
m_pad_config.rs_up.def = button_list.at(XInputKeyCodes::RSYPos);
|
|
||||||
m_pad_config.start.def = button_list.at(XInputKeyCodes::Start);
|
|
||||||
m_pad_config.select.def = button_list.at(XInputKeyCodes::Back);
|
|
||||||
m_pad_config.ps.def = button_list.at(XInputKeyCodes::Guide);
|
|
||||||
m_pad_config.square.def = button_list.at(XInputKeyCodes::X);
|
|
||||||
m_pad_config.cross.def = button_list.at(XInputKeyCodes::A);
|
|
||||||
m_pad_config.circle.def = button_list.at(XInputKeyCodes::B);
|
|
||||||
m_pad_config.triangle.def = button_list.at(XInputKeyCodes::Y);
|
|
||||||
m_pad_config.left.def = button_list.at(XInputKeyCodes::Left);
|
|
||||||
m_pad_config.down.def = button_list.at(XInputKeyCodes::Down);
|
|
||||||
m_pad_config.right.def = button_list.at(XInputKeyCodes::Right);
|
|
||||||
m_pad_config.up.def = button_list.at(XInputKeyCodes::Up);
|
|
||||||
m_pad_config.r1.def = button_list.at(XInputKeyCodes::RB);
|
|
||||||
m_pad_config.r2.def = button_list.at(XInputKeyCodes::RT);
|
|
||||||
m_pad_config.r3.def = button_list.at(XInputKeyCodes::RS);
|
|
||||||
m_pad_config.l1.def = button_list.at(XInputKeyCodes::LB);
|
|
||||||
m_pad_config.l2.def = button_list.at(XInputKeyCodes::LT);
|
|
||||||
m_pad_config.l3.def = button_list.at(XInputKeyCodes::LS);
|
|
||||||
|
|
||||||
// Set default misc variables
|
|
||||||
m_pad_config.lstickdeadzone.def = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE; // between 0 and 32767
|
|
||||||
m_pad_config.rstickdeadzone.def = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE; // between 0 and 32767
|
|
||||||
m_pad_config.ltriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
|
||||||
m_pad_config.rtriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
|
||||||
m_pad_config.padsquircling.def = 8000;
|
|
||||||
|
|
||||||
// apply defaults
|
|
||||||
m_pad_config.from_default();
|
|
||||||
|
|
||||||
// set capabilities
|
// set capabilities
|
||||||
b_has_config = true;
|
b_has_config = true;
|
||||||
b_has_rumble = true;
|
b_has_rumble = true;
|
||||||
@ -70,6 +28,49 @@ xinput_pad_handler::~xinput_pad_handler()
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xinput_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||||
|
{
|
||||||
|
// Set this profile's save location
|
||||||
|
cfg->cfg_name = name;
|
||||||
|
|
||||||
|
// Set default button mapping
|
||||||
|
cfg->ls_left.def = button_list.at(XInputKeyCodes::LSXNeg);
|
||||||
|
cfg->ls_down.def = button_list.at(XInputKeyCodes::LSYNeg);
|
||||||
|
cfg->ls_right.def = button_list.at(XInputKeyCodes::LSXPos);
|
||||||
|
cfg->ls_up.def = button_list.at(XInputKeyCodes::LSYPos);
|
||||||
|
cfg->rs_left.def = button_list.at(XInputKeyCodes::RSXNeg);
|
||||||
|
cfg->rs_down.def = button_list.at(XInputKeyCodes::RSYNeg);
|
||||||
|
cfg->rs_right.def = button_list.at(XInputKeyCodes::RSXPos);
|
||||||
|
cfg->rs_up.def = button_list.at(XInputKeyCodes::RSYPos);
|
||||||
|
cfg->start.def = button_list.at(XInputKeyCodes::Start);
|
||||||
|
cfg->select.def = button_list.at(XInputKeyCodes::Back);
|
||||||
|
cfg->ps.def = button_list.at(XInputKeyCodes::Guide);
|
||||||
|
cfg->square.def = button_list.at(XInputKeyCodes::X);
|
||||||
|
cfg->cross.def = button_list.at(XInputKeyCodes::A);
|
||||||
|
cfg->circle.def = button_list.at(XInputKeyCodes::B);
|
||||||
|
cfg->triangle.def = button_list.at(XInputKeyCodes::Y);
|
||||||
|
cfg->left.def = button_list.at(XInputKeyCodes::Left);
|
||||||
|
cfg->down.def = button_list.at(XInputKeyCodes::Down);
|
||||||
|
cfg->right.def = button_list.at(XInputKeyCodes::Right);
|
||||||
|
cfg->up.def = button_list.at(XInputKeyCodes::Up);
|
||||||
|
cfg->r1.def = button_list.at(XInputKeyCodes::RB);
|
||||||
|
cfg->r2.def = button_list.at(XInputKeyCodes::RT);
|
||||||
|
cfg->r3.def = button_list.at(XInputKeyCodes::RS);
|
||||||
|
cfg->l1.def = button_list.at(XInputKeyCodes::LB);
|
||||||
|
cfg->l2.def = button_list.at(XInputKeyCodes::LT);
|
||||||
|
cfg->l3.def = button_list.at(XInputKeyCodes::LS);
|
||||||
|
|
||||||
|
// Set default misc variables
|
||||||
|
cfg->lstickdeadzone.def = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE; // between 0 and 32767
|
||||||
|
cfg->rstickdeadzone.def = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE; // between 0 and 32767
|
||||||
|
cfg->ltriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
||||||
|
cfg->rtriggerthreshold.def = XINPUT_GAMEPAD_TRIGGER_THRESHOLD; // between 0 and 255
|
||||||
|
cfg->padsquircling.def = 8000;
|
||||||
|
|
||||||
|
// apply defaults
|
||||||
|
cfg->from_default();
|
||||||
|
}
|
||||||
|
|
||||||
void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist, std::vector<std::string> buttons)
|
void xinput_pad_handler::GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist, std::vector<std::string> buttons)
|
||||||
{
|
{
|
||||||
if (get_blacklist)
|
if (get_blacklist)
|
||||||
@ -152,29 +153,30 @@ void xinput_pad_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& v
|
|||||||
{
|
{
|
||||||
// Update the pad button values based on their type and thresholds.
|
// Update the pad button values based on their type and thresholds.
|
||||||
// With this you can use axis or triggers as buttons or vice versa
|
// With this you can use axis or triggers as buttons or vice versa
|
||||||
|
auto p_profile = m_dev->config;
|
||||||
switch (keyCode)
|
switch (keyCode)
|
||||||
{
|
{
|
||||||
case XInputKeyCodes::LT:
|
case XInputKeyCodes::LT:
|
||||||
pressed = val > m_pad_config.ltriggerthreshold;
|
pressed = val > p_profile->ltriggerthreshold;
|
||||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.ltriggerthreshold) : 0;
|
val = pressed ? NormalizeTriggerInput(val, p_profile->ltriggerthreshold) : 0;
|
||||||
break;
|
break;
|
||||||
case XInputKeyCodes::RT:
|
case XInputKeyCodes::RT:
|
||||||
pressed = val > m_pad_config.rtriggerthreshold;
|
pressed = val > p_profile->rtriggerthreshold;
|
||||||
val = pressed ? NormalizeTriggerInput(val, m_pad_config.rtriggerthreshold) : 0;
|
val = pressed ? NormalizeTriggerInput(val, p_profile->rtriggerthreshold) : 0;
|
||||||
break;
|
break;
|
||||||
case XInputKeyCodes::LSXNeg:
|
case XInputKeyCodes::LSXNeg:
|
||||||
case XInputKeyCodes::LSXPos:
|
case XInputKeyCodes::LSXPos:
|
||||||
case XInputKeyCodes::LSYPos:
|
case XInputKeyCodes::LSYPos:
|
||||||
case XInputKeyCodes::LSYNeg:
|
case XInputKeyCodes::LSYNeg:
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.lstickdeadzone);
|
pressed = val > (ignore_threshold ? 0 : p_profile->lstickdeadzone);
|
||||||
val = pressed ? NormalizeStickInput(val, m_pad_config.lstickdeadzone, ignore_threshold) : 0;
|
val = pressed ? NormalizeStickInput(val, p_profile->lstickdeadzone, ignore_threshold) : 0;
|
||||||
break;
|
break;
|
||||||
case XInputKeyCodes::RSXNeg:
|
case XInputKeyCodes::RSXNeg:
|
||||||
case XInputKeyCodes::RSXPos:
|
case XInputKeyCodes::RSXPos:
|
||||||
case XInputKeyCodes::RSYPos:
|
case XInputKeyCodes::RSYPos:
|
||||||
case XInputKeyCodes::RSYNeg:
|
case XInputKeyCodes::RSYNeg:
|
||||||
pressed = val > (ignore_threshold ? 0 : m_pad_config.rstickdeadzone);
|
pressed = val > (ignore_threshold ? 0 : p_profile->rstickdeadzone);
|
||||||
val = pressed ? NormalizeStickInput(val, m_pad_config.rstickdeadzone, ignore_threshold) : 0;
|
val = pressed ? NormalizeStickInput(val, p_profile->rstickdeadzone, ignore_threshold) : 0;
|
||||||
break;
|
break;
|
||||||
default: // normal button (should in theory also support sensitive buttons)
|
default: // normal button (should in theory also support sensitive buttons)
|
||||||
pressed = val > 0;
|
pressed = val > 0;
|
||||||
@ -293,10 +295,6 @@ bool xinput_pad_handler::Init()
|
|||||||
if (!is_init)
|
if (!is_init)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pad_config.load();
|
|
||||||
if (!m_pad_config.exist())
|
|
||||||
m_pad_config.save();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,8 +314,9 @@ void xinput_pad_handler::ThreadProc()
|
|||||||
{
|
{
|
||||||
for (auto &bind : bindings)
|
for (auto &bind : bindings)
|
||||||
{
|
{
|
||||||
auto device = bind.first;
|
m_dev = bind.first;
|
||||||
auto padnum = device->deviceNumber;
|
auto padnum = m_dev->deviceNumber;
|
||||||
|
auto profile = m_dev->config;
|
||||||
auto pad = bind.second;
|
auto pad = bind.second;
|
||||||
|
|
||||||
result = (*xinputGetState)(padnum, &state);
|
result = (*xinputGetState)(padnum, &state);
|
||||||
@ -333,7 +332,7 @@ void xinput_pad_handler::ThreadProc()
|
|||||||
last_connection_status[padnum] = false;
|
last_connection_status[padnum] = false;
|
||||||
connected--;
|
connected--;
|
||||||
}
|
}
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
case ERROR_SUCCESS:
|
case ERROR_SUCCESS:
|
||||||
if (last_connection_status[padnum] == false)
|
if (last_connection_status[padnum] == false)
|
||||||
@ -364,7 +363,7 @@ void xinput_pad_handler::ThreadProc()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// used to get the absolute value of an axis
|
// used to get the absolute value of an axis
|
||||||
float stick_val[4];
|
s32 stick_val[4];
|
||||||
|
|
||||||
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
// Translate any corresponding keycodes to our two sticks. (ignoring thresholds for now)
|
||||||
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
for (int i = 0; i < static_cast<int>(pad->m_sticks.size()); i++)
|
||||||
@ -388,13 +387,13 @@ void xinput_pad_handler::ThreadProc()
|
|||||||
u16 lx, ly, rx, ry;
|
u16 lx, ly, rx, ry;
|
||||||
|
|
||||||
// Normalize our two stick's axis based on the thresholds
|
// Normalize our two stick's axis based on the thresholds
|
||||||
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], m_pad_config.lstickdeadzone);
|
std::tie(lx, ly) = NormalizeStickDeadzone(stick_val[0], stick_val[1], profile->lstickdeadzone);
|
||||||
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], m_pad_config.rstickdeadzone);
|
std::tie(rx, ry) = NormalizeStickDeadzone(stick_val[2], stick_val[3], profile->rstickdeadzone);
|
||||||
|
|
||||||
if (m_pad_config.padsquircling != 0)
|
if (profile->padsquircling != 0)
|
||||||
{
|
{
|
||||||
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, m_pad_config.padsquircling);
|
std::tie(lx, ly) = ConvertToSquirclePoint(lx, ly, profile->padsquircling);
|
||||||
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, m_pad_config.padsquircling);
|
std::tie(rx, ry) = ConvertToSquirclePoint(rx, ry, profile->padsquircling);
|
||||||
}
|
}
|
||||||
|
|
||||||
pad->m_sticks[0].m_value = lx;
|
pad->m_sticks[0].m_value = lx;
|
||||||
@ -410,19 +409,19 @@ void xinput_pad_handler::ThreadProc()
|
|||||||
|
|
||||||
// The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor.
|
// The left motor is the low-frequency rumble motor. The right motor is the high-frequency rumble motor.
|
||||||
// The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535.
|
// The two motors are not the same, and they create different vibration effects. Values range between 0 to 65535.
|
||||||
int idx_l = m_pad_config.switch_vibration_motors ? 1 : 0;
|
int idx_l = profile->switch_vibration_motors ? 1 : 0;
|
||||||
int idx_s = m_pad_config.switch_vibration_motors ? 0 : 1;
|
int idx_s = profile->switch_vibration_motors ? 0 : 1;
|
||||||
|
|
||||||
int speed_large = m_pad_config.enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
int speed_large = profile->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value * 257 : vibration_min;
|
||||||
int speed_small = m_pad_config.enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
int speed_small = profile->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value * 257 : vibration_min;
|
||||||
|
|
||||||
device->newVibrateData = device->newVibrateData || device->largeVibrate != speed_large || device->smallVibrate != speed_small;
|
m_dev->newVibrateData = m_dev->newVibrateData || m_dev->largeVibrate != speed_large || m_dev->smallVibrate != speed_small;
|
||||||
|
|
||||||
device->largeVibrate = speed_large;
|
m_dev->largeVibrate = speed_large;
|
||||||
device->smallVibrate = speed_small;
|
m_dev->smallVibrate = speed_small;
|
||||||
|
|
||||||
// XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable.
|
// XBox One Controller can't handle faster vibration updates than ~10ms. Elite is even worse. So I'll use 20ms to be on the safe side. No lag was noticable.
|
||||||
if (device->newVibrateData && (clock() - device->last_vibration > 20))
|
if (m_dev->newVibrateData && (clock() - m_dev->last_vibration > 20))
|
||||||
{
|
{
|
||||||
XINPUT_VIBRATION vibrate;
|
XINPUT_VIBRATION vibrate;
|
||||||
vibrate.wLeftMotorSpeed = speed_large;
|
vibrate.wLeftMotorSpeed = speed_large;
|
||||||
@ -430,8 +429,8 @@ void xinput_pad_handler::ThreadProc()
|
|||||||
|
|
||||||
if ((*xinputSetState)(padnum, &vibrate) == ERROR_SUCCESS)
|
if ((*xinputSetState)(padnum, &vibrate) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
device->newVibrateData = false;
|
m_dev->newVibrateData = false;
|
||||||
device->last_vibration = clock();
|
m_dev->last_vibration = clock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,10 +463,15 @@ bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::st
|
|||||||
if (device_number < 0)
|
if (device_number < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::shared_ptr<XInputDevice> device_id = std::make_shared<XInputDevice>();
|
std::shared_ptr<XInputDevice> x_device = std::make_shared<XInputDevice>();
|
||||||
device_id->deviceNumber = static_cast<u32>(device_number);
|
x_device->deviceNumber = static_cast<u32>(device_number);
|
||||||
|
|
||||||
m_pad_config.load();
|
int index = static_cast<int>(bindings.size());
|
||||||
|
m_pad_configs[index].load();
|
||||||
|
x_device->config = &m_pad_configs[index];
|
||||||
|
pad_config* p_profile = x_device->config;
|
||||||
|
if (p_profile == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
pad->Init
|
pad->Init
|
||||||
(
|
(
|
||||||
@ -477,29 +481,29 @@ bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::st
|
|||||||
CELL_PAD_DEV_TYPE_STANDARD
|
CELL_PAD_DEV_TYPE_STANDARD
|
||||||
);
|
);
|
||||||
|
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.up), CELL_PAD_CTRL_UP);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->up), CELL_PAD_CTRL_UP);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.down), CELL_PAD_CTRL_DOWN);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->down), CELL_PAD_CTRL_DOWN);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.left), CELL_PAD_CTRL_LEFT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->left), CELL_PAD_CTRL_LEFT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.right), CELL_PAD_CTRL_RIGHT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->right), CELL_PAD_CTRL_RIGHT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.start), CELL_PAD_CTRL_START);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->start), CELL_PAD_CTRL_START);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.select), CELL_PAD_CTRL_SELECT);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->select), CELL_PAD_CTRL_SELECT);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.l3), CELL_PAD_CTRL_L3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->l3), CELL_PAD_CTRL_L3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, m_pad_config.r3), CELL_PAD_CTRL_R3);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, FindKeyCode(button_list, p_profile->r3), CELL_PAD_CTRL_R3);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l1), CELL_PAD_CTRL_L1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l1), CELL_PAD_CTRL_L1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r1), CELL_PAD_CTRL_R1);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r1), CELL_PAD_CTRL_R1);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->ps), 0x100/*CELL_PAD_CTRL_PS*/);// TODO: PS button support
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.cross), CELL_PAD_CTRL_CROSS);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->cross), CELL_PAD_CTRL_CROSS);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.circle), CELL_PAD_CTRL_CIRCLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->circle), CELL_PAD_CTRL_CIRCLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.square), CELL_PAD_CTRL_SQUARE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->square), CELL_PAD_CTRL_SQUARE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.triangle), CELL_PAD_CTRL_TRIANGLE);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.l2), CELL_PAD_CTRL_L2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->l2), CELL_PAD_CTRL_L2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, m_pad_config.r2), CELL_PAD_CTRL_R2);
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, FindKeyCode(button_list, p_profile->r2), CELL_PAD_CTRL_R2);
|
||||||
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, 0, 0x0); // Reserved
|
||||||
|
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, m_pad_config.ls_left), FindKeyCode(button_list, m_pad_config.ls_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X, FindKeyCode(button_list, p_profile->ls_left), FindKeyCode(button_list, p_profile->ls_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, m_pad_config.ls_down), FindKeyCode(button_list, m_pad_config.ls_up));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y, FindKeyCode(button_list, p_profile->ls_down), FindKeyCode(button_list, p_profile->ls_up));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, m_pad_config.rs_left), FindKeyCode(button_list, m_pad_config.rs_right));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X, FindKeyCode(button_list, p_profile->rs_left), FindKeyCode(button_list, p_profile->rs_right));
|
||||||
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, m_pad_config.rs_down), FindKeyCode(button_list, m_pad_config.rs_up));
|
pad->m_sticks.emplace_back(CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y, FindKeyCode(button_list, p_profile->rs_down), FindKeyCode(button_list, p_profile->rs_up));
|
||||||
|
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_X, 512);
|
||||||
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
pad->m_sensors.emplace_back(CELL_PAD_BTN_OFFSET_SENSOR_Y, 399);
|
||||||
@ -509,7 +513,7 @@ bool xinput_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::st
|
|||||||
pad->m_vibrateMotors.emplace_back(true, 0);
|
pad->m_vibrateMotors.emplace_back(true, 0);
|
||||||
pad->m_vibrateMotors.emplace_back(false, 0);
|
pad->m_vibrateMotors.emplace_back(false, 0);
|
||||||
|
|
||||||
bindings.emplace_back(device_id, pad);
|
bindings.emplace_back(x_device, pad);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "Utilities/Config.h"
|
#include "Utilities/Config.h"
|
||||||
#include "Emu/Io/PadHandler.h"
|
#include "Emu/Io/PadHandler.h"
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
@ -95,6 +94,7 @@ class xinput_pad_handler final : public PadHandlerBase
|
|||||||
u8 largeVibrate{ 0 };
|
u8 largeVibrate{ 0 };
|
||||||
u8 smallVibrate{ 0 };
|
u8 smallVibrate{ 0 };
|
||||||
clock_t last_vibration{ 0 };
|
clock_t last_vibration{ 0 };
|
||||||
|
pad_config* config{ nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -109,6 +109,7 @@ public:
|
|||||||
void ThreadProc() override;
|
void ThreadProc() override;
|
||||||
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
void GetNextButtonPress(const std::string& padId, const std::function<void(u16, std::string, int[])>& callback, bool get_blacklist = false, std::vector<std::string> buttons = {}) override;
|
||||||
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
|
void TestVibration(const std::string& padId, u32 largeMotor, u32 smallMotor) override;
|
||||||
|
void init_config(pad_config* cfg, const std::string& name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef void (WINAPI * PFN_XINPUTENABLE)(BOOL);
|
typedef void (WINAPI * PFN_XINPUTENABLE)(BOOL);
|
||||||
@ -121,15 +122,16 @@ private:
|
|||||||
std::array<u16, XInputKeyCodes::KeyCodeCount> GetButtonValues(const XINPUT_STATE& state);
|
std::array<u16, XInputKeyCodes::KeyCodeCount> GetButtonValues(const XINPUT_STATE& state);
|
||||||
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
|
void TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold = false) override;
|
||||||
|
|
||||||
bool is_init;
|
bool is_init{ false };
|
||||||
HMODULE library;
|
HMODULE library{ nullptr };
|
||||||
PFN_XINPUTGETSTATE xinputGetState;
|
PFN_XINPUTGETSTATE xinputGetState{ nullptr };
|
||||||
PFN_XINPUTSETSTATE xinputSetState;
|
PFN_XINPUTSETSTATE xinputSetState{ nullptr };
|
||||||
PFN_XINPUTENABLE xinputEnable;
|
PFN_XINPUTENABLE xinputEnable{ nullptr };
|
||||||
PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation;
|
PFN_XINPUTGETBATTERYINFORMATION xinputGetBatteryInformation{ nullptr };
|
||||||
|
|
||||||
std::vector<u32> blacklist;
|
std::vector<u32> blacklist;
|
||||||
std::vector<std::pair<std::shared_ptr<XInputDevice>, std::shared_ptr<Pad>>> bindings;
|
std::vector<std::pair<std::shared_ptr<XInputDevice>, std::shared_ptr<Pad>>> bindings;
|
||||||
|
std::shared_ptr<XInputDevice> m_dev;
|
||||||
|
|
||||||
// holds internal controller state change
|
// holds internal controller state change
|
||||||
XINPUT_STATE state;
|
XINPUT_STATE state;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user