2020-11-18 05:55:09 +01:00
|
|
|
// Copyright 2020 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2+
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2021-04-15 01:07:40 +02:00
|
|
|
#include "common/settings.h"
|
2020-11-18 05:55:09 +01:00
|
|
|
#include "input_common/mouse/mouse_input.h"
|
|
|
|
|
|
|
|
namespace MouseInput {
|
|
|
|
|
|
|
|
Mouse::Mouse() {
|
|
|
|
update_thread = std::thread(&Mouse::UpdateThread, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
Mouse::~Mouse() {
|
|
|
|
update_thread_running = false;
|
|
|
|
if (update_thread.joinable()) {
|
|
|
|
update_thread.join();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mouse::UpdateThread() {
|
|
|
|
constexpr int update_time = 10;
|
|
|
|
while (update_thread_running) {
|
|
|
|
for (MouseInfo& info : mouse_info) {
|
2020-12-03 16:30:49 +01:00
|
|
|
const Common::Vec3f angular_direction{
|
|
|
|
-info.tilt_direction.y,
|
|
|
|
0.0f,
|
|
|
|
-info.tilt_direction.x,
|
|
|
|
};
|
2020-11-18 05:55:09 +01:00
|
|
|
|
|
|
|
info.motion.SetGyroscope(angular_direction * info.tilt_speed);
|
|
|
|
info.motion.UpdateRotation(update_time * 1000);
|
|
|
|
info.motion.UpdateOrientation(update_time * 1000);
|
|
|
|
info.tilt_speed = 0;
|
|
|
|
info.data.motion = info.motion.GetMotion();
|
2021-02-13 18:47:54 +01:00
|
|
|
if (Settings::values.mouse_panning) {
|
|
|
|
info.last_mouse_change *= 0.96f;
|
|
|
|
info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x),
|
|
|
|
static_cast<int>(16 * -info.last_mouse_change.y)};
|
|
|
|
}
|
2020-11-18 05:55:09 +01:00
|
|
|
}
|
|
|
|
if (configuring) {
|
|
|
|
UpdateYuzuSettings();
|
|
|
|
}
|
2021-02-13 18:47:54 +01:00
|
|
|
if (mouse_panning_timout++ > 20) {
|
2021-02-03 19:34:25 +01:00
|
|
|
StopPanning();
|
|
|
|
}
|
2020-11-18 05:55:09 +01:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mouse::UpdateYuzuSettings() {
|
2020-12-03 16:32:57 +01:00
|
|
|
if (buttons == 0) {
|
|
|
|
return;
|
2020-11-18 05:55:09 +01:00
|
|
|
}
|
2020-12-03 16:32:57 +01:00
|
|
|
|
|
|
|
mouse_queue.Push(MouseStatus{
|
|
|
|
.button = last_button,
|
|
|
|
});
|
2020-11-18 05:55:09 +01:00
|
|
|
}
|
|
|
|
|
2021-02-24 03:39:02 +01:00
|
|
|
void Mouse::PressButton(int x, int y, MouseButton button_) {
|
2020-12-03 16:30:49 +01:00
|
|
|
const auto button_index = static_cast<std::size_t>(button_);
|
|
|
|
if (button_index >= mouse_info.size()) {
|
2020-11-18 05:55:09 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 16:30:49 +01:00
|
|
|
const auto button = 1U << button_index;
|
2020-11-18 05:55:09 +01:00
|
|
|
buttons |= static_cast<u16>(button);
|
2021-02-24 03:39:02 +01:00
|
|
|
last_button = button_;
|
2020-11-18 05:55:09 +01:00
|
|
|
|
2020-12-01 00:53:43 +01:00
|
|
|
mouse_info[button_index].mouse_origin = Common::MakeVec(x, y);
|
|
|
|
mouse_info[button_index].last_mouse_position = Common::MakeVec(x, y);
|
|
|
|
mouse_info[button_index].data.pressed = true;
|
2020-11-18 05:55:09 +01:00
|
|
|
}
|
|
|
|
|
2021-02-03 19:34:25 +01:00
|
|
|
void Mouse::StopPanning() {
|
|
|
|
for (MouseInfo& info : mouse_info) {
|
|
|
|
if (Settings::values.mouse_panning) {
|
|
|
|
info.data.axis = {};
|
|
|
|
info.tilt_speed = 0;
|
|
|
|
info.last_mouse_change = {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mouse::MouseMove(int x, int y, int center_x, int center_y) {
|
2020-11-18 05:55:09 +01:00
|
|
|
for (MouseInfo& info : mouse_info) {
|
2021-02-03 19:34:25 +01:00
|
|
|
if (Settings::values.mouse_panning) {
|
2021-02-13 18:47:54 +01:00
|
|
|
auto mouse_change =
|
|
|
|
(Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
|
2021-02-03 19:34:25 +01:00
|
|
|
mouse_panning_timout = 0;
|
|
|
|
|
|
|
|
if (mouse_change.y == 0 && mouse_change.x == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-02-13 18:47:54 +01:00
|
|
|
const auto mouse_change_length = mouse_change.Length();
|
|
|
|
if (mouse_change_length < 3.0f) {
|
|
|
|
mouse_change /= mouse_change_length / 3.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
info.last_mouse_change = (info.last_mouse_change * 0.91f) + (mouse_change * 0.09f);
|
|
|
|
|
|
|
|
const auto last_mouse_change_length = info.last_mouse_change.Length();
|
|
|
|
if (last_mouse_change_length > 8.0f) {
|
|
|
|
info.last_mouse_change /= last_mouse_change_length / 8.0f;
|
|
|
|
} else if (last_mouse_change_length < 1.0f) {
|
|
|
|
info.last_mouse_change = mouse_change / mouse_change.Length();
|
|
|
|
}
|
2021-02-03 19:34:25 +01:00
|
|
|
|
|
|
|
info.tilt_direction = info.last_mouse_change;
|
|
|
|
info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-11-18 05:55:09 +01:00
|
|
|
if (info.data.pressed) {
|
2020-12-03 16:30:49 +01:00
|
|
|
const auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin;
|
|
|
|
const auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position;
|
2020-11-18 05:55:09 +01:00
|
|
|
info.last_mouse_position = Common::MakeVec(x, y);
|
|
|
|
info.data.axis = {mouse_move.x, -mouse_move.y};
|
|
|
|
|
|
|
|
if (mouse_change.x == 0 && mouse_change.y == 0) {
|
|
|
|
info.tilt_speed = 0;
|
|
|
|
} else {
|
|
|
|
info.tilt_direction = mouse_change.Cast<float>();
|
|
|
|
info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-24 03:39:02 +01:00
|
|
|
void Mouse::ReleaseButton(MouseButton button_) {
|
2020-12-03 16:30:49 +01:00
|
|
|
const auto button_index = static_cast<std::size_t>(button_);
|
|
|
|
if (button_index >= mouse_info.size()) {
|
2020-11-18 05:55:09 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-03 16:30:49 +01:00
|
|
|
const auto button = 1U << button_index;
|
2020-11-18 05:55:09 +01:00
|
|
|
buttons &= static_cast<u16>(0xFF - button);
|
|
|
|
|
2020-12-01 00:53:43 +01:00
|
|
|
mouse_info[button_index].tilt_speed = 0;
|
|
|
|
mouse_info[button_index].data.pressed = false;
|
|
|
|
mouse_info[button_index].data.axis = {0, 0};
|
2020-11-18 05:55:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Mouse::BeginConfiguration() {
|
|
|
|
buttons = 0;
|
|
|
|
last_button = MouseButton::Undefined;
|
|
|
|
mouse_queue.Clear();
|
|
|
|
configuring = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mouse::EndConfiguration() {
|
|
|
|
buttons = 0;
|
2021-02-24 03:39:02 +01:00
|
|
|
for (MouseInfo& info : mouse_info) {
|
|
|
|
info.tilt_speed = 0;
|
|
|
|
info.data.pressed = false;
|
|
|
|
info.data.axis = {0, 0};
|
|
|
|
}
|
2020-11-18 05:55:09 +01:00
|
|
|
last_button = MouseButton::Undefined;
|
|
|
|
mouse_queue.Clear();
|
|
|
|
configuring = false;
|
|
|
|
}
|
|
|
|
|
2021-03-06 20:27:02 +01:00
|
|
|
bool Mouse::ToggleButton(std::size_t button_) {
|
|
|
|
if (button_ >= mouse_info.size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const auto button = 1U << button_;
|
|
|
|
const bool button_state = (toggle_buttons & button) != 0;
|
|
|
|
const bool button_lock = (lock_buttons & button) != 0;
|
|
|
|
|
|
|
|
if (button_lock) {
|
|
|
|
return button_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
lock_buttons |= static_cast<u16>(button);
|
|
|
|
|
|
|
|
if (button_state) {
|
|
|
|
toggle_buttons &= static_cast<u16>(0xFF - button);
|
|
|
|
} else {
|
|
|
|
toggle_buttons |= static_cast<u16>(button);
|
|
|
|
}
|
|
|
|
|
|
|
|
return !button_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Mouse::UnlockButton(std::size_t button_) {
|
|
|
|
if (button_ >= mouse_info.size()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto button = 1U << button_;
|
|
|
|
const bool button_state = (toggle_buttons & button) != 0;
|
|
|
|
|
|
|
|
lock_buttons &= static_cast<u16>(0xFF - button);
|
|
|
|
|
|
|
|
return button_state;
|
|
|
|
}
|
|
|
|
|
2020-11-18 05:55:09 +01:00
|
|
|
Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() {
|
|
|
|
return mouse_queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Common::SPSCQueue<MouseStatus>& Mouse::GetMouseQueue() const {
|
|
|
|
return mouse_queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
MouseData& Mouse::GetMouseState(std::size_t button) {
|
|
|
|
return mouse_info[button].data;
|
|
|
|
}
|
|
|
|
|
|
|
|
const MouseData& Mouse::GetMouseState(std::size_t button) const {
|
|
|
|
return mouse_info[button].data;
|
|
|
|
}
|
|
|
|
} // namespace MouseInput
|