Cemu/src/input/api/Wiimote/NativeWiimoteController.cpp
SSimco 9f02733a0d
Use unordered_map for keydown to allow codes above 255 (#248)
- Adds internal support for 32bit key codes, required for proper keyboard input on Linux
- Use gdk_keyval_name to get key name on Linux
2022-09-19 03:07:26 +02:00

237 lines
5.9 KiB
C++

#include "input/api/Wiimote/NativeWiimoteController.h"
#include "input/api/Wiimote/WiimoteControllerProvider.h"
#include <pugixml.hpp>
NativeWiimoteController::NativeWiimoteController(size_t index)
: base_type(fmt::format("{}", index), fmt::format("Controller {}", index + 1)), m_index(index)
{
m_settings.motion = true;
}
void NativeWiimoteController::save(pugi::xml_node& node)
{
base_type::save(node);
node.append_child("packet_delay").append_child(pugi::node_pcdata).set_value(
fmt::format("{}", m_packet_delay).c_str());
}
void NativeWiimoteController::load(const pugi::xml_node& node)
{
base_type::load(node);
if (const auto value = node.child("packet_delay"))
m_packet_delay = ConvertString<uint32>(value.child_value());
}
bool NativeWiimoteController::connect()
{
if (is_connected())
return true;
if (!m_provider->is_registered_device(m_index))
{
m_provider->get_controllers();
}
if (m_provider->is_connected(m_index))
{
m_provider->set_packet_delay(m_index, m_packet_delay);
m_provider->set_led(m_index, m_player_index);
return true;
}
return false;
}
bool NativeWiimoteController::is_connected()
{
if (m_provider->is_connected(m_index))
{
m_provider->set_packet_delay(m_index, m_packet_delay);
return true;
}
return false;
}
void NativeWiimoteController::set_player_index(size_t player_index)
{
m_player_index = player_index;
m_provider->set_led(m_index, m_player_index);
}
NativeWiimoteController::Extension NativeWiimoteController::get_extension() const
{
Extension result = None;
const auto ext = m_provider->get_state(m_index).m_extension;
if (std::holds_alternative<NunchuckData>(ext))
result = Nunchuck;
else if (std::holds_alternative<ClassicData>(ext))
result = Classic;
return result;
}
bool NativeWiimoteController::is_mpls_attached() const
{
return m_provider->get_state(m_index).m_motion_plus.has_value();
}
bool NativeWiimoteController::has_position()
{
const auto state = m_provider->get_state(m_index);
return std::any_of(state.ir_camera.dots.cbegin(), state.ir_camera.dots.cend(),
[](const IRDot& v) { return v.visible; });
}
glm::vec2 NativeWiimoteController::get_position()
{
const auto state = m_provider->get_state(m_index);
return state.ir_camera.position;
}
glm::vec2 NativeWiimoteController::get_prev_position()
{
const auto state = m_provider->get_state(m_index);
return state.ir_camera.m_prev_position;
}
bool NativeWiimoteController::has_low_battery()
{
const auto state = m_provider->get_state(m_index);
return HAS_FLAG(state.flags, kBatteryEmpty);
}
void NativeWiimoteController::start_rumble()
{
if (m_settings.rumble < 1.0f)
{
return;
}
m_provider->set_rumble(m_index, true);
}
void NativeWiimoteController::stop_rumble()
{
m_provider->set_rumble(m_index, false);
}
MotionSample NativeWiimoteController::get_motion_sample()
{
const auto state = m_provider->get_state(m_index);
return state.motion_sample;
}
MotionSample NativeWiimoteController::get_nunchuck_motion_sample() const
{
const auto state = m_provider->get_state(m_index);
if (std::holds_alternative<NunchuckData>(state.m_extension))
{
return std::get<NunchuckData>(state.m_extension).motion_sample;
}
return {};
}
std::string NativeWiimoteController::get_button_name(uint64 button) const
{
switch (button)
{
case kWiimoteButton_A: return "A";
case kWiimoteButton_B: return "B";
case kWiimoteButton_One: return "1";
case kWiimoteButton_Two: return "2";
case kWiimoteButton_Plus: return "+";
case kWiimoteButton_Minus: return "-";
case kWiimoteButton_Home: return "HOME";
case kWiimoteButton_Up: return "UP";
case kWiimoteButton_Down: return "DOWN";
case kWiimoteButton_Left: return "LEFT";
case kWiimoteButton_Right: return "RIGHT";
// nunchuck
case kWiimoteButton_C: return "C";
case kWiimoteButton_Z: return "Z";
// classic
case kHighestWiimote + kClassicButton_A: return "A";
case kHighestWiimote + kClassicButton_B: return "B";
case kHighestWiimote + kClassicButton_Y: return "Y";
case kHighestWiimote + kClassicButton_X: return "X";
case kHighestWiimote + kClassicButton_Plus: return "+";
case kHighestWiimote + kClassicButton_Minus: return "-";
case kHighestWiimote + kClassicButton_Home: return "HOME";
case kHighestWiimote + kClassicButton_Up: return "UP";
case kHighestWiimote + kClassicButton_Down: return "DOWN";
case kHighestWiimote + kClassicButton_Left: return "LEFT";
case kHighestWiimote + kClassicButton_Right: return "RIGHT";
case kHighestWiimote + kClassicButton_L: return "L";
case kHighestWiimote + kClassicButton_R: return "R";
case kHighestWiimote + kClassicButton_ZL: return "ZL";
case kHighestWiimote + kClassicButton_ZR: return "ZR";
}
return base_type::get_button_name(button);
}
uint32 NativeWiimoteController::get_packet_delay()
{
m_packet_delay = m_provider->get_packet_delay(m_index);
return m_packet_delay;
}
void NativeWiimoteController::set_packet_delay(uint32 delay)
{
m_packet_delay = delay;
m_provider->set_packet_delay(m_index, delay);
}
ControllerState NativeWiimoteController::raw_state()
{
ControllerState result{};
if (!is_connected())
return result;
const auto state = m_provider->get_state(m_index);
for (int i = 0; i < std::numeric_limits<uint16>::digits; i++)
result.buttons[i] = state.buttons & (1<<i);
if (std::holds_alternative<NunchuckData>(state.m_extension))
{
const auto nunchuck = std::get<NunchuckData>(state.m_extension);
if (nunchuck.c)
result.buttons[kWiimoteButton_C]=true;
if (nunchuck.z)
result.buttons[kWiimoteButton_Z]=true;
result.axis = nunchuck.axis;
}
else if (std::holds_alternative<ClassicData>(state.m_extension))
{
const auto classic = std::get<ClassicData>(state.m_extension);
uint64 buttons = (uint64)classic.buttons << kHighestWiimote;
for (int i = 0; i < std::numeric_limits<uint64>::digits; i++)
result.buttons[i] = result.buttons[i] || (buttons & (1 << i));
result.axis = classic.left_axis;
result.rotation = classic.right_axis;
result.trigger = classic.trigger;
}
return result;
}