#include "input/api/Wiimote/NativeWiimoteController.h" #include "input/api/Wiimote/WiimoteControllerProvider.h" #include 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(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(ext)) result = Nunchuck; else if (std::holds_alternative(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(state.m_extension)) { return std::get(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::digits; i++) result.buttons[i] = state.buttons & (1<(state.m_extension)) { const auto nunchuck = std::get(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(state.m_extension)) { const auto classic = std::get(state.m_extension); uint64 buttons = (uint64)classic.buttons << kHighestWiimote; for (int i = 0; i < std::numeric_limits::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; }