#pragma once #include "input/motion/MotionHandler.h" #include "input/api/Wiimote/WiimoteDevice.h" #include "input/api/Wiimote/WiimoteMessages.h" #include "input/api/ControllerProvider.h" #include #include #include #ifndef HAS_WIIMOTE #define HAS_WIIMOTE 1 #endif #define WIIMOTE_DEBUG 1 class WiimoteControllerProvider : public ControllerProviderBase { friend class WiimoteController; public: constexpr static uint32 kDefaultPacketDelay = 25; WiimoteControllerProvider(); ~WiimoteControllerProvider(); inline static InputAPI::Type kAPIType = InputAPI::Wiimote; InputAPI::Type api() const override { return kAPIType; } std::vector> get_controllers() override; bool is_connected(size_t index); bool is_registered_device(size_t index); void set_rumble(size_t index, bool state); void request_status(size_t index); void set_led(size_t index, size_t player_index); uint32 get_packet_delay(size_t index); void set_packet_delay(size_t index, uint32 delay); struct WiimoteState { uint16 buttons = 0; uint8 flags = 0; uint8 battery_level = 0; glm::vec3 m_acceleration{}, m_prev_acceleration{}; float m_roll = 0; std::chrono::high_resolution_clock::time_point m_last_motion_timestamp{}; MotionSample motion_sample{}; WiiUMotionHandler motion_handler{}; bool m_calibrated = false; Calibration m_calib_acceleration{}; struct IRCamera { IRMode mode = kIRDisabled; std::array dots{}, prev_dots{}; glm::vec2 position{}, m_prev_position{}; glm::vec2 middle {}; float distance = 0; std::pair indices{ 0,1 }; }ir_camera{}; std::optional m_motion_plus; std::variant m_extension{}; }; WiimoteState get_state(size_t index); private: std::atomic_bool m_running = false; std::thread m_reader_thread, m_writer_thread; std::shared_mutex m_device_mutex; struct Wiimote { Wiimote(WiimoteDevicePtr device) : device(std::move(device)) {} WiimoteDevicePtr device; std::atomic_bool connected = true; std::atomic_bool rumble = false; std::shared_mutex mutex; WiimoteState state{}; std::atomic_uint32_t data_delay = kDefaultPacketDelay; std::chrono::high_resolution_clock::time_point data_ts{}; }; boost::ptr_vector m_wiimotes; std::list>> m_write_queue; std::mutex m_writer_mutex; std::condition_variable m_writer_cond; void reader_thread(); void writer_thread(); void calibrate(size_t index); IRMode set_ir_camera(size_t index, bool state); void send_packet(size_t index, std::vector data); void send_read_packet(size_t index, MemoryType type, RegisterAddress address, uint16 size); void send_write_packet(size_t index, MemoryType type, RegisterAddress address, const std::vector& data); void parse_acceleration(WiimoteState& wiimote_state, const uint8*& data); void rotate_ir(WiimoteState& wiimote_state); void calculate_ir_position(WiimoteState& wiimote_state); int parse_ir(WiimoteState& wiimote_state, const uint8* data); void request_extension(size_t index); void detect_motion_plus(size_t index); void set_motion_plus(size_t index, bool state); void update_report_type(size_t index); };