mirror of
https://github.com/rock88/moonlight-nx
synced 2024-11-26 05:20:24 +00:00
Rewrite controls
This commit is contained in:
parent
7688adcc3f
commit
11d54f819f
13 changed files with 359 additions and 307 deletions
2
Makefile
2
Makefile
|
@ -114,7 +114,7 @@ MOONLIGHT_LIBRETRO_CXX_SOURCES = \
|
||||||
src/ui/LoadingOverlay.cpp \
|
src/ui/LoadingOverlay.cpp \
|
||||||
src/GameStreamClient.cpp \
|
src/GameStreamClient.cpp \
|
||||||
src/Settings.cpp \
|
src/Settings.cpp \
|
||||||
src/moonlight_libretro_wrapper.cpp
|
src/InputController.cpp
|
||||||
|
|
||||||
MOONLIGHT_COMMON_C_SOURCES = \
|
MOONLIGHT_COMMON_C_SOURCES = \
|
||||||
third_party/moonlight-common-c/enet/callbacks.c \
|
third_party/moonlight-common-c/enet/callbacks.c \
|
||||||
|
|
|
@ -58,7 +58,7 @@ static EVP_PKEY *privateKey;
|
||||||
|
|
||||||
const char* gs_error;
|
const char* gs_error;
|
||||||
|
|
||||||
static int mkdirtree(const char* directory) {
|
int mkdirtree(const char* directory) {
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
char* p = buffer;
|
char* p = buffer;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
3602C3B7245D903000368900 /* HostButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3B5245D903000368900 /* HostButton.cpp */; };
|
3602C3B7245D903000368900 /* HostButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3B5245D903000368900 /* HostButton.cpp */; };
|
||||||
3602C3BA245DB3C800368900 /* AppListWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3B8245DB3C800368900 /* AppListWindow.cpp */; };
|
3602C3BA245DB3C800368900 /* AppListWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3B8245DB3C800368900 /* AppListWindow.cpp */; };
|
||||||
3602C3BD245DBA9100368900 /* AppButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3BB245DBA9100368900 /* AppButton.cpp */; };
|
3602C3BD245DBA9100368900 /* AppButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3602C3BB245DBA9100368900 /* AppButton.cpp */; };
|
||||||
361F8A3A245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 361F8A38245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp */; };
|
3603E93C246316400051287D /* InputController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3603E93A246316400051287D /* InputController.cpp */; };
|
||||||
3652EFCD245B3B00001FABF3 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF0F245B3B00001FABF3 /* widget.cpp */; };
|
3652EFCD245B3B00001FABF3 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF0F245B3B00001FABF3 /* widget.cpp */; };
|
||||||
3652EFCE245B3B00001FABF3 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF10245B3B00001FABF3 /* common.cpp */; };
|
3652EFCE245B3B00001FABF3 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF10245B3B00001FABF3 /* common.cpp */; };
|
||||||
3652EFCF245B3B00001FABF3 /* checkbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF11245B3B00001FABF3 /* checkbox.cpp */; };
|
3652EFCF245B3B00001FABF3 /* checkbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652EF11245B3B00001FABF3 /* checkbox.cpp */; };
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
3652F07F245C292B001FABF3 /* LinkedBlockingQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F062245C292B001FABF3 /* LinkedBlockingQueue.c */; };
|
3652F07F245C292B001FABF3 /* LinkedBlockingQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F062245C292B001FABF3 /* LinkedBlockingQueue.c */; };
|
||||||
3652F080245C292B001FABF3 /* ByteBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F064245C292B001FABF3 /* ByteBuffer.c */; };
|
3652F080245C292B001FABF3 /* ByteBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F064245C292B001FABF3 /* ByteBuffer.c */; };
|
||||||
3652F083245C60D1001FABF3 /* LoadingOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F081245C60D1001FABF3 /* LoadingOverlay.cpp */; };
|
3652F083245C60D1001FABF3 /* LoadingOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F081245C60D1001FABF3 /* LoadingOverlay.cpp */; };
|
||||||
3652F086245C6CFC001FABF3 /* moonlight_libretro.c in Sources */ = {isa = PBXBuildFile; fileRef = 3652F085245C6CFC001FABF3 /* moonlight_libretro.c */; };
|
3652F086245C6CFC001FABF3 /* moonlight_libretro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F085245C6CFC001FABF3 /* moonlight_libretro.cpp */; };
|
||||||
3652F08A245C8569001FABF3 /* ContentWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F089245C8569001FABF3 /* ContentWindow.cpp */; };
|
3652F08A245C8569001FABF3 /* ContentWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3652F089245C8569001FABF3 /* ContentWindow.cpp */; };
|
||||||
367CD95A245DE25F00A95738 /* StreamWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 367CD958245DE25F00A95738 /* StreamWindow.cpp */; };
|
367CD95A245DE25F00A95738 /* StreamWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 367CD958245DE25F00A95738 /* StreamWindow.cpp */; };
|
||||||
36A0C0372461DBA30083289C /* AddHostButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A0C0352461DBA30083289C /* AddHostButton.cpp */; };
|
36A0C0372461DBA30083289C /* AddHostButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A0C0352461DBA30083289C /* AddHostButton.cpp */; };
|
||||||
|
@ -122,8 +122,8 @@
|
||||||
3602C3BB245DBA9100368900 /* AppButton.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppButton.cpp; sourceTree = "<group>"; };
|
3602C3BB245DBA9100368900 /* AppButton.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AppButton.cpp; sourceTree = "<group>"; };
|
||||||
3602C3BC245DBA9100368900 /* AppButton.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AppButton.hpp; sourceTree = "<group>"; };
|
3602C3BC245DBA9100368900 /* AppButton.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AppButton.hpp; sourceTree = "<group>"; };
|
||||||
3602C3C0245DC7E300368900 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
3602C3C0245DC7E300368900 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||||
361F8A38245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = moonlight_libretro_wrapper.cpp; sourceTree = "<group>"; };
|
3603E93A246316400051287D /* InputController.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InputController.cpp; sourceTree = "<group>"; };
|
||||||
361F8A39245CB44E00A8D9C0 /* moonlight_libretro_wrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = moonlight_libretro_wrapper.h; sourceTree = "<group>"; };
|
3603E93B246316400051287D /* InputController.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = InputController.hpp; sourceTree = "<group>"; };
|
||||||
3652ECE8245B3AFF001FABF3 /* colorpicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorpicker.h; sourceTree = "<group>"; };
|
3652ECE8245B3AFF001FABF3 /* colorpicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorpicker.h; sourceTree = "<group>"; };
|
||||||
3652ECE9245B3AFF001FABF3 /* renderpass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = renderpass.h; sourceTree = "<group>"; };
|
3652ECE9245B3AFF001FABF3 /* renderpass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = renderpass.h; sourceTree = "<group>"; };
|
||||||
3652ECEA245B3AFF001FABF3 /* theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = theme.h; sourceTree = "<group>"; };
|
3652ECEA245B3AFF001FABF3 /* theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = theme.h; sourceTree = "<group>"; };
|
||||||
|
@ -272,7 +272,7 @@
|
||||||
3652F081245C60D1001FABF3 /* LoadingOverlay.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LoadingOverlay.cpp; sourceTree = "<group>"; };
|
3652F081245C60D1001FABF3 /* LoadingOverlay.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LoadingOverlay.cpp; sourceTree = "<group>"; };
|
||||||
3652F082245C60D1001FABF3 /* LoadingOverlay.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LoadingOverlay.hpp; sourceTree = "<group>"; };
|
3652F082245C60D1001FABF3 /* LoadingOverlay.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LoadingOverlay.hpp; sourceTree = "<group>"; };
|
||||||
3652F084245C6CFC001FABF3 /* libretro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libretro.h; sourceTree = "<group>"; };
|
3652F084245C6CFC001FABF3 /* libretro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libretro.h; sourceTree = "<group>"; };
|
||||||
3652F085245C6CFC001FABF3 /* moonlight_libretro.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = moonlight_libretro.c; sourceTree = "<group>"; };
|
3652F085245C6CFC001FABF3 /* moonlight_libretro.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moonlight_libretro.cpp; sourceTree = "<group>"; };
|
||||||
3652F089245C8569001FABF3 /* ContentWindow.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ContentWindow.cpp; sourceTree = "<group>"; };
|
3652F089245C8569001FABF3 /* ContentWindow.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ContentWindow.cpp; sourceTree = "<group>"; };
|
||||||
367CD958245DE25F00A95738 /* StreamWindow.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StreamWindow.cpp; sourceTree = "<group>"; };
|
367CD958245DE25F00A95738 /* StreamWindow.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StreamWindow.cpp; sourceTree = "<group>"; };
|
||||||
367CD959245DE25F00A95738 /* StreamWindow.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StreamWindow.hpp; sourceTree = "<group>"; };
|
367CD959245DE25F00A95738 /* StreamWindow.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StreamWindow.hpp; sourceTree = "<group>"; };
|
||||||
|
@ -634,10 +634,10 @@
|
||||||
3652F004245C28C6001FABF3 /* GameStreamClient.hpp */,
|
3652F004245C28C6001FABF3 /* GameStreamClient.hpp */,
|
||||||
36A0C03B2461F03C0083289C /* Settings.cpp */,
|
36A0C03B2461F03C0083289C /* Settings.cpp */,
|
||||||
36A0C03C2461F03C0083289C /* Settings.hpp */,
|
36A0C03C2461F03C0083289C /* Settings.hpp */,
|
||||||
|
3603E93A246316400051287D /* InputController.cpp */,
|
||||||
|
3603E93B246316400051287D /* InputController.hpp */,
|
||||||
3652F084245C6CFC001FABF3 /* libretro.h */,
|
3652F084245C6CFC001FABF3 /* libretro.h */,
|
||||||
361F8A39245CB44E00A8D9C0 /* moonlight_libretro_wrapper.h */,
|
3652F085245C6CFC001FABF3 /* moonlight_libretro.cpp */,
|
||||||
361F8A38245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp */,
|
|
||||||
3652F085245C6CFC001FABF3 /* moonlight_libretro.c */,
|
|
||||||
36B406962459F460005BD903 /* moonlight_glfw.cpp */,
|
36B406962459F460005BD903 /* moonlight_glfw.cpp */,
|
||||||
);
|
);
|
||||||
path = src;
|
path = src;
|
||||||
|
@ -806,7 +806,6 @@
|
||||||
3652F075245C292B001FABF3 /* VideoStream.c in Sources */,
|
3652F075245C292B001FABF3 /* VideoStream.c in Sources */,
|
||||||
3652EFE0245B3B00001FABF3 /* imageview.cpp in Sources */,
|
3652EFE0245B3B00001FABF3 /* imageview.cpp in Sources */,
|
||||||
3652EFDB245B3B00001FABF3 /* texture.cpp in Sources */,
|
3652EFDB245B3B00001FABF3 /* texture.cpp in Sources */,
|
||||||
361F8A3A245CB44E00A8D9C0 /* moonlight_libretro_wrapper.cpp in Sources */,
|
|
||||||
36A0C03D2461F03C0083289C /* Settings.cpp in Sources */,
|
36A0C03D2461F03C0083289C /* Settings.cpp in Sources */,
|
||||||
3652F079245C292B001FABF3 /* RtpReorderQueue.c in Sources */,
|
3652F079245C292B001FABF3 /* RtpReorderQueue.c in Sources */,
|
||||||
3652F065245C292B001FABF3 /* list.c in Sources */,
|
3652F065245C292B001FABF3 /* list.c in Sources */,
|
||||||
|
@ -814,7 +813,7 @@
|
||||||
36DFE217245A278700FC51CE /* glsym_gl.c in Sources */,
|
36DFE217245A278700FC51CE /* glsym_gl.c in Sources */,
|
||||||
3652F06A245C292B001FABF3 /* protocol.c in Sources */,
|
3652F06A245C292B001FABF3 /* protocol.c in Sources */,
|
||||||
3652EFFC245B6434001FABF3 /* MainWindow.cpp in Sources */,
|
3652EFFC245B6434001FABF3 /* MainWindow.cpp in Sources */,
|
||||||
3652F086245C6CFC001FABF3 /* moonlight_libretro.c in Sources */,
|
3652F086245C6CFC001FABF3 /* moonlight_libretro.cpp in Sources */,
|
||||||
3652EFD3245B3B00001FABF3 /* button.cpp in Sources */,
|
3652EFD3245B3B00001FABF3 /* button.cpp in Sources */,
|
||||||
3652EFE6245B3B00001FABF3 /* traits.cpp in Sources */,
|
3652EFE6245B3B00001FABF3 /* traits.cpp in Sources */,
|
||||||
3652EFDE245B3B00001FABF3 /* tabwidget.cpp in Sources */,
|
3652EFDE245B3B00001FABF3 /* tabwidget.cpp in Sources */,
|
||||||
|
@ -876,6 +875,7 @@
|
||||||
3652F011245C2919001FABF3 /* client.c in Sources */,
|
3652F011245C2919001FABF3 /* client.c in Sources */,
|
||||||
3652EFE4245B3B00001FABF3 /* combobox.cpp in Sources */,
|
3652EFE4245B3B00001FABF3 /* combobox.cpp in Sources */,
|
||||||
36A56313245F194000901354 /* gl_render.c in Sources */,
|
36A56313245F194000901354 /* gl_render.c in Sources */,
|
||||||
|
3603E93C246316400051287D /* InputController.cpp in Sources */,
|
||||||
3652EFF2245B3B00001FABF3 /* textbox.cpp in Sources */,
|
3652EFF2245B3B00001FABF3 /* textbox.cpp in Sources */,
|
||||||
3652F074245C292B001FABF3 /* Platform.c in Sources */,
|
3652F074245C292B001FABF3 /* Platform.c in Sources */,
|
||||||
3652EFCD245B3B00001FABF3 /* widget.cpp in Sources */,
|
3652EFCD245B3B00001FABF3 /* widget.cpp in Sources */,
|
||||||
|
|
162
src/InputController.cpp
Normal file
162
src/InputController.cpp
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
#include "InputController.hpp"
|
||||||
|
#include "Settings.hpp"
|
||||||
|
#include "Limelight.h"
|
||||||
|
#include "libretro.h"
|
||||||
|
#include "Limelight.h"
|
||||||
|
#include <nanogui/nanogui.h>
|
||||||
|
#include <nanogui/opengl.h>
|
||||||
|
|
||||||
|
extern retro_input_state_t input_state_cb;
|
||||||
|
|
||||||
|
int16_t keyboard_state[RETROK_LAST];
|
||||||
|
struct MouseState mouse_state;
|
||||||
|
struct GamePadState game_pad_state;
|
||||||
|
|
||||||
|
static int m_width = 1, m_height = 1;
|
||||||
|
|
||||||
|
void InputController::handle_mouse(int width, int height) {
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
|
||||||
|
int mouse_l_press = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
|
||||||
|
int mouse_r_press = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT);
|
||||||
|
|
||||||
|
int mouse_x = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
|
||||||
|
int mouse_y = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
|
||||||
|
int pointer_x = 0, pointer_y = 0;
|
||||||
|
|
||||||
|
// TODO: Pointer on macOS currently broken
|
||||||
|
// https://github.com/libretro/RetroArch/issues/10168
|
||||||
|
if (input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED)) {
|
||||||
|
pointer_x = (input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X) + 0x7fff) * width / 0xffff;
|
||||||
|
pointer_y = (input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y) + 0x7fff) * height / 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __LAKKA_SWITCH__
|
||||||
|
if (mouse_x != 0 && mouse_y != 0) {
|
||||||
|
mouse_state.x = mouse_x;
|
||||||
|
mouse_state.y = mouse_y;
|
||||||
|
nanogui::cursor_pos_callback_event(mouse_x, mouse_y);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (mouse_l_press && pointer_x != 0 && pointer_y != 0) {
|
||||||
|
mouse_state.x = pointer_x;
|
||||||
|
mouse_state.y = pointer_y;
|
||||||
|
nanogui::cursor_pos_callback_event(pointer_x, pointer_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mouse_state.l_press && mouse_l_press) {
|
||||||
|
mouse_state.l_press = true;
|
||||||
|
nanogui::mouse_button_callback_event(NANOGUI_MOUSE_BUTTON_1, NANOGUI_PRESS, 0);
|
||||||
|
} else if (mouse_state.l_press && !mouse_l_press) {
|
||||||
|
mouse_state.l_press = false;
|
||||||
|
nanogui::mouse_button_callback_event(NANOGUI_MOUSE_BUTTON_1, NANOGUI_RELEASE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mouse_state.r_press && mouse_r_press) {
|
||||||
|
mouse_state.r_press = true;
|
||||||
|
nanogui::mouse_button_callback_event(NANOGUI_MOUSE_BUTTON_2, NANOGUI_PRESS, 0);
|
||||||
|
} else if (mouse_state.r_press && !mouse_r_press) {
|
||||||
|
mouse_state.r_press = false;
|
||||||
|
nanogui::mouse_button_callback_event(NANOGUI_MOUSE_BUTTON_2, NANOGUI_RELEASE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputController::handle_keyboard() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputController::handle_game_pad() {
|
||||||
|
game_pad_state.leftTrigger = 0xFFFF * input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2);
|
||||||
|
game_pad_state.rightTrigger = 0xFFFF * input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
|
||||||
|
|
||||||
|
game_pad_state.leftStickX = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
|
||||||
|
game_pad_state.leftStickY = 0xFFFF - input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y);
|
||||||
|
game_pad_state.rightStickX = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);
|
||||||
|
game_pad_state.rightStickY = 0xFFFF - input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
|
||||||
|
|
||||||
|
#define SET_GAME_PAD_STATE(LIMELIGHT_KEY, RETRO_KEY) \
|
||||||
|
input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_KEY) ? (game_pad_state.buttonFlags |= LIMELIGHT_KEY) : (game_pad_state.buttonFlags &= ~LIMELIGHT_KEY);
|
||||||
|
|
||||||
|
SET_GAME_PAD_STATE(UP_FLAG, RETRO_DEVICE_ID_JOYPAD_UP);
|
||||||
|
SET_GAME_PAD_STATE(DOWN_FLAG, RETRO_DEVICE_ID_JOYPAD_DOWN);
|
||||||
|
SET_GAME_PAD_STATE(LEFT_FLAG, RETRO_DEVICE_ID_JOYPAD_LEFT);
|
||||||
|
SET_GAME_PAD_STATE(RIGHT_FLAG, RETRO_DEVICE_ID_JOYPAD_RIGHT);
|
||||||
|
|
||||||
|
SET_GAME_PAD_STATE(BACK_FLAG, RETRO_DEVICE_ID_JOYPAD_SELECT);
|
||||||
|
SET_GAME_PAD_STATE(PLAY_FLAG, RETRO_DEVICE_ID_JOYPAD_START);
|
||||||
|
|
||||||
|
SET_GAME_PAD_STATE(LB_FLAG, RETRO_DEVICE_ID_JOYPAD_L);
|
||||||
|
SET_GAME_PAD_STATE(RB_FLAG, RETRO_DEVICE_ID_JOYPAD_R);
|
||||||
|
|
||||||
|
SET_GAME_PAD_STATE(LS_CLK_FLAG, RETRO_DEVICE_ID_JOYPAD_L3);
|
||||||
|
SET_GAME_PAD_STATE(RS_CLK_FLAG, RETRO_DEVICE_ID_JOYPAD_R3);
|
||||||
|
|
||||||
|
if (Settings::settings()->swap_ab_xy()) {
|
||||||
|
SET_GAME_PAD_STATE(A_FLAG, RETRO_DEVICE_ID_JOYPAD_B);
|
||||||
|
SET_GAME_PAD_STATE(B_FLAG, RETRO_DEVICE_ID_JOYPAD_A);
|
||||||
|
SET_GAME_PAD_STATE(X_FLAG, RETRO_DEVICE_ID_JOYPAD_Y);
|
||||||
|
SET_GAME_PAD_STATE(Y_FLAG, RETRO_DEVICE_ID_JOYPAD_X);
|
||||||
|
} else {
|
||||||
|
SET_GAME_PAD_STATE(A_FLAG, RETRO_DEVICE_ID_JOYPAD_A);
|
||||||
|
SET_GAME_PAD_STATE(B_FLAG, RETRO_DEVICE_ID_JOYPAD_B);
|
||||||
|
SET_GAME_PAD_STATE(X_FLAG, RETRO_DEVICE_ID_JOYPAD_X);
|
||||||
|
SET_GAME_PAD_STATE(Y_FLAG, RETRO_DEVICE_ID_JOYPAD_Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputController::send_to_stream() {
|
||||||
|
#if defined(__LAKKA_SWITCH__)
|
||||||
|
static int mouse_x = mouse_state.x, mouse_y = mouse_state.y;
|
||||||
|
static int last_mouse_x = mouse_state.x, last_mouse_y = mouse_state.y;
|
||||||
|
|
||||||
|
bool move_mouse = (game_pad_state.leftTrigger == 0) && (game_pad_state.rightTrigger == 0);
|
||||||
|
|
||||||
|
if (move_mouse) {
|
||||||
|
mouse_x = std::min(std::max(mouse_x + mouse_state.x - last_mouse_x, 0), m_width);
|
||||||
|
mouse_y = std::min(std::max(mouse_y + mouse_state.y - last_mouse_y, 0), m_height);
|
||||||
|
|
||||||
|
LiSendMousePositionEvent(mouse_x, mouse_y, m_width, m_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_mouse_x = mouse_state.x;
|
||||||
|
last_mouse_y = mouse_state.y;
|
||||||
|
|
||||||
|
if (mouse_state.l_press && ((game_pad_state.buttonFlags & LB_FLAG) || game_pad_state.leftTrigger)) {
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
|
} else {
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse_state.l_press && ((game_pad_state.buttonFlags & RB_FLAG) || game_pad_state.rightTrigger)) {
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
||||||
|
} else {
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
LiSendMousePositionEvent(mouse_state.x, mouse_state.y, m_width, m_height);
|
||||||
|
LiSendMouseButtonEvent(mouse_state.l_press ? BUTTON_ACTION_PRESS : BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
LiSendMouseButtonEvent(mouse_state.r_press ? BUTTON_ACTION_PRESS : BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool send_alt_enter = false;
|
||||||
|
|
||||||
|
if (!send_alt_enter && GAME_PAD_COMBO(LEFT_FLAG)) {
|
||||||
|
send_alt_enter = true;
|
||||||
|
LiSendKeyboardEvent(0x0D, KEY_ACTION_DOWN, MODIFIER_ALT);
|
||||||
|
} else if (send_alt_enter && !GAME_PAD_COMBO(LEFT_FLAG)) {
|
||||||
|
send_alt_enter = false;
|
||||||
|
LiSendKeyboardEvent(0x0D, KEY_ACTION_UP, MODIFIER_ALT);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiSendControllerEvent(
|
||||||
|
game_pad_state.buttonFlags,
|
||||||
|
game_pad_state.leftTrigger,
|
||||||
|
game_pad_state.rightTrigger,
|
||||||
|
game_pad_state.leftStickX,
|
||||||
|
game_pad_state.leftStickY,
|
||||||
|
game_pad_state.rightStickX,
|
||||||
|
game_pad_state.rightStickY
|
||||||
|
);
|
||||||
|
}
|
52
src/InputController.hpp
Normal file
52
src/InputController.hpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
extern int16_t keyboard_state[];
|
||||||
|
|
||||||
|
struct MouseState {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
bool l_press;
|
||||||
|
bool r_press;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct MouseState mouse_state;
|
||||||
|
|
||||||
|
struct GamePadState {
|
||||||
|
short buttonFlags;
|
||||||
|
unsigned char leftTrigger;
|
||||||
|
unsigned char rightTrigger;
|
||||||
|
short leftStickX;
|
||||||
|
short leftStickY;
|
||||||
|
short rightStickX;
|
||||||
|
short rightStickY;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct GamePadState game_pad_state;
|
||||||
|
|
||||||
|
#define GAME_PAD_COMBO(KEY) \
|
||||||
|
((game_pad_state.buttonFlags & LB_FLAG) && (game_pad_state.buttonFlags & RB_FLAG) && (game_pad_state.buttonFlags & KEY))
|
||||||
|
|
||||||
|
class InputController {
|
||||||
|
public:
|
||||||
|
static InputController* controller() {
|
||||||
|
static InputController controller;
|
||||||
|
return &controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_input(int width, int height) {
|
||||||
|
handle_mouse(width, height);
|
||||||
|
handle_keyboard();
|
||||||
|
handle_game_pad();
|
||||||
|
};
|
||||||
|
|
||||||
|
void send_to_stream();
|
||||||
|
|
||||||
|
private:
|
||||||
|
InputController() {};
|
||||||
|
|
||||||
|
void handle_mouse(int width, int height);
|
||||||
|
void handle_keyboard();
|
||||||
|
void handle_game_pad();
|
||||||
|
};
|
|
@ -4,8 +4,14 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#define TRY_JSON(x) try { \
|
extern "C" {
|
||||||
x; } catch (const std::exception &e) {}
|
int mkdirtree(const char* directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define JSON_GET_VALUE(to, json, check, type) \
|
||||||
|
if (json.check()) { \
|
||||||
|
to = json.get<type>(); \
|
||||||
|
}
|
||||||
|
|
||||||
void Settings::add_host(const std::string address) {
|
void Settings::add_host(const std::string address) {
|
||||||
if (std::find(m_hosts.begin(), m_hosts.end(), address) == m_hosts.end()) {
|
if (std::find(m_hosts.begin(), m_hosts.end(), address) == m_hosts.end()) {
|
||||||
|
@ -24,14 +30,17 @@ void Settings::load() {
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
stream >> json;
|
stream >> json;
|
||||||
|
|
||||||
TRY_JSON(m_hosts = json["hosts"].get<std::vector<std::string>>());
|
JSON_GET_VALUE(m_hosts, json["hosts"], is_array, std::vector<std::string>);
|
||||||
TRY_JSON(m_resolution = json["settings"]["resolution"].get<int>());
|
JSON_GET_VALUE(m_resolution, json["settings"]["resolution"], is_number_integer, int);
|
||||||
TRY_JSON(m_fps = json["settings"]["fps"].get<int>());
|
JSON_GET_VALUE(m_fps, json["settings"]["fps"], is_number_integer, int);
|
||||||
TRY_JSON(m_bitrate = json["settings"]["bitrate"].get<int>());
|
JSON_GET_VALUE(m_bitrate, json["settings"]["bitrate"], is_number_integer, int);
|
||||||
TRY_JSON(m_swap_ab_xy = json["settings"]["swap_ab_xy"].get<bool>());
|
JSON_GET_VALUE(m_swap_ab_xy, json["settings"]["swap_ab_xy"], is_number_integer, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::save() {
|
void Settings::save() {
|
||||||
|
try {
|
||||||
|
mkdirtree(m_working_dir.c_str());
|
||||||
|
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
|
|
||||||
json["hosts"] = m_hosts;
|
json["hosts"] = m_hosts;
|
||||||
|
@ -44,4 +53,7 @@ void Settings::save() {
|
||||||
|
|
||||||
std::ofstream stream(m_working_dir + "/settings.json");
|
std::ofstream stream(m_working_dir + "/settings.json");
|
||||||
stream << std::setw(4) << json << std::endl;
|
stream << std::setw(4) << json << std::endl;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
printf("Save settings error: %s\n", e.what());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_working_dir(std::string working_dir) {
|
void set_working_dir(std::string working_dir) {
|
||||||
m_working_dir = working_dir + "/moonlight";
|
m_working_dir = std::string(working_dir + "/moonlight");
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,51 @@
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "Settings.hpp"
|
#include "Settings.hpp"
|
||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
#include "moonlight_libretro_wrapper.h"
|
|
||||||
#include "gl_render.h"
|
#include "gl_render.h"
|
||||||
#include "libretro.h"
|
#include "libretro.h"
|
||||||
|
#include "InputController.hpp"
|
||||||
|
|
||||||
|
extern retro_input_state_t input_state_cb;
|
||||||
|
|
||||||
|
static int mouse_x = 0, mouse_y = 0;
|
||||||
|
static int mouse_l = 0, mouse_r = 0;
|
||||||
|
|
||||||
|
static int glfw_keyboard_state[GLFW_KEY_LAST];
|
||||||
|
|
||||||
|
#define GLFW_KEY_TO_RETRO(RETRO, KEY) \
|
||||||
|
if (id == RETRO) return glfw_keyboard_state[KEY];
|
||||||
|
|
||||||
|
static int16_t glfw_input_state_cb(unsigned port, unsigned device, unsigned index, unsigned id) {
|
||||||
|
if (device == RETRO_DEVICE_MOUSE) {
|
||||||
|
if (id == RETRO_DEVICE_ID_MOUSE_X) {
|
||||||
|
return mouse_x;
|
||||||
|
} else if (id == RETRO_DEVICE_ID_MOUSE_Y) {
|
||||||
|
return mouse_y;
|
||||||
|
} else if (id == RETRO_DEVICE_ID_MOUSE_LEFT) {
|
||||||
|
return mouse_l;
|
||||||
|
} else if (id == RETRO_DEVICE_ID_MOUSE_RIGHT) {
|
||||||
|
return mouse_r;
|
||||||
|
}
|
||||||
|
} else if (device == RETRO_DEVICE_JOYPAD) {
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_UP, GLFW_KEY_UP);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_DOWN, GLFW_KEY_DOWN);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_LEFT, GLFW_KEY_LEFT);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_RIGHT, GLFW_KEY_RIGHT);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_L, GLFW_KEY_Q);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_R, GLFW_KEY_E);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_L2, GLFW_KEY_Z);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_R2, GLFW_KEY_C);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_A, GLFW_KEY_A);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_B, GLFW_KEY_B);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_X, GLFW_KEY_X);
|
||||||
|
GLFW_KEY_TO_RETRO(RETRO_DEVICE_ID_JOYPAD_Y, GLFW_KEY_Y);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
|
input_state_cb = glfw_input_state_cb;
|
||||||
|
|
||||||
glfwInit();
|
glfwInit();
|
||||||
|
|
||||||
glfwSetErrorCallback([](int i, const char *error) {
|
glfwSetErrorCallback([](int i, const char *error) {
|
||||||
|
@ -29,11 +69,16 @@ int main(int argc, const char * argv[]) {
|
||||||
gl_render_init();
|
gl_render_init();
|
||||||
|
|
||||||
glfwSetCursorPosCallback(window, [](GLFWwindow *w, double x, double y) {
|
glfwSetCursorPosCallback(window, [](GLFWwindow *w, double x, double y) {
|
||||||
nanogui::cursor_pos_callback_event(x, y);
|
mouse_x = x;
|
||||||
|
mouse_y = y;
|
||||||
});
|
});
|
||||||
|
|
||||||
glfwSetMouseButtonCallback(window, [](GLFWwindow *w, int button, int action, int modifiers) {
|
glfwSetMouseButtonCallback(window, [](GLFWwindow *w, int button, int action, int modifiers) {
|
||||||
nanogui::mouse_button_callback_event(button, action, modifiers);
|
if (button == 0) {
|
||||||
|
mouse_l = action;
|
||||||
|
} else if (button == 1) {
|
||||||
|
mouse_r = action;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
glfwSetScrollCallback(window, [](GLFWwindow *w, double x, double y) {
|
glfwSetScrollCallback(window, [](GLFWwindow *w, double x, double y) {
|
||||||
|
@ -41,12 +86,7 @@ int main(int argc, const char * argv[]) {
|
||||||
});
|
});
|
||||||
|
|
||||||
glfwSetKeyCallback(window, [](GLFWwindow *w, int key, int scancode, int action, int mods) {
|
glfwSetKeyCallback(window, [](GLFWwindow *w, int key, int scancode, int action, int mods) {
|
||||||
if (GLFW_KEY_A <= key && key <= GLFW_KEY_Z) {
|
glfw_keyboard_state[key] = action != GLFW_RELEASE;
|
||||||
keyboard_state[RETROK_a + key - GLFW_KEY_A] = action == GLFW_PRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard_state[RETROK_w] ? game_pad_state.buttonFlags |= UP_FLAG : game_pad_state.buttonFlags &= ~UP_FLAG;
|
|
||||||
keyboard_state[RETROK_s] ? game_pad_state.buttonFlags |= DOWN_FLAG : game_pad_state.buttonFlags &= ~DOWN_FLAG;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
int width, height, fb_width, fb_height;
|
int width, height, fb_width, fb_height;
|
||||||
|
@ -58,11 +98,13 @@ int main(int argc, const char * argv[]) {
|
||||||
nanogui::init();
|
nanogui::init();
|
||||||
nanogui::ref<Application> app = new Application(Size(width, height), Size(fb_width, fb_height));
|
nanogui::ref<Application> app = new Application(Size(width, height), Size(fb_width, fb_height));
|
||||||
|
|
||||||
nanogui::setup(1.0 / 60.0 * 1000);
|
nanogui::setup(1.0 / 15.0);
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
|
InputController::controller()->handle_input(width, height);
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
glfwGetFramebufferSize(window, &width, &height);
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
|
|
|
@ -3,12 +3,16 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
#include "glsym/glsym.h"
|
#include "glsym/glsym.h"
|
||||||
#include "libretro.h"
|
#include "libretro.h"
|
||||||
#include "moonlight_libretro_wrapper.h"
|
#include "gl_render.h"
|
||||||
|
#include "Application.hpp"
|
||||||
|
#include "InputController.hpp"
|
||||||
|
#include "Settings.hpp"
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
|
||||||
static struct retro_hw_render_callback hw_render;
|
static struct retro_hw_render_callback hw_render;
|
||||||
|
|
||||||
#if defined(HAVE_PSGL)
|
#if defined(HAVE_PSGL)
|
||||||
|
@ -39,10 +43,32 @@ retro_audio_sample_batch_t audio_batch_cb;
|
||||||
static retro_environment_t environ_cb;
|
static retro_environment_t environ_cb;
|
||||||
static retro_input_poll_t input_poll_cb;
|
static retro_input_poll_t input_poll_cb;
|
||||||
retro_input_state_t input_state_cb;
|
retro_input_state_t input_state_cb;
|
||||||
static retro_log_printf_t log_cb;
|
|
||||||
|
static Application* app;
|
||||||
|
static bool moonlight_is_initialized = false;
|
||||||
|
|
||||||
|
void moonlight_init(int width, int height) {
|
||||||
|
if (moonlight_is_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
moonlight_is_initialized = true;
|
||||||
|
|
||||||
|
gl_render_init();
|
||||||
|
|
||||||
|
nanogui::init();
|
||||||
|
app = new Application(Size(width, height), Size(width, height));
|
||||||
|
|
||||||
|
nanogui::setup(1.0 / 15.0);
|
||||||
|
}
|
||||||
|
|
||||||
void retro_init(void) {
|
void retro_init(void) {
|
||||||
moonlight_libretro_wrapper_preinit();
|
#ifdef __LAKKA_SWITCH__
|
||||||
|
Settings::settings()->set_working_dir("/storage/system");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_deinit(void) {
|
void retro_deinit(void) {
|
||||||
|
@ -87,13 +113,11 @@ void retro_set_environment(retro_environment_t cb) {
|
||||||
bool no_game = true;
|
bool no_game = true;
|
||||||
cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_game);
|
cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_game);
|
||||||
|
|
||||||
#ifdef __LAKKA_SWITCH__
|
#ifndef __LAKKA_SWITCH__
|
||||||
moonlight_libretro_wrapper_set_working_dir("/storage/system");
|
|
||||||
#else
|
|
||||||
const char *dir = NULL;
|
const char *dir = NULL;
|
||||||
cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir);
|
cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir);
|
||||||
if (dir != NULL) {
|
if (dir != NULL) {
|
||||||
moonlight_libretro_wrapper_set_working_dir(dir);
|
Settings::settings()->set_working_dir(dir);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -123,51 +147,15 @@ static void update_variables(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_run(void) {
|
void retro_run(void) {
|
||||||
moonlight_libretro_wrapper_init(width, height);
|
moonlight_init(width, height);
|
||||||
|
|
||||||
// Handle inputs
|
|
||||||
input_poll_cb();
|
input_poll_cb();
|
||||||
|
InputController::controller()->handle_input(width, height);
|
||||||
|
|
||||||
double mouse_x = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
|
|
||||||
double mouse_y = input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
|
|
||||||
double pointer_x = 0;
|
|
||||||
double pointer_y = 0;
|
|
||||||
|
|
||||||
// TODO: Pointers in MacBook currently work incorrectly...
|
|
||||||
if (input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED)) {
|
|
||||||
int p_x = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
|
|
||||||
int p_y = input_state_cb(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
|
|
||||||
pointer_x = (p_x + 0x7fff) * width / 0xffff;
|
|
||||||
pointer_y = (p_y + 0x7fff) * height / 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __LAKKA_SWITCH__
|
|
||||||
if (mouse_x != 0 && mouse_y != 0) {
|
|
||||||
moonlight_libretro_wrapper_handle_mouse_move(mouse_x, mouse_y);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT)) {
|
|
||||||
if (pointer_x != 0 && pointer_y != 0) {
|
|
||||||
moonlight_libretro_wrapper_handle_mouse_move(pointer_x, pointer_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
moonlight_libretro_wrapper_handle_mouse_button(0, 1, 0);
|
|
||||||
} else if (!input_state_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT)) {
|
|
||||||
moonlight_libretro_wrapper_handle_mouse_button(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < RETROK_LAST; i++) {
|
|
||||||
keyboard_state[i] = input_state_cb(0, RETRO_DEVICE_KEYBOARD, 0, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
moonlight_libretro_wrapper_handle_game_pad();
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
|
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
|
||||||
|
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
moonlight_libretro_wrapper_draw();
|
nanogui::draw();
|
||||||
|
|
||||||
video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
|
video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
|
||||||
}
|
}
|
|
@ -1,105 +0,0 @@
|
||||||
#include "moonlight_libretro_wrapper.h"
|
|
||||||
#include "libretro.h"
|
|
||||||
#include "gl_render.h"
|
|
||||||
#include "Application.hpp"
|
|
||||||
#include "Settings.hpp"
|
|
||||||
#include "Limelight.h"
|
|
||||||
#include "Settings.hpp"
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
|
|
||||||
static bool moonlight_is_initialized = false;
|
|
||||||
|
|
||||||
static Application* app;
|
|
||||||
static std::string working_dir;
|
|
||||||
|
|
||||||
int16_t keyboard_state[RETROK_LAST];
|
|
||||||
struct GamePadState game_pad_state;
|
|
||||||
|
|
||||||
extern retro_input_state_t input_state_cb;
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_preinit() {
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_init(int width, int height) {
|
|
||||||
if (moonlight_is_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
moonlight_is_initialized = true;
|
|
||||||
|
|
||||||
Settings::settings()->set_working_dir(working_dir);
|
|
||||||
|
|
||||||
gl_render_init();
|
|
||||||
|
|
||||||
nanogui::init();
|
|
||||||
app = new Application(Size(width, height), Size(width, height));
|
|
||||||
|
|
||||||
//nanogui::setup(1.0 / 60.0 * 1000); no needs anymore?
|
|
||||||
}
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_set_working_dir(const char* dir) {
|
|
||||||
std::string str(dir, strlen(dir));
|
|
||||||
working_dir = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_handle_mouse_move(double x, double y) {
|
|
||||||
nanogui::cursor_pos_callback_event(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_handle_mouse_button(int button, int action, int modifiers) {
|
|
||||||
nanogui::mouse_button_callback_event(button, action, modifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_game_pad_state(short flag, int16_t state) {
|
|
||||||
if (state) {
|
|
||||||
game_pad_state.buttonFlags |= flag;
|
|
||||||
} else {
|
|
||||||
game_pad_state.buttonFlags &= ~flag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_handle_game_pad() {
|
|
||||||
game_pad_state.leftTrigger = 0xFFFF * input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2);
|
|
||||||
game_pad_state.rightTrigger = 0xFFFF * input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2);
|
|
||||||
|
|
||||||
game_pad_state.leftStickX = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
|
|
||||||
game_pad_state.leftStickY = 0xFFFF - input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y);
|
|
||||||
game_pad_state.rightStickX = input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);
|
|
||||||
game_pad_state.rightStickY = 0xFFFF - input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
|
|
||||||
|
|
||||||
#define GAME_PAD_STATE(KEY) \
|
|
||||||
input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, KEY)
|
|
||||||
|
|
||||||
set_game_pad_state(UP_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_UP));
|
|
||||||
set_game_pad_state(DOWN_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_DOWN));
|
|
||||||
set_game_pad_state(LEFT_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_LEFT));
|
|
||||||
set_game_pad_state(RIGHT_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_RIGHT));
|
|
||||||
|
|
||||||
set_game_pad_state(BACK_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_SELECT));
|
|
||||||
set_game_pad_state(PLAY_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_START));
|
|
||||||
|
|
||||||
set_game_pad_state(LB_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_L));
|
|
||||||
set_game_pad_state(RB_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_R));
|
|
||||||
|
|
||||||
set_game_pad_state(LS_CLK_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_L3));
|
|
||||||
set_game_pad_state(RS_CLK_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_R3));
|
|
||||||
|
|
||||||
if (Settings::settings()->swap_ab_xy()) {
|
|
||||||
set_game_pad_state(A_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_B));
|
|
||||||
set_game_pad_state(B_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_A));
|
|
||||||
set_game_pad_state(X_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_Y));
|
|
||||||
set_game_pad_state(Y_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_X));
|
|
||||||
} else {
|
|
||||||
set_game_pad_state(A_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_A));
|
|
||||||
set_game_pad_state(B_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_B));
|
|
||||||
set_game_pad_state(X_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_X));
|
|
||||||
set_game_pad_state(Y_FLAG, GAME_PAD_STATE(RETRO_DEVICE_ID_JOYPAD_Y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void moonlight_libretro_wrapper_draw() {
|
|
||||||
nanogui::draw();
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define EXTERN extern "C"
|
|
||||||
#else
|
|
||||||
#define EXTERN extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EXTERN int16_t keyboard_state[];
|
|
||||||
|
|
||||||
struct GamePadState {
|
|
||||||
short buttonFlags;
|
|
||||||
unsigned char leftTrigger;
|
|
||||||
unsigned char rightTrigger;
|
|
||||||
short leftStickX;
|
|
||||||
short leftStickY;
|
|
||||||
short rightStickX;
|
|
||||||
short rightStickY;
|
|
||||||
};
|
|
||||||
|
|
||||||
EXTERN struct GamePadState game_pad_state;
|
|
||||||
|
|
||||||
EXTERN void moonlight_libretro_wrapper_preinit();
|
|
||||||
EXTERN void moonlight_libretro_wrapper_init(int width, int height);
|
|
||||||
EXTERN void moonlight_libretro_wrapper_set_working_dir(const char* dir);
|
|
||||||
EXTERN void moonlight_libretro_wrapper_handle_mouse_move(double x, double y);
|
|
||||||
EXTERN void moonlight_libretro_wrapper_handle_mouse_button(int button, int action, int modifiers);
|
|
||||||
EXTERN void moonlight_libretro_wrapper_handle_game_pad();
|
|
||||||
EXTERN void moonlight_libretro_wrapper_draw();
|
|
|
@ -13,8 +13,7 @@ HostButton::HostButton(Widget* parent, const std::string &host): Button(parent,
|
||||||
add<Widget>()->set_fixed_height(170);
|
add<Widget>()->set_fixed_height(170);
|
||||||
auto label = add<Label>(host);
|
auto label = add<Label>(host);
|
||||||
label->set_font_size(20);
|
label->set_font_size(20);
|
||||||
|
label->inc_ref();
|
||||||
inc_ref();
|
|
||||||
|
|
||||||
GameStreamClient::client()->connect(host, [this, label](auto result) {
|
GameStreamClient::client()->connect(host, [this, label](auto result) {
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
|
@ -27,8 +26,12 @@ HostButton::HostButton(Widget* parent, const std::string &host): Button(parent,
|
||||||
m_is_active = false;
|
m_is_active = false;
|
||||||
m_host_status_icon = FA_POWER_OFF;
|
m_host_status_icon = FA_POWER_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_parent != NULL) {
|
||||||
screen()->perform_layout();
|
screen()->perform_layout();
|
||||||
this->dec_ref();
|
}
|
||||||
|
|
||||||
|
label->dec_ref();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,15 @@
|
||||||
#include "LoadingOverlay.hpp"
|
#include "LoadingOverlay.hpp"
|
||||||
#include "GameStreamClient.hpp"
|
#include "GameStreamClient.hpp"
|
||||||
#include "Settings.hpp"
|
#include "Settings.hpp"
|
||||||
|
#include "InputController.hpp"
|
||||||
#include "gl_render.h"
|
#include "gl_render.h"
|
||||||
#include "video_decoder.h"
|
#include "video_decoder.h"
|
||||||
#include "audio_decoder.h"
|
#include "audio_decoder.h"
|
||||||
#include "nanovg.h"
|
#include "nanovg.h"
|
||||||
#include "moonlight_libretro_wrapper.h"
|
|
||||||
#include "libretro.h"
|
#include "libretro.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
static bool pressed = false, sent_l_press = false, sent_r_press = false;
|
|
||||||
static bool sent_alt_tab = false;
|
|
||||||
static int current_mouse_x = 0, current_mouse_y = 0;
|
|
||||||
static int start_mouse_x = 0, start_mouse_y = 0;
|
|
||||||
|
|
||||||
using namespace nanogui;
|
using namespace nanogui;
|
||||||
|
|
||||||
static std::weak_ptr<StreamWindow *> _weak;
|
static std::weak_ptr<StreamWindow *> _weak;
|
||||||
|
@ -28,12 +23,6 @@ StreamWindow::StreamWindow(Widget *parent, const std::string &address, int app_i
|
||||||
m_connection_status_is_poor = false;
|
m_connection_status_is_poor = false;
|
||||||
m_size = parent->size();
|
m_size = parent->size();
|
||||||
|
|
||||||
pressed = sent_l_press = sent_r_press = false;
|
|
||||||
sent_alt_tab = false;
|
|
||||||
current_mouse_x = width() / 2;
|
|
||||||
current_mouse_y = height() / 2;
|
|
||||||
start_mouse_x = start_mouse_y = 0;
|
|
||||||
|
|
||||||
LiInitializeStreamConfiguration(&m_config);
|
LiInitializeStreamConfiguration(&m_config);
|
||||||
|
|
||||||
int h = Settings::settings()->resolution();
|
int h = Settings::settings()->resolution();
|
||||||
|
@ -121,83 +110,22 @@ void StreamWindow::draw(NVGcontext *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get out of here...
|
// TODO: Get out of here...
|
||||||
if (keyboard_state[RETROK_q] || ((game_pad_state.buttonFlags & LB_FLAG) && (game_pad_state.buttonFlags & RB_FLAG) && (game_pad_state.buttonFlags & DOWN_FLAG))) {
|
if (GAME_PAD_COMBO(DOWN_FLAG)) {
|
||||||
async([this] {
|
async([this] { this->terminate(true); });
|
||||||
this->terminate(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LiSendControllerEvent(
|
if (GAME_PAD_COMBO(UP_FLAG)) {
|
||||||
game_pad_state.buttonFlags,
|
async([this] { this->terminate(false); });
|
||||||
game_pad_state.leftTrigger,
|
|
||||||
game_pad_state.rightTrigger,
|
|
||||||
game_pad_state.leftStickX,
|
|
||||||
game_pad_state.leftStickY,
|
|
||||||
game_pad_state.rightStickX,
|
|
||||||
game_pad_state.rightStickY
|
|
||||||
);
|
|
||||||
|
|
||||||
// Send Alt + Tab
|
|
||||||
if (sent_alt_tab) {
|
|
||||||
sent_alt_tab = false;
|
|
||||||
LiSendKeyboardEvent(0x09, KEY_ACTION_UP, MODIFIER_ALT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((game_pad_state.buttonFlags & LB_FLAG) && (game_pad_state.buttonFlags & RB_FLAG) && (game_pad_state.buttonFlags & LEFT_FLAG)) {
|
InputController::controller()->send_to_stream();
|
||||||
sent_alt_tab = true;
|
|
||||||
LiSendKeyboardEvent(0x09, KEY_ACTION_DOWN, MODIFIER_ALT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamWindow::mouse_button_event(const nanogui::Vector2i &p, int button, bool down, int modifiers) {
|
bool StreamWindow::mouse_button_event(const nanogui::Vector2i &p, int button, bool down, int modifiers) {
|
||||||
#if defined(__LIBRETRO__) && (defined(__LAKKA_SWITCH__) || defined(__APPLE__))
|
|
||||||
if (button == 0) {
|
|
||||||
if (down && !pressed) {
|
|
||||||
start_mouse_x = p.x();
|
|
||||||
start_mouse_y = p.y();
|
|
||||||
}
|
|
||||||
pressed = down;
|
|
||||||
|
|
||||||
if (pressed && (keyboard_state[RETROK_LCTRL] || (game_pad_state.buttonFlags & LB_FLAG))) {
|
|
||||||
sent_l_press = true;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
||||||
} else if (sent_l_press) {
|
|
||||||
sent_l_press = false;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pressed && (keyboard_state[RETROK_LALT] || (game_pad_state.buttonFlags & RB_FLAG))) {
|
|
||||||
sent_r_press = true;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
|
||||||
} else if (sent_r_press) {
|
|
||||||
sent_r_press = false;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (button == 0) {
|
|
||||||
LiSendMouseButtonEvent(down ? BUTTON_ACTION_PRESS : BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
||||||
} else if (button == 1) {
|
|
||||||
LiSendMouseButtonEvent(down ? BUTTON_ACTION_PRESS : BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamWindow::mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) {
|
bool StreamWindow::mouse_motion_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) {
|
||||||
#if defined(__LIBRETRO__) && (defined(__LAKKA_SWITCH__) || defined(__APPLE__))
|
|
||||||
if (pressed) {
|
|
||||||
current_mouse_x = std::min(std::max(current_mouse_x + p.x() - start_mouse_x, 0), width());
|
|
||||||
current_mouse_y = std::min(std::max(current_mouse_y + p.y() - start_mouse_y, 0), height());
|
|
||||||
|
|
||||||
LiSendMousePositionEvent(current_mouse_x, current_mouse_y, width(), height());
|
|
||||||
|
|
||||||
start_mouse_x = p.x();
|
|
||||||
start_mouse_y = p.y();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
LiSendMousePositionEvent(p.x(), p.y(), width(), height());
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue