Add multiple udp server support
This commit is contained in:
		
							parent
							
								
									0e15c68f54
								
							
						
					
					
						commit
						2c2b586d86
					
				| @ -174,9 +174,7 @@ struct Values { | ||||
| 
 | ||||
|     Setting<bool> motion_enabled; | ||||
|     std::string motion_device; | ||||
|     std::string udp_input_address; | ||||
|     u16 udp_input_port; | ||||
|     u8 udp_pad_index; | ||||
|     std::string udp_input_servers; | ||||
| 
 | ||||
|     bool mouse_enabled; | ||||
|     std::string mouse_device; | ||||
|  | ||||
| @ -233,7 +233,7 @@ void InputSubsystem::ReloadInputDevices() { | ||||
|     if (!impl->udp) { | ||||
|         return; | ||||
|     } | ||||
|     impl->udp->ReloadUDPClient(); | ||||
|     impl->udp->ReloadSockets(); | ||||
| } | ||||
| 
 | ||||
| std::vector<std::unique_ptr<Polling::DevicePoller>> InputSubsystem::GetPollers( | ||||
|  | ||||
| @ -136,15 +136,7 @@ static void SocketLoop(Socket* socket) { | ||||
| 
 | ||||
| Client::Client() { | ||||
|     LOG_INFO(Input, "Udp Initialization started"); | ||||
|     for (std::size_t client = 0; client < clients.size(); client++) { | ||||
|         const auto pad = client % 4; | ||||
|         StartCommunication(client, Settings::values.udp_input_address, | ||||
|                            Settings::values.udp_input_port, pad, 24872); | ||||
|         // Set motion parameters
 | ||||
|         // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
 | ||||
|         // Real HW values are unknown, 0.0001 is an approximate to Standard
 | ||||
|         clients[client].motion.SetGyroThreshold(0.0001f); | ||||
|     } | ||||
|     ReloadSockets(); | ||||
| } | ||||
| 
 | ||||
| Client::~Client() { | ||||
| @ -167,26 +159,61 @@ std::vector<Common::ParamPackage> Client::GetInputDevices() const { | ||||
|     return devices; | ||||
| } | ||||
| 
 | ||||
| bool Client::DeviceConnected(std::size_t pad) const { | ||||
| bool Client::DeviceConnected(std::size_t client) const { | ||||
|     // Use last timestamp to detect if the socket has stopped sending data
 | ||||
|     const auto now = std::chrono::system_clock::now(); | ||||
|     const auto time_difference = static_cast<u64>( | ||||
|         std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update) | ||||
|     const auto now = std::chrono::steady_clock::now(); | ||||
|     const auto time_difference = | ||||
|         static_cast<u64>(std::chrono::duration_cast<std::chrono::milliseconds>( | ||||
|                              now - clients[client].last_motion_update) | ||||
|                              .count()); | ||||
|     return time_difference < 1000 && clients[pad].active == 1; | ||||
|     return time_difference < 1000 && clients[client].active == 1; | ||||
| } | ||||
| 
 | ||||
| void Client::ReloadUDPClient() { | ||||
| void Client::ReloadSockets() { | ||||
|     Reset(); | ||||
| 
 | ||||
|     std::stringstream servers_ss(Settings::values.udp_input_servers); | ||||
|     std::string server_token; | ||||
|     std::size_t client = 0; | ||||
|     while (std::getline(servers_ss, server_token, ',')) { | ||||
|         if (client == max_udp_clients) { | ||||
|             break; | ||||
|         } | ||||
|         std::stringstream server_ss(server_token); | ||||
|         std::string token; | ||||
|         std::getline(server_ss, token, ':'); | ||||
|         std::string udp_input_address = token; | ||||
|         std::getline(server_ss, token, ':'); | ||||
|         char* temp; | ||||
|         const u16 udp_input_port = static_cast<u16>(std::strtol(token.c_str(), &temp, 0)); | ||||
|         if (*temp != '\0') { | ||||
|             LOG_ERROR(Input, "Port number is not valid {}", token); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         for (std::size_t pad = 0; pad < 4; ++pad) { | ||||
|             const std::size_t client_number = | ||||
|                 GetClientNumber(udp_input_address, udp_input_port, pad); | ||||
|             if (client_number != max_udp_clients) { | ||||
|                 LOG_ERROR(Input, "Duplicated UDP servers found"); | ||||
|                 continue; | ||||
|             } | ||||
|             StartCommunication(client++, udp_input_address, udp_input_port, pad, 24872); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t pad) const { | ||||
|     for (std::size_t client = 0; client < clients.size(); client++) { | ||||
|         ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client); | ||||
|         if (clients[client].active == -1) { | ||||
|             continue; | ||||
|         } | ||||
|         if (clients[client].host == host && clients[client].port == port && | ||||
|             clients[client].pad_index == pad) { | ||||
|             return client; | ||||
|         } | ||||
|     } | ||||
| void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_index, u32 client_id) { | ||||
|     // client number must be determined from host / port and pad index
 | ||||
|     const std::size_t client = pad_index; | ||||
|     clients[client].socket->Stop(); | ||||
|     clients[client].thread.join(); | ||||
|     StartCommunication(client, host, port, pad_index, client_id); | ||||
|     return max_udp_clients; | ||||
| } | ||||
| 
 | ||||
| void Client::OnVersion([[maybe_unused]] Response::Version data) { | ||||
| @ -197,9 +224,7 @@ void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) { | ||||
|     LOG_TRACE(Input, "PortInfo packet received: {}", data.model); | ||||
| } | ||||
| 
 | ||||
| void Client::OnPadData(Response::PadData data) { | ||||
|     // Client number must be determined from host / port and pad index
 | ||||
|     const std::size_t client = data.info.id; | ||||
| void Client::OnPadData(Response::PadData data, std::size_t client) { | ||||
|     LOG_TRACE(Input, "PadData packet received"); | ||||
|     if (data.packet_counter == clients[client].packet_sequence) { | ||||
|         LOG_WARNING( | ||||
| @ -208,9 +233,9 @@ void Client::OnPadData(Response::PadData data) { | ||||
|             clients[client].packet_sequence, data.packet_counter); | ||||
|         return; | ||||
|     } | ||||
|     clients[client].active = data.info.is_pad_active; | ||||
|     clients[client].active = static_cast<s8>(data.info.is_pad_active); | ||||
|     clients[client].packet_sequence = data.packet_counter; | ||||
|     const auto now = std::chrono::system_clock::now(); | ||||
|     const auto now = std::chrono::steady_clock::now(); | ||||
|     const auto time_difference = | ||||
|         static_cast<u64>(std::chrono::duration_cast<std::chrono::microseconds>( | ||||
|                              now - clients[client].last_motion_update) | ||||
| @ -264,18 +289,30 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16 | ||||
|                                 std::size_t pad_index, u32 client_id) { | ||||
|     SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, | ||||
|                             [this](Response::PortInfo info) { OnPortInfo(info); }, | ||||
|                             [this](Response::PadData data) { OnPadData(data); }}; | ||||
|     LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port); | ||||
|                             [this, client](Response::PadData data) { OnPadData(data, client); }}; | ||||
|     LOG_INFO(Input, "Starting communication with UDP input server on {}:{}:{}", host, port, | ||||
|              pad_index); | ||||
|     clients[client].host = host; | ||||
|     clients[client].port = port; | ||||
|     clients[client].pad_index = pad_index; | ||||
|     clients[client].active = 0; | ||||
|     clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback); | ||||
|     clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; | ||||
|     // Set motion parameters
 | ||||
|     // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
 | ||||
|     // Real HW values are unknown, 0.0001 is an approximate to Standard
 | ||||
|     clients[client].motion.SetGyroThreshold(0.0001f); | ||||
| } | ||||
| 
 | ||||
| void Client::Reset() { | ||||
|     for (auto& client : clients) { | ||||
|         if (client.thread.joinable()) { | ||||
|             client.active = -1; | ||||
|             client.socket->Stop(); | ||||
|             client.thread.join(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | ||||
|                                 const Common::Vec3<float>& gyro, bool touch) { | ||||
| @ -283,52 +320,60 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a | ||||
|         LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {}), touch={}", | ||||
|                   client, gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2], touch); | ||||
|     } | ||||
|     UDPPadStatus pad; | ||||
|     UDPPadStatus pad{ | ||||
|         .host = clients[client].host, | ||||
|         .port = clients[client].port, | ||||
|         .pad_index = clients[client].pad_index, | ||||
|     }; | ||||
|     if (touch) { | ||||
|         pad.touch = PadTouch::Click; | ||||
|         pad_queue[client].Push(pad); | ||||
|         pad_queue.Push(pad); | ||||
|     } | ||||
|     for (size_t i = 0; i < 3; ++i) { | ||||
|         if (gyro[i] > 5.0f || gyro[i] < -5.0f) { | ||||
|             pad.motion = static_cast<PadMotion>(i); | ||||
|             pad.motion_value = gyro[i]; | ||||
|             pad_queue[client].Push(pad); | ||||
|             pad_queue.Push(pad); | ||||
|         } | ||||
|         if (acc[i] > 1.75f || acc[i] < -1.75f) { | ||||
|             pad.motion = static_cast<PadMotion>(i + 3); | ||||
|             pad.motion_value = acc[i]; | ||||
|             pad_queue[client].Push(pad); | ||||
|             pad_queue.Push(pad); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Client::BeginConfiguration() { | ||||
|     for (auto& pq : pad_queue) { | ||||
|         pq.Clear(); | ||||
|     } | ||||
|     pad_queue.Clear(); | ||||
|     configuring = true; | ||||
| } | ||||
| 
 | ||||
| void Client::EndConfiguration() { | ||||
|     for (auto& pq : pad_queue) { | ||||
|         pq.Clear(); | ||||
|     } | ||||
|     pad_queue.Clear(); | ||||
|     configuring = false; | ||||
| } | ||||
| 
 | ||||
| DeviceStatus& Client::GetPadState(std::size_t pad) { | ||||
|     return clients[pad].status; | ||||
| DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { | ||||
|     const std::size_t client_number = GetClientNumber(host, port, pad); | ||||
|     if (client_number == max_udp_clients) { | ||||
|         return clients[0].status; | ||||
|     } | ||||
|     return clients[client_number].status; | ||||
| } | ||||
| 
 | ||||
| const DeviceStatus& Client::GetPadState(std::size_t pad) const { | ||||
|     return clients[pad].status; | ||||
| const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { | ||||
|     const std::size_t client_number = GetClientNumber(host, port, pad); | ||||
|     if (client_number == max_udp_clients) { | ||||
|         return clients[0].status; | ||||
|     } | ||||
|     return clients[client_number].status; | ||||
| } | ||||
| 
 | ||||
| std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() { | ||||
| Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() { | ||||
|     return pad_queue; | ||||
| } | ||||
| 
 | ||||
| const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() const { | ||||
| const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const { | ||||
|     return pad_queue; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -21,8 +21,7 @@ | ||||
| 
 | ||||
| namespace InputCommon::CemuhookUDP { | ||||
| 
 | ||||
| constexpr u16 DEFAULT_PORT = 26760; | ||||
| constexpr char DEFAULT_ADDR[] = "127.0.0.1"; | ||||
| constexpr char DEFAULT_SRV[] = "127.0.0.1:26760"; | ||||
| 
 | ||||
| class Socket; | ||||
| 
 | ||||
| @ -48,6 +47,9 @@ enum class PadTouch { | ||||
| }; | ||||
| 
 | ||||
| struct UDPPadStatus { | ||||
|     std::string host{"127.0.0.1"}; | ||||
|     u16 port{26760}; | ||||
|     std::size_t pad_index{}; | ||||
|     PadTouch touch{PadTouch::Undefined}; | ||||
|     PadMotion motion{PadMotion::Undefined}; | ||||
|     f32 motion_value{0.0f}; | ||||
| @ -82,37 +84,41 @@ public: | ||||
| 
 | ||||
|     std::vector<Common::ParamPackage> GetInputDevices() const; | ||||
| 
 | ||||
|     bool DeviceConnected(std::size_t pad) const; | ||||
|     void ReloadUDPClient(); | ||||
|     void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, | ||||
|                       std::size_t pad_index = 0, u32 client_id = 24872); | ||||
|     bool DeviceConnected(std::size_t client) const; | ||||
|     void ReloadSockets(); | ||||
| 
 | ||||
|     std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue(); | ||||
|     const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const; | ||||
|     Common::SPSCQueue<UDPPadStatus>& GetPadQueue(); | ||||
|     const Common::SPSCQueue<UDPPadStatus>& GetPadQueue() const; | ||||
| 
 | ||||
|     DeviceStatus& GetPadState(std::size_t pad); | ||||
|     const DeviceStatus& GetPadState(std::size_t pad) const; | ||||
|     DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad); | ||||
|     const DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad) const; | ||||
| 
 | ||||
| private: | ||||
|     struct ClientData { | ||||
|         std::string host{"127.0.0.1"}; | ||||
|         u16 port{26760}; | ||||
|         std::size_t pad_index{}; | ||||
|         std::unique_ptr<Socket> socket; | ||||
|         DeviceStatus status; | ||||
|         std::thread thread; | ||||
|         u64 packet_sequence = 0; | ||||
|         u8 active = 0; | ||||
|         u64 packet_sequence{}; | ||||
|         s8 active{-1}; | ||||
| 
 | ||||
|         // Realtime values
 | ||||
|         // motion is initalized with PID values for drift correction on joycons
 | ||||
|         InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f}; | ||||
|         std::chrono::time_point<std::chrono::system_clock> last_motion_update; | ||||
|         std::chrono::time_point<std::chrono::steady_clock> last_motion_update; | ||||
|     }; | ||||
| 
 | ||||
|     // For shutting down, clear all data, join all threads, release usb
 | ||||
|     void Reset(); | ||||
| 
 | ||||
|     // Translates configuration to client number
 | ||||
|     std::size_t GetClientNumber(std::string_view host, u16 port, std::size_t pad) const; | ||||
| 
 | ||||
|     void OnVersion(Response::Version); | ||||
|     void OnPortInfo(Response::PortInfo); | ||||
|     void OnPadData(Response::PadData); | ||||
|     void OnPadData(Response::PadData, std::size_t client); | ||||
|     void StartCommunication(std::size_t client, const std::string& host, u16 port, | ||||
|                             std::size_t pad_index, u32 client_id); | ||||
|     void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | ||||
| @ -120,8 +126,10 @@ private: | ||||
| 
 | ||||
|     bool configuring = false; | ||||
| 
 | ||||
|     std::array<ClientData, 4> clients; | ||||
|     std::array<Common::SPSCQueue<UDPPadStatus>, 4> pad_queue; | ||||
|     // Allocate clients for 8 udp servers
 | ||||
|     const std::size_t max_udp_clients = 32; | ||||
|     std::array<ClientData, 4 * 8> clients; | ||||
|     Common::SPSCQueue<UDPPadStatus> pad_queue; | ||||
| }; | ||||
| 
 | ||||
| /// An async job allowing configuration of the touchpad calibration.
 | ||||
|  | ||||
| @ -13,17 +13,17 @@ namespace InputCommon { | ||||
| 
 | ||||
| class UDPMotion final : public Input::MotionDevice { | ||||
| public: | ||||
|     explicit UDPMotion(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_) | ||||
|     explicit UDPMotion(std::string ip_, u16 port_, u16 pad_, CemuhookUDP::Client* client_) | ||||
|         : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} | ||||
| 
 | ||||
|     Input::MotionStatus GetStatus() const override { | ||||
|         return client->GetPadState(pad).motion_status; | ||||
|         return client->GetPadState(ip, port, pad).motion_status; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const std::string ip; | ||||
|     const int port; | ||||
|     const u32 pad; | ||||
|     const u16 port; | ||||
|     const u16 pad; | ||||
|     CemuhookUDP::Client* client; | ||||
|     mutable std::mutex mutex; | ||||
| }; | ||||
| @ -39,8 +39,8 @@ UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_) | ||||
|  */ | ||||
| std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) { | ||||
|     auto ip = params.Get("ip", "127.0.0.1"); | ||||
|     const auto port = params.Get("port", 26760); | ||||
|     const auto pad = static_cast<u32>(params.Get("pad_index", 0)); | ||||
|     const auto port = static_cast<u16>(params.Get("port", 26760)); | ||||
|     const auto pad = static_cast<u16>(params.Get("pad_index", 0)); | ||||
| 
 | ||||
|     return std::make_unique<UDPMotion>(std::move(ip), port, pad, client.get()); | ||||
| } | ||||
| @ -59,35 +59,33 @@ Common::ParamPackage UDPMotionFactory::GetNextInput() { | ||||
|     Common::ParamPackage params; | ||||
|     CemuhookUDP::UDPPadStatus pad; | ||||
|     auto& queue = client->GetPadQueue(); | ||||
|     for (std::size_t pad_number = 0; pad_number < queue.size(); ++pad_number) { | ||||
|         while (queue[pad_number].Pop(pad)) { | ||||
|     while (queue.Pop(pad)) { | ||||
|         if (pad.motion == CemuhookUDP::PadMotion::Undefined || std::abs(pad.motion_value) < 1) { | ||||
|             continue; | ||||
|         } | ||||
|         params.Set("engine", "cemuhookudp"); | ||||
|             params.Set("ip", "127.0.0.1"); | ||||
|             params.Set("port", 26760); | ||||
|             params.Set("pad_index", static_cast<int>(pad_number)); | ||||
|         params.Set("ip", pad.host); | ||||
|         params.Set("port", static_cast<u16>(pad.port)); | ||||
|         params.Set("pad_index", static_cast<u16>(pad.pad_index)); | ||||
|         params.Set("motion", static_cast<u16>(pad.motion)); | ||||
|         return params; | ||||
|     } | ||||
|     } | ||||
|     return params; | ||||
| } | ||||
| 
 | ||||
| class UDPTouch final : public Input::TouchDevice { | ||||
| public: | ||||
|     explicit UDPTouch(std::string ip_, int port_, u32 pad_, CemuhookUDP::Client* client_) | ||||
|     explicit UDPTouch(std::string ip_, u16 port_, u16 pad_, CemuhookUDP::Client* client_) | ||||
|         : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} | ||||
| 
 | ||||
|     std::tuple<float, float, bool> GetStatus() const override { | ||||
|         return client->GetPadState(pad).touch_status; | ||||
|         return client->GetPadState(ip, port, pad).touch_status; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const std::string ip; | ||||
|     const int port; | ||||
|     const u32 pad; | ||||
|     const u16 port; | ||||
|     const u16 pad; | ||||
|     CemuhookUDP::Client* client; | ||||
|     mutable std::mutex mutex; | ||||
| }; | ||||
| @ -103,8 +101,8 @@ UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_) | ||||
|  */ | ||||
| std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) { | ||||
|     auto ip = params.Get("ip", "127.0.0.1"); | ||||
|     const auto port = params.Get("port", 26760); | ||||
|     const auto pad = static_cast<u32>(params.Get("pad_index", 0)); | ||||
|     const auto port = static_cast<u16>(params.Get("port", 26760)); | ||||
|     const auto pad = static_cast<u16>(params.Get("pad_index", 0)); | ||||
| 
 | ||||
|     return std::make_unique<UDPTouch>(std::move(ip), port, pad, client.get()); | ||||
| } | ||||
| @ -123,19 +121,17 @@ Common::ParamPackage UDPTouchFactory::GetNextInput() { | ||||
|     Common::ParamPackage params; | ||||
|     CemuhookUDP::UDPPadStatus pad; | ||||
|     auto& queue = client->GetPadQueue(); | ||||
|     for (std::size_t pad_number = 0; pad_number < queue.size(); ++pad_number) { | ||||
|         while (queue[pad_number].Pop(pad)) { | ||||
|     while (queue.Pop(pad)) { | ||||
|         if (pad.touch == CemuhookUDP::PadTouch::Undefined) { | ||||
|             continue; | ||||
|         } | ||||
|         params.Set("engine", "cemuhookudp"); | ||||
|             params.Set("ip", "127.0.0.1"); | ||||
|             params.Set("port", 26760); | ||||
|             params.Set("pad_index", static_cast<int>(pad_number)); | ||||
|         params.Set("ip", pad.host); | ||||
|         params.Set("port", static_cast<u16>(pad.port)); | ||||
|         params.Set("pad_index", static_cast<u16>(pad.pad_index)); | ||||
|         params.Set("touch", static_cast<u16>(pad.touch)); | ||||
|         return params; | ||||
|     } | ||||
|     } | ||||
|     return params; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -568,16 +568,11 @@ void Config::ReadMotionTouchValues() { | ||||
|         ReadSetting(QStringLiteral("touch_from_button_map"), 0).toInt(); | ||||
|     Settings::values.touch_from_button_map_index = | ||||
|         std::clamp(Settings::values.touch_from_button_map_index, 0, num_touch_from_button_maps - 1); | ||||
|     Settings::values.udp_input_address = | ||||
|         ReadSetting(QStringLiteral("udp_input_address"), | ||||
|                     QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR)) | ||||
|     Settings::values.udp_input_servers = | ||||
|         ReadSetting(QStringLiteral("udp_input_servers"), | ||||
|                     QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_SRV)) | ||||
|             .toString() | ||||
|             .toStdString(); | ||||
|     Settings::values.udp_input_port = static_cast<u16>( | ||||
|         ReadSetting(QStringLiteral("udp_input_port"), InputCommon::CemuhookUDP::DEFAULT_PORT) | ||||
|             .toInt()); | ||||
|     Settings::values.udp_pad_index = | ||||
|         static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt()); | ||||
| } | ||||
| 
 | ||||
| void Config::ReadCoreValues() { | ||||
| @ -1108,12 +1103,9 @@ void Config::SaveMotionTouchValues() { | ||||
|                  false); | ||||
|     WriteSetting(QStringLiteral("touch_from_button_map"), | ||||
|                  Settings::values.touch_from_button_map_index, 0); | ||||
|     WriteSetting(QStringLiteral("udp_input_address"), | ||||
|                  QString::fromStdString(Settings::values.udp_input_address), | ||||
|                  QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR)); | ||||
|     WriteSetting(QStringLiteral("udp_input_port"), Settings::values.udp_input_port, | ||||
|                  InputCommon::CemuhookUDP::DEFAULT_PORT); | ||||
|     WriteSetting(QStringLiteral("udp_pad_index"), Settings::values.udp_pad_index, 0); | ||||
|     WriteSetting(QStringLiteral("udp_input_servers"), | ||||
|                  QString::fromStdString(Settings::values.udp_input_servers), | ||||
|                  QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_SRV)); | ||||
| 
 | ||||
|     qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); | ||||
|     for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { | ||||
|  | ||||
| @ -3,10 +3,12 @@ | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <array> | ||||
| #include <sstream> | ||||
| #include <QCloseEvent> | ||||
| #include <QLabel> | ||||
| #include <QMessageBox> | ||||
| #include <QPushButton> | ||||
| #include <QStringListModel> | ||||
| #include <QVBoxLayout> | ||||
| #include "common/logging/log.h" | ||||
| #include "core/settings.h" | ||||
| @ -74,11 +76,6 @@ void CalibrationConfigurationDialog::UpdateButtonText(const QString& text) { | ||||
|     cancel_button->setText(text); | ||||
| } | ||||
| 
 | ||||
| constexpr std::array<std::pair<const char*, const char*>, 2> MotionProviders = {{ | ||||
|     {"motion_emu", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Mouse (Right Click)")}, | ||||
|     {"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}, | ||||
| }}; | ||||
| 
 | ||||
| constexpr std::array<std::pair<const char*, const char*>, 2> TouchProviders = {{ | ||||
|     {"emu_window", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Emulator Window")}, | ||||
|     {"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}, | ||||
| @ -89,9 +86,6 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, | ||||
|     : QDialog(parent), input_subsystem{input_subsystem_}, | ||||
|       ui(std::make_unique<Ui::ConfigureMotionTouch>()) { | ||||
|     ui->setupUi(this); | ||||
|     for (const auto& [provider, name] : MotionProviders) { | ||||
|         ui->motion_provider->addItem(tr(name), QString::fromUtf8(provider)); | ||||
|     } | ||||
|     for (const auto& [provider, name] : TouchProviders) { | ||||
|         ui->touch_provider->addItem(tr(name), QString::fromUtf8(provider)); | ||||
|     } | ||||
| @ -116,8 +110,6 @@ void ConfigureMotionTouch::SetConfiguration() { | ||||
|     const std::string motion_engine = motion_param.Get("engine", "motion_emu"); | ||||
|     const std::string touch_engine = touch_param.Get("engine", "emu_window"); | ||||
| 
 | ||||
|     ui->motion_provider->setCurrentIndex( | ||||
|         ui->motion_provider->findData(QString::fromStdString(motion_engine))); | ||||
|     ui->touch_provider->setCurrentIndex( | ||||
|         ui->touch_provider->findData(QString::fromStdString(touch_engine))); | ||||
|     ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button); | ||||
| @ -133,23 +125,30 @@ void ConfigureMotionTouch::SetConfiguration() { | ||||
|     max_x = touch_param.Get("max_x", 1800); | ||||
|     max_y = touch_param.Get("max_y", 850); | ||||
| 
 | ||||
|     ui->udp_server->setText(QString::fromStdString(Settings::values.udp_input_address)); | ||||
|     ui->udp_port->setText(QString::number(Settings::values.udp_input_port)); | ||||
|     ui->udp_pad_index->setCurrentIndex(Settings::values.udp_pad_index); | ||||
|     ui->udp_server->setText(QString::fromStdString("127.0.0.1")); | ||||
|     ui->udp_port->setText(QString::number(26760)); | ||||
| 
 | ||||
|     udp_server_list_model = new QStringListModel(this); | ||||
|     udp_server_list_model->setStringList({}); | ||||
|     ui->udp_server_list->setModel(udp_server_list_model); | ||||
| 
 | ||||
|     std::stringstream ss(Settings::values.udp_input_servers); | ||||
|     std::string token; | ||||
| 
 | ||||
|     while (std::getline(ss, token, ',')) { | ||||
|         const int row = udp_server_list_model->rowCount(); | ||||
|         udp_server_list_model->insertRows(row, 1); | ||||
|         const QModelIndex index = udp_server_list_model->index(row); | ||||
|         udp_server_list_model->setData(index, QString::fromStdString(token)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ConfigureMotionTouch::UpdateUiDisplay() { | ||||
|     const QString motion_engine = ui->motion_provider->currentData().toString(); | ||||
|     const QString touch_engine = ui->touch_provider->currentData().toString(); | ||||
|     const QString cemuhook_udp = QStringLiteral("cemuhookudp"); | ||||
| 
 | ||||
|     if (motion_engine == QStringLiteral("motion_emu")) { | ||||
|     ui->motion_sensitivity_label->setVisible(true); | ||||
|     ui->motion_sensitivity->setVisible(true); | ||||
|     } else { | ||||
|         ui->motion_sensitivity_label->setVisible(false); | ||||
|         ui->motion_sensitivity->setVisible(false); | ||||
|     } | ||||
| 
 | ||||
|     if (touch_engine == cemuhook_udp) { | ||||
|         ui->touch_calibration->setVisible(true); | ||||
| @ -163,19 +162,15 @@ void ConfigureMotionTouch::UpdateUiDisplay() { | ||||
|         ui->touch_calibration_label->setVisible(false); | ||||
|     } | ||||
| 
 | ||||
|     if (motion_engine == cemuhook_udp || touch_engine == cemuhook_udp) { | ||||
|     ui->udp_config_group_box->setVisible(true); | ||||
|     } else { | ||||
|         ui->udp_config_group_box->setVisible(false); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ConfigureMotionTouch::ConnectEvents() { | ||||
|     connect(ui->motion_provider, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             [this](int index) { UpdateUiDisplay(); }); | ||||
|     connect(ui->touch_provider, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             [this](int index) { UpdateUiDisplay(); }); | ||||
|     connect(ui->udp_test, &QPushButton::clicked, this, &ConfigureMotionTouch::OnCemuhookUDPTest); | ||||
|     connect(ui->udp_add, &QPushButton::clicked, this, &ConfigureMotionTouch::OnUDPAddServer); | ||||
|     connect(ui->udp_remove, &QPushButton::clicked, this, &ConfigureMotionTouch::OnUDPDeleteServer); | ||||
|     connect(ui->touch_calibration_config, &QPushButton::clicked, this, | ||||
|             &ConfigureMotionTouch::OnConfigureTouchCalibration); | ||||
|     connect(ui->touch_from_button_config_btn, &QPushButton::clicked, this, | ||||
| @ -187,13 +182,58 @@ void ConfigureMotionTouch::ConnectEvents() { | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void ConfigureMotionTouch::OnUDPAddServer() { | ||||
|     QRegExp re(tr("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[" | ||||
|                   "0-9][0-9]?)$")); // a valid ip address
 | ||||
|     bool ok; | ||||
|     QString port_text = ui->udp_port->text(); | ||||
|     QString server_text = ui->udp_server->text(); | ||||
|     const QString server_string = tr("%1:%2").arg(server_text, port_text); | ||||
|     int port_number = port_text.toInt(&ok, 10); | ||||
|     int row = udp_server_list_model->rowCount(); | ||||
| 
 | ||||
|     if (!ok) { | ||||
|         QMessageBox::warning(this, tr("yuzu"), tr("Port number has invalid characters")); | ||||
|         return; | ||||
|     } | ||||
|     if (port_number < 0 || port_number > 65353) { | ||||
|         QMessageBox::warning(this, tr("yuzu"), tr("Port has to be in range 0 and 65353")); | ||||
|         return; | ||||
|     } | ||||
|     if (!re.exactMatch(server_text)) { | ||||
|         QMessageBox::warning(this, tr("yuzu"), tr("IP address is not valid")); | ||||
|         return; | ||||
|     } | ||||
|     // Search for duplicates
 | ||||
|     for (const auto& item : udp_server_list_model->stringList()) { | ||||
|         if (item == server_string) { | ||||
|             QMessageBox::warning(this, tr("yuzu"), tr("This UDP server already exists")); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     // Limit server count to 8
 | ||||
|     if (row == 8) { | ||||
|         QMessageBox::warning(this, tr("yuzu"), tr("Unable to add more than 8 servers")); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     udp_server_list_model->insertRows(row, 1); | ||||
|     QModelIndex index = udp_server_list_model->index(row); | ||||
|     udp_server_list_model->setData(index, server_string); | ||||
|     ui->udp_server_list->setCurrentIndex(index); | ||||
| } | ||||
| 
 | ||||
| void ConfigureMotionTouch::OnUDPDeleteServer() { | ||||
|     udp_server_list_model->removeRows(ui->udp_server_list->currentIndex().row(), 1); | ||||
| } | ||||
| 
 | ||||
| void ConfigureMotionTouch::OnCemuhookUDPTest() { | ||||
|     ui->udp_test->setEnabled(false); | ||||
|     ui->udp_test->setText(tr("Testing")); | ||||
|     udp_test_in_progress = true; | ||||
|     InputCommon::CemuhookUDP::TestCommunication( | ||||
|         ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), | ||||
|         static_cast<u32>(ui->udp_pad_index->currentIndex()), 24872, | ||||
|         ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0, | ||||
|         24872, | ||||
|         [this] { | ||||
|             LOG_INFO(Frontend, "UDP input test success"); | ||||
|             QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); | ||||
| @ -207,9 +247,9 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() { | ||||
| void ConfigureMotionTouch::OnConfigureTouchCalibration() { | ||||
|     ui->touch_calibration_config->setEnabled(false); | ||||
|     ui->touch_calibration_config->setText(tr("Configuring")); | ||||
|     CalibrationConfigurationDialog dialog( | ||||
|         this, ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toUInt()), | ||||
|         static_cast<u8>(ui->udp_pad_index->currentIndex()), 24872); | ||||
|     CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), | ||||
|                                           static_cast<u16>(ui->udp_port->text().toUInt()), 0, | ||||
|                                           24872); | ||||
|     dialog.exec(); | ||||
|     if (dialog.completed) { | ||||
|         min_x = dialog.min_x; | ||||
| @ -269,7 +309,7 @@ void ConfigureMotionTouch::OnConfigureTouchFromButton() { | ||||
| 
 | ||||
| bool ConfigureMotionTouch::CanCloseDialog() { | ||||
|     if (udp_test_in_progress) { | ||||
|         QMessageBox::warning(this, tr("Citra"), | ||||
|         QMessageBox::warning(this, tr("yuzu"), | ||||
|                              tr("UDP Test or calibration configuration is in progress.<br>Please " | ||||
|                                 "wait for them to finish.")); | ||||
|         return false; | ||||
| @ -282,17 +322,11 @@ void ConfigureMotionTouch::ApplyConfiguration() { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     std::string motion_engine = ui->motion_provider->currentData().toString().toStdString(); | ||||
|     std::string touch_engine = ui->touch_provider->currentData().toString().toStdString(); | ||||
| 
 | ||||
|     Common::ParamPackage motion_param{}, touch_param{}; | ||||
|     motion_param.Set("engine", std::move(motion_engine)); | ||||
|     Common::ParamPackage touch_param{}; | ||||
|     touch_param.Set("engine", std::move(touch_engine)); | ||||
| 
 | ||||
|     if (motion_engine == "motion_emu") { | ||||
|         motion_param.Set("sensitivity", static_cast<float>(ui->motion_sensitivity->value())); | ||||
|     } | ||||
| 
 | ||||
|     if (touch_engine == "cemuhookudp") { | ||||
|         touch_param.Set("min_x", min_x); | ||||
|         touch_param.Set("min_y", min_y); | ||||
| @ -300,15 +334,25 @@ void ConfigureMotionTouch::ApplyConfiguration() { | ||||
|         touch_param.Set("max_y", max_y); | ||||
|     } | ||||
| 
 | ||||
|     Settings::values.motion_device = motion_param.Serialize(); | ||||
|     Settings::values.touch_device = touch_param.Serialize(); | ||||
|     Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked(); | ||||
|     Settings::values.touch_from_button_map_index = ui->touch_from_button_map->currentIndex(); | ||||
|     Settings::values.touch_from_button_maps = touch_from_button_maps; | ||||
|     Settings::values.udp_input_address = ui->udp_server->text().toStdString(); | ||||
|     Settings::values.udp_input_port = static_cast<u16>(ui->udp_port->text().toInt()); | ||||
|     Settings::values.udp_pad_index = static_cast<u8>(ui->udp_pad_index->currentIndex()); | ||||
|     Settings::values.udp_input_servers = GetUDPServerString(); | ||||
|     input_subsystem->ReloadInputDevices(); | ||||
| 
 | ||||
|     accept(); | ||||
| } | ||||
| 
 | ||||
| std::string ConfigureMotionTouch::GetUDPServerString() const { | ||||
|     QString input_servers; | ||||
| 
 | ||||
|     for (const auto& item : udp_server_list_model->stringList()) { | ||||
|         input_servers += item; | ||||
|         input_servers += QLatin1Char{','}; | ||||
|     } | ||||
| 
 | ||||
|     // Remove last comma
 | ||||
|     input_servers.chop(1); | ||||
|     return input_servers.toStdString(); | ||||
| } | ||||
|  | ||||
| @ -10,6 +10,7 @@ | ||||
| 
 | ||||
| class QLabel; | ||||
| class QPushButton; | ||||
| class QStringListModel; | ||||
| class QVBoxLayout; | ||||
| 
 | ||||
| namespace InputCommon { | ||||
| @ -62,6 +63,8 @@ public slots: | ||||
|     void ApplyConfiguration(); | ||||
| 
 | ||||
| private slots: | ||||
|     void OnUDPAddServer(); | ||||
|     void OnUDPDeleteServer(); | ||||
|     void OnCemuhookUDPTest(); | ||||
|     void OnConfigureTouchCalibration(); | ||||
|     void OnConfigureTouchFromButton(); | ||||
| @ -73,10 +76,12 @@ private: | ||||
|     void UpdateUiDisplay(); | ||||
|     void ConnectEvents(); | ||||
|     bool CanCloseDialog(); | ||||
|     std::string GetUDPServerString() const; | ||||
| 
 | ||||
|     InputCommon::InputSubsystem* input_subsystem; | ||||
| 
 | ||||
|     std::unique_ptr<Ui::ConfigureMotionTouch> ui; | ||||
|     QStringListModel* udp_server_list_model; | ||||
| 
 | ||||
|     // Coordinate system of the CemuhookUDP touch provider
 | ||||
|     int min_x{}; | ||||
|  | ||||
| @ -2,38 +2,27 @@ | ||||
| <ui version="4.0"> | ||||
|  <class>ConfigureMotionTouch</class> | ||||
|  <widget class="QDialog" name="ConfigureMotionTouch"> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Configure Motion / Touch</string> | ||||
|   </property> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>500</width> | ||||
|     <height>450</height> | ||||
|     <height>482</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Configure Motion / Touch</string> | ||||
|   </property> | ||||
|   <property name="styleSheet"> | ||||
|    <string notr="true"/> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout"> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="motion_group_box"> | ||||
|      <property name="title"> | ||||
|       <string>Motion</string> | ||||
|       <string>Mouse Motion</string> | ||||
|      </property> | ||||
|      <layout class="QVBoxLayout"> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="motion_provider_label"> | ||||
|           <property name="text"> | ||||
|            <string>Motion Provider:</string> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="motion_provider"/> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout"> | ||||
|         <item> | ||||
| @ -179,8 +168,36 @@ | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|         <item> | ||||
|          <widget class="QListView" name="udp_server_list"/> | ||||
|         </item> | ||||
|         <item> | ||||
|          <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|           <property name="leftMargin"> | ||||
|            <number>0</number> | ||||
|           </property> | ||||
|           <property name="topMargin"> | ||||
|            <number>0</number> | ||||
|           </property> | ||||
|           <property name="rightMargin"> | ||||
|            <number>0</number> | ||||
|           </property> | ||||
|           <property name="bottomMargin"> | ||||
|            <number>0</number> | ||||
|           </property> | ||||
|           <item> | ||||
|            <layout class="QHBoxLayout"> | ||||
|             <property name="leftMargin"> | ||||
|              <number>3</number> | ||||
|             </property> | ||||
|             <property name="topMargin"> | ||||
|              <number>3</number> | ||||
|             </property> | ||||
|             <property name="rightMargin"> | ||||
|              <number>0</number> | ||||
|             </property> | ||||
|             <item> | ||||
|              <widget class="QLabel" name="udp_server_label"> | ||||
|               <property name="text"> | ||||
| @ -202,6 +219,12 @@ | ||||
|           </item> | ||||
|           <item> | ||||
|            <layout class="QHBoxLayout"> | ||||
|             <property name="leftMargin"> | ||||
|              <number>3</number> | ||||
|             </property> | ||||
|             <property name="rightMargin"> | ||||
|              <number>0</number> | ||||
|             </property> | ||||
|             <item> | ||||
|              <widget class="QLabel" name="udp_port_label"> | ||||
|               <property name="text"> | ||||
| @ -223,41 +246,12 @@ | ||||
|           </item> | ||||
|           <item> | ||||
|            <layout class="QHBoxLayout"> | ||||
|         <item> | ||||
|          <widget class="QLabel" name="udp_pad_index_label"> | ||||
|           <property name="text"> | ||||
|            <string>Pad:</string> | ||||
|             <property name="leftMargin"> | ||||
|              <number>3</number> | ||||
|             </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QComboBox" name="udp_pad_index"> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Pad 1</string> | ||||
|             <property name="rightMargin"> | ||||
|              <number>0</number> | ||||
|             </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Pad 2</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Pad 3</string> | ||||
|            </property> | ||||
|           </item> | ||||
|           <item> | ||||
|            <property name="text"> | ||||
|             <string>Pad 4</string> | ||||
|            </property> | ||||
|           </item> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout"> | ||||
|             <item> | ||||
|              <widget class="QLabel" name="udp_learn_more"> | ||||
|               <property name="text"> | ||||
| @ -278,6 +272,69 @@ | ||||
|               </property> | ||||
|              </widget> | ||||
|             </item> | ||||
|             <item> | ||||
|              <widget class="QPushButton" name="udp_add"> | ||||
|               <property name="sizePolicy"> | ||||
|                <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||||
|                 <horstretch>0</horstretch> | ||||
|                 <verstretch>0</verstretch> | ||||
|                </sizepolicy> | ||||
|               </property> | ||||
|               <property name="text"> | ||||
|                <string>Add Server</string> | ||||
|               </property> | ||||
|              </widget> | ||||
|             </item> | ||||
|            </layout> | ||||
|           </item> | ||||
|           <item> | ||||
|            <spacer name="verticalSpacer_3"> | ||||
|             <property name="orientation"> | ||||
|              <enum>Qt::Vertical</enum> | ||||
|             </property> | ||||
|             <property name="sizeHint" stdset="0"> | ||||
|              <size> | ||||
|               <width>20</width> | ||||
|               <height>40</height> | ||||
|              </size> | ||||
|             </property> | ||||
|            </spacer> | ||||
|           </item> | ||||
|           <item> | ||||
|            <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||
|             <property name="topMargin"> | ||||
|              <number>0</number> | ||||
|             </property> | ||||
|             <item> | ||||
|              <widget class="QPushButton" name="udp_remove"> | ||||
|               <property name="sizePolicy"> | ||||
|                <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> | ||||
|                 <horstretch>0</horstretch> | ||||
|                 <verstretch>0</verstretch> | ||||
|                </sizepolicy> | ||||
|               </property> | ||||
|               <property name="text"> | ||||
|                <string>Remove Server</string> | ||||
|               </property> | ||||
|              </widget> | ||||
|             </item> | ||||
|             <item> | ||||
|              <spacer name="horizontalSpacer_2"> | ||||
|               <property name="orientation"> | ||||
|                <enum>Qt::Horizontal</enum> | ||||
|               </property> | ||||
|               <property name="sizeHint" stdset="0"> | ||||
|                <size> | ||||
|                 <width>40</width> | ||||
|                 <height>20</height> | ||||
|                </size> | ||||
|               </property> | ||||
|              </spacer> | ||||
|             </item> | ||||
|            </layout> | ||||
|           </item> | ||||
|          </layout> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|      </layout> | ||||
| @ -312,6 +369,16 @@ | ||||
|    <signal>accepted()</signal> | ||||
|    <receiver>ConfigureMotionTouch</receiver> | ||||
|    <slot>ApplyConfiguration()</slot> | ||||
|    <hints> | ||||
|     <hint type="sourcelabel"> | ||||
|      <x>20</x> | ||||
|      <y>20</y> | ||||
|     </hint> | ||||
|     <hint type="destinationlabel"> | ||||
|      <x>20</x> | ||||
|      <y>20</y> | ||||
|     </hint> | ||||
|    </hints> | ||||
|   </connection> | ||||
|  </connections> | ||||
| </ui> | ||||
|  | ||||
| @ -306,10 +306,8 @@ void Config::ReadValues() { | ||||
|         sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15); | ||||
|     Settings::values.touchscreen.diameter_y = | ||||
|         sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15); | ||||
|     Settings::values.udp_input_address = | ||||
|         sdl2_config->Get("Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR); | ||||
|     Settings::values.udp_input_port = static_cast<u16>(sdl2_config->GetInteger( | ||||
|         "Controls", "udp_input_port", InputCommon::CemuhookUDP::DEFAULT_PORT)); | ||||
|     Settings::values.udp_input_servers = | ||||
|         sdl2_config->Get("Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_SRV); | ||||
| 
 | ||||
|     std::transform(keyboard_keys.begin(), keyboard_keys.end(), | ||||
|                    Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 german
						german