This commit is contained in:
Eddy 2026-07-06 00:40:15 +02:00 committed by GitHub
commit cc4e6c3a78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 246 additions and 3 deletions

View File

@ -88,6 +88,8 @@ add_library(CemuWxGui STATIC
input/settings/DefaultControllerSettings.h
input/settings/WiimoteControllerSettings.cpp
input/settings/WiimoteControllerSettings.h
input/settings/MouseControllerSettings.cpp
input/settings/MouseControllerSettings.h
LoggingWindow.cpp
LoggingWindow.h
MainWindow.cpp

View File

@ -1383,6 +1383,12 @@ void MainWindow::OnMouseMove(wxMouseEvent& event)
std::unique_lock lock(instance.m_main_mouse.m_mutex);
auto physPos = ToPhys(event.GetPosition());
instance.m_main_mouse.position = { physPos.x, physPos.y };
auto renderCanvasMouse = m_render_canvas->ScreenToClient(m_mouse_position);
instance.SetMousePositionInRenderBox
({
static_cast<float>(renderCanvasMouse.x) / m_render_canvas->GetClientSize().GetWidth(),
static_cast<float>(renderCanvasMouse.y) / m_render_canvas->GetClientSize().GetHeight(),
});
lock.unlock();
if (!IsFullScreen())

View File

@ -173,10 +173,23 @@ void InputAPIAddWindow::on_api_selected(wxCommandEvent& event)
m_controller_list->SetSelection(wxNOT_FOUND);
const auto selection = m_input_api->GetStringSelection();
// keyboard is a special case, as theres only one device supported atm
// keyboard and mouse are special cases, as theres only one device supported atm
bool isSingleDeviceOnly{false};
InputAPI::Type singleDeviceAPI;
if (selection == wxString::FromUTF8(to_string(InputAPI::Keyboard)))
{
const auto controllers = InputManager::instance().get_api_provider(InputAPI::Keyboard)->get_controllers();
isSingleDeviceOnly = true;
singleDeviceAPI = InputAPI::Keyboard;
}
else if (selection == wxString::FromUTF8(to_string(InputAPI::Mouse)))
{
isSingleDeviceOnly = true;
singleDeviceAPI = InputAPI::Mouse;
}
if (isSingleDeviceOnly)
{
const auto controllers = InputManager::instance().get_api_provider(singleDeviceAPI)->get_controllers();
if (!controllers.empty())
{
m_controller = controllers[0];

View File

@ -25,6 +25,7 @@
#include "wxgui/input/PairingDialog.h"
#endif
#include "input/api/Mouse/MouseController.h"
#include "wxgui/input/panels/VPADInputPanel.h"
#include "wxgui/input/panels/ProControllerInputPanel.h"
@ -35,6 +36,7 @@
#include "util/EventService.h"
#include "resource/embedded/resources.h"
#include "settings/MouseControllerSettings.h"
bool g_inputConfigWindowHasFocus = false;
@ -960,7 +962,14 @@ void InputSettings2::on_controller_settings(wxCommandEvent& event)
wnd.ShowModal();
break;
}
case InputAPI::Mouse:
{
const auto mouse_controller = std::dynamic_pointer_cast<MouseController>(controller);
wxASSERT(mouse_controller);
MouseControllerSettings wnd(this, wxGetMousePosition() + wxSize(5, 5), mouse_controller);
wnd.ShowModal();
break;
}
case InputAPI::Keyboard: break;
#ifdef SUPPORTS_WIIMOTE

View File

@ -0,0 +1,72 @@
#include "MouseControllerSettings.h"
#include "input/api/Mouse/MouseController.h"
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/statbox.h>
#include "wxgui/helpers/wxHelpers.h"
#include "wxgui/input/InputAPIAddWindow.h"
MouseControllerSettings::MouseControllerSettings(wxWindow* parent, const wxPoint& position, std::shared_ptr<MouseController> controller)
: wxDialog(parent, wxID_ANY, _("Controller settings"), position, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE), m_controller(std::move(controller))
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
auto* sizer = new wxBoxSizer(wxVERTICAL);
// options
{
auto* box = new wxStaticBox(this, wxID_ANY, _("Options"));
auto* box_sizer = new wxStaticBoxSizer(box, wxVERTICAL);
// Position (wiimote pointer)
m_usePosition = new wxCheckBox(box, wxID_ANY, _("Use position"));
m_usePosition->SetValue(m_controller->IsPositionEnabled());
m_usePosition->Enable(m_controller->has_position());
box_sizer->Add(m_usePosition, 0, wxEXPAND | wxALL, 5);
sizer->Add(box_sizer, 1, wxALL|wxEXPAND, 5);
}
{
auto* control_sizer = new wxFlexGridSizer(0, 3, 0, 0);
control_sizer->AddGrowableCol(2);
auto* ok_button = new wxButton(this, wxID_ANY, _("OK"));
ok_button->Bind(wxEVT_BUTTON, [this](auto&) { UpdateSettings(); EndModal(wxID_OK); });
control_sizer->Add(ok_button, 0, wxALL, 5);
control_sizer->Add(0, 0, 0, wxEXPAND, 5);
auto* cancel_button = new wxButton(this, wxID_ANY, _("Cancel"));
cancel_button->Bind(wxEVT_BUTTON, [this](auto&) { EndModal(wxID_CANCEL); });
control_sizer->Add(cancel_button, 0, wxALL, 5);
sizer->Add(control_sizer, 0, wxEXPAND, 5);
}
this->SetSizer(sizer);
this->Layout();
this->Fit();
this->Bind(wxEVT_CLOSE_WINDOW, &MouseControllerSettings::OnClose, this);
}
void MouseControllerSettings::UpdateSettings()
{
if (m_usePosition)
m_controller->SetPositionEnabled(m_usePosition->GetValue());
}
void MouseControllerSettings::OnClose(wxCloseEvent& event)
{
if (this->GetReturnCode() == 0 || this->GetReturnCode() == wxID_OK)
UpdateSettings();
event.Skip();
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "input/api/Controller.h"
#include "wx/dialog.h"
#include <memory>
class wxCheckBox;
class wxPoint;
class wxWindow;
class MouseController;
class MouseControllerSettings : public wxDialog
{
public:
MouseControllerSettings(wxWindow* parent, const wxPoint& position, std::shared_ptr<MouseController> controller);
private:
std::shared_ptr<MouseController> m_controller;
wxCheckBox* m_usePosition = nullptr;
void UpdateSettings();
void OnClose(wxCloseEvent& event);
};

View File

@ -19,6 +19,10 @@ add_library(CemuInput
api/Keyboard/KeyboardControllerProvider.cpp
api/Keyboard/KeyboardController.cpp
api/Keyboard/KeyboardController.h
api/Mouse/MouseControllerProvider.h
api/Mouse/MouseControllerProvider.cpp
api/Mouse/MouseController.cpp
api/Mouse/MouseController.h
emulated/ProController.cpp
emulated/EmulatedController.h
emulated/EmulatedController.cpp

View File

@ -1,5 +1,6 @@
#include "input/ControllerFactory.h"
#include "api/Mouse/MouseController.h"
#include "input/emulated/VPADController.h"
#include "input/emulated/ProController.h"
#include "input/emulated/ClassicController.h"
@ -31,6 +32,10 @@ ControllerPtr ControllerFactory::CreateController(InputAPI::Type api, std::strin
case InputAPI::Keyboard:
return std::make_shared<KeyboardController>();
#endif
#if HAS_MOUSE
case InputAPI::Mouse:
return std::make_shared<MouseController>();
#endif
#if HAS_DIRECTINPUT
case InputAPI::DirectInput:
{

View File

@ -5,6 +5,7 @@
#include <pugixml.hpp>
#include "Cafe/GameProfile/GameProfile.h"
#include "util/EventService.h"
#include "input/api/Mouse/MouseControllerProvider.h"
InputManager::InputManager()
{
@ -28,6 +29,9 @@ InputManager::InputManager()
#if HAS_KEYBOARD
create_provider<KeyboardControllerProvider>();
#endif
#if HAS_MOUSE
create_provider<MouseControllerProvider>();
#endif
#ifdef HAS_SDL
create_provider<SDLControllerProvider>();
#endif
@ -233,6 +237,8 @@ bool InputManager::migrate_config(const fs::path& file_path)
std::string uuid;
if (api_string == to_string(InputAPI::Keyboard))
uuid = to_string(InputAPI::Keyboard);
else if (api_string == to_string(InputAPI::Mouse))
uuid = to_string(InputAPI::Mouse);
else
{
if (!uuid_opt)
@ -928,6 +934,16 @@ std::optional<glm::ivec2> InputManager::get_right_down_mouse_info(bool* is_pad)
return {};
}
glm::vec2 InputManager::GetMousePositionInRenderBox() const
{
return m_mouseInRenderCanvas;
}
void InputManager::SetMousePositionInRenderBox(glm::vec2 newMousePosition)
{
m_mouseInRenderCanvas = newMousePosition;
}
void InputManager::update_thread()
{
SetThreadName("Input_update");

View File

@ -91,10 +91,17 @@ public:
glm::ivec2 get_mouse_position(bool pad_window) const;
std::optional<glm::ivec2> get_left_down_mouse_info(bool* is_pad);
std::optional<glm::ivec2> get_right_down_mouse_info(bool* is_pad);
// Returns the mouse position relative to the render canvas (see MainWindow::m_render_canvas).
// (0, 0) is up left; (1, 1) is down right. The values may be negative or above 1 if the mouse cursor
// is outside the render canvas. At the time of writing this, it is used only for mouse-to-wiimote pointer feature.
glm::vec2 GetMousePositionInRenderBox() const;
void SetMousePositionInRenderBox(glm::vec2 newMousePosition);
std::atomic<float> m_mouse_wheel;
private:
glm::vec2 m_mouseInRenderCanvas{};
void update_thread();
std::thread m_update_thread;

View File

@ -7,6 +7,7 @@ namespace InputAPI
enum Type
{
Keyboard,
Mouse,
SDLController,
XInput,
DirectInput,
@ -26,6 +27,8 @@ namespace InputAPI
{
case Keyboard:
return "Keyboard";
case Mouse:
return "Mouse";
case DirectInput:
return "DirectInput";
case XInput:
@ -53,6 +56,8 @@ namespace InputAPI
{
if (str == to_string(Keyboard))
return Keyboard;
else if (str == to_string(Mouse))
return Mouse;
else if (str == to_string(DirectInput))
return DirectInput;
else if (str == to_string(XInput))

View File

@ -0,0 +1,26 @@
#include "MouseController.h"
#include "input/api/Controller.h"
std::string_view MouseController::api_name() const
{
static_assert(to_string(InputAPI::Mouse) == "Mouse");
return to_string(InputAPI::Mouse);
}
MouseController& MouseController::SetPositionEnabled(bool value)
{
m_isPositionEnabled = value;
return *this;
}
glm::vec2 MouseController::get_position()
{
return InputManager::instance().GetMousePositionInRenderBox();
}
PositionVisibility MouseController::GetPositionVisibility()
{
return IsPositionEnabled()
? PositionVisibility::FULL
: PositionVisibility::NONE;
}

View File

@ -0,0 +1,26 @@
#pragma once
#include "MouseControllerProvider.h"
#include "input/api/Controller.h"
class MouseController : public Controller<MouseControllerProvider>
{
public:
MouseController() : base_type("mouse", "Mouse") {}
std::string_view api_name() const override;
InputAPI::Type api() const override { return InputAPI::Mouse; }
bool is_connected() override { return true; }
ControllerState raw_state() override { return {}; }
bool has_position() override { return true; }
bool IsPositionEnabled() const { return m_isPositionEnabled; }
MouseController& SetPositionEnabled(bool value);
glm::vec2 get_position() override;
PositionVisibility GetPositionVisibility() override;
private:
bool m_isPositionEnabled = false;
};

View File

@ -0,0 +1,10 @@
#include "MouseControllerProvider.h"
#include "MouseController.h"
std::vector<std::shared_ptr<ControllerBase>> MouseControllerProvider::get_controllers()
{
std::vector<std::shared_ptr<ControllerBase>> result;
result.emplace_back(std::make_shared<MouseController>());
return result;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "input/api/ControllerProvider.h"
#ifndef HAS_MOUSE
#define HAS_MOUSE 1
#endif
class MouseControllerProvider : public ControllerProviderBase
{
public:
inline static InputAPI::Type kAPIType = InputAPI::Mouse;
InputAPI::Type api() const override { return kAPIType; }
std::vector<std::shared_ptr<ControllerBase>> get_controllers() override;
};