mirror of
https://github.com/rock88/moonlight-nx
synced 2024-11-22 11:33:11 +00:00
Basic gamepad input
This commit is contained in:
parent
fe73134192
commit
4aeabcf113
6 changed files with 184 additions and 5 deletions
|
@ -22,6 +22,7 @@ struct MouseState {
|
||||||
|
|
||||||
struct MouseState mouse_state;
|
struct MouseState mouse_state;
|
||||||
struct GamePadState game_pad_state;
|
struct GamePadState game_pad_state;
|
||||||
|
static GLFWgamepadstate last_glfw_gamepad_state;
|
||||||
|
|
||||||
static int m_width = 1, m_height = 1;
|
static int m_width = 1, m_height = 1;
|
||||||
|
|
||||||
|
@ -130,6 +131,30 @@ void InputController::handle_gamepad_event(GLFWgamepadstate* gamepad) {
|
||||||
SET_GAME_PAD_STATE(X_FLAG, GLFW_GAMEPAD_BUTTON_X);
|
SET_GAME_PAD_STATE(X_FLAG, GLFW_GAMEPAD_BUTTON_X);
|
||||||
SET_GAME_PAD_STATE(Y_FLAG, GLFW_GAMEPAD_BUTTON_Y);
|
SET_GAME_PAD_STATE(Y_FLAG, GLFW_GAMEPAD_BUTTON_Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send to nanogui
|
||||||
|
if (gamepad->buttons != last_glfw_gamepad_state.buttons) {
|
||||||
|
for (int j = 0; j <= GLFW_GAMEPAD_BUTTON_LAST; j++) {
|
||||||
|
if (gamepad->buttons[j] == last_glfw_gamepad_state.buttons[j]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nanogui::gamepad_button_callback_event(0, j, gamepad->buttons[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gamepad->axes != last_glfw_gamepad_state.axes) {
|
||||||
|
for (int j = 0; j <= GLFW_GAMEPAD_AXIS_LAST; j++) {
|
||||||
|
if (gamepad->axes[j] == last_glfw_gamepad_state.axes[j]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nanogui::gamepad_analog_callback_event(0, j, gamepad->axes[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_glfw_gamepad_state = *gamepad;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::handle_rumple(unsigned short low_freq_motor, unsigned short high_freq_motor) {
|
void InputController::handle_rumple(unsigned short low_freq_motor, unsigned short high_freq_motor) {
|
||||||
|
|
|
@ -62,9 +62,21 @@ void Application::pop_window() {
|
||||||
m_windows.back()->set_visible(true);
|
m_windows.back()->set_visible(true);
|
||||||
update_focus(m_windows.back());
|
update_focus(m_windows.back());
|
||||||
perform_layout();
|
perform_layout();
|
||||||
}
|
|
||||||
|
if (auto w = static_cast<ContentWindow *>(m_windows.front())) {
|
||||||
if (auto w = static_cast<ContentWindow *>(m_windows.front())) {
|
w->window_appear();
|
||||||
w->window_appear();
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::gamepad_button_callback_event(int jid, int button, int action) {
|
||||||
|
if (!m_windows.empty()) {
|
||||||
|
m_windows.back()->gamepad_button_event(jid, button, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::gamepad_analog_callback_event(int jid, int axis, float value) {
|
||||||
|
if (!m_windows.empty()) {
|
||||||
|
m_windows.back()->gamepad_analog_event(jid, axis, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ public:
|
||||||
|
|
||||||
void pop_window();
|
void pop_window();
|
||||||
|
|
||||||
|
void gamepad_button_callback_event(int jid, int button, int action) override;
|
||||||
|
void gamepad_analog_callback_event(int jid, int axis, float value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Widget *> m_windows;
|
std::vector<Widget *> m_windows;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "ContentWindow.hpp"
|
#include "ContentWindow.hpp"
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
|
#include "LoadingOverlay.hpp"
|
||||||
#include "nanovg.h"
|
#include "nanovg.h"
|
||||||
|
#include <nanogui/opengl.h>
|
||||||
|
|
||||||
using namespace nanogui;
|
using namespace nanogui;
|
||||||
|
|
||||||
|
@ -74,3 +76,138 @@ void ContentWindow::set_right_title_button(int icon, const std::function<void()>
|
||||||
});
|
});
|
||||||
perform_layout();
|
perform_layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline std::vector<Widget *> selectables_child_recursive(Widget *widget) {
|
||||||
|
std::vector<Widget *> selectables;
|
||||||
|
|
||||||
|
for (auto child: widget->children()) {
|
||||||
|
if (child->selectable()) {
|
||||||
|
selectables.push_back(child);
|
||||||
|
}
|
||||||
|
auto child_selectables = selectables_child_recursive(child);
|
||||||
|
selectables.insert(selectables.end(), child_selectables.begin(), child_selectables.end());
|
||||||
|
}
|
||||||
|
return selectables;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Widget *most_closed_widget(Widget *target, std::vector<Widget *> widgets, bool left, bool right, bool up, bool down) {
|
||||||
|
if (widgets.size() < 2) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
int distanse = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
for (int i = 0; i < widgets.size(); i++) {
|
||||||
|
auto widget = widgets[i];
|
||||||
|
|
||||||
|
if (widget == target) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && widget->center().y() == target->center().y() && widget->center().x() < target->center().x()) {
|
||||||
|
int new_distanse = target->center().x() - widget->center().x();
|
||||||
|
if (new_distanse < distanse) {
|
||||||
|
distanse = new_distanse;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
} else if (right && widget->center().y() == target->center().y() && widget->center().x() > target->center().x()) {
|
||||||
|
int new_distanse = widget->center().x() - target->center().x();
|
||||||
|
if (new_distanse < distanse) {
|
||||||
|
distanse = new_distanse;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
} else if (up && widget->center().x() == target->center().x() && widget->center().y() < target->center().y()) {
|
||||||
|
int new_distanse = target->center().y() - widget->center().y();
|
||||||
|
if (new_distanse < distanse) {
|
||||||
|
distanse = new_distanse;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
} else if (down && widget->center().x() == target->center().x() && widget->center().y() > target->center().y()) {
|
||||||
|
int new_distanse = widget->center().y() - target->center().y();
|
||||||
|
if (new_distanse < distanse) {
|
||||||
|
distanse = new_distanse;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
return widgets[index];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ContentWindow::gamepad_button_event(int jid, int button, int action) {
|
||||||
|
if (!action) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MessageDialog *> messages;
|
||||||
|
std::vector<LoadingOverlay *> loaders;
|
||||||
|
|
||||||
|
for (auto child: screen()->children()) {
|
||||||
|
if (auto message = dynamic_cast<MessageDialog *>(child)) {
|
||||||
|
messages.push_back(message);
|
||||||
|
}
|
||||||
|
if (auto loader = dynamic_cast<LoadingOverlay *>(child)) {
|
||||||
|
loaders.push_back(loader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handle_button = messages.empty() && loaders.empty();
|
||||||
|
|
||||||
|
if (button == NANOGUI_GAMEPAD_BUTTON_B) {
|
||||||
|
if (!messages.empty()) {
|
||||||
|
for (auto message: messages) {
|
||||||
|
message->dispose();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loaders.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pop();
|
||||||
|
return false;
|
||||||
|
} else if (handle_button && button == NANOGUI_GAMEPAD_BUTTON_A) {
|
||||||
|
auto selectables = selectables_child_recursive(m_container);
|
||||||
|
auto current = std::find_if(selectables.begin(), selectables.end(), [](auto c) { return c->selected(); });
|
||||||
|
|
||||||
|
if (current != selectables.end()) {
|
||||||
|
auto widget = *current;
|
||||||
|
widget->mouse_button_event(widget->position() + widget->size() / 2, NANOGUI_MOUSE_BUTTON_1, 1, 0);
|
||||||
|
widget->mouse_button_event(widget->position() + widget->size() / 2, NANOGUI_MOUSE_BUTTON_1, 0, 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto selectables = selectables_child_recursive(m_container);
|
||||||
|
auto current = std::find_if(selectables.begin(), selectables.end(), [](auto c) { return c->selected(); });
|
||||||
|
|
||||||
|
if (handle_button && button >= NANOGUI_GAMEPAD_BUTTON_DPAD_UP && button <= NANOGUI_GAMEPAD_BUTTON_DPAD_LEFT) {
|
||||||
|
if (current == selectables.end()) {
|
||||||
|
selectables.front()->set_selected(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto current_selectable = *current;
|
||||||
|
auto new_selectable = most_closed_widget(
|
||||||
|
current_selectable,
|
||||||
|
selectables,
|
||||||
|
button == NANOGUI_GAMEPAD_BUTTON_DPAD_LEFT,
|
||||||
|
button == NANOGUI_GAMEPAD_BUTTON_DPAD_RIGHT,
|
||||||
|
button == NANOGUI_GAMEPAD_BUTTON_DPAD_UP,
|
||||||
|
button == NANOGUI_GAMEPAD_BUTTON_DPAD_DOWN
|
||||||
|
);
|
||||||
|
|
||||||
|
if (new_selectable) {
|
||||||
|
current_selectable->set_selected(false);
|
||||||
|
new_selectable->set_selected(true);
|
||||||
|
|
||||||
|
m_scroll->set_scroll((new_selectable->position().y() + new_selectable->height()) / m_scroll->height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ public:
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool gamepad_button_event(int jid, int button, int action) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Application* application() {
|
Application* application() {
|
||||||
auto application = static_cast<Application *>(screen());
|
auto application = static_cast<Application *>(screen());
|
||||||
|
|
2
third_party/nanogui
vendored
2
third_party/nanogui
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit ec772a923595c1d4b08156fcbf8f4631871dd642
|
Subproject commit 45d1e7539dcade92040ec406f063c73b3cdfae13
|
Loading…
Reference in a new issue