From 3f7f673216fdc2580296ec87cb06997b1b54327b Mon Sep 17 00:00:00 2001 From: TheQuinbox <thequinbox@gmail.com> Date: Wed, 15 May 2024 00:45:57 -0600 Subject: [PATCH] Initial thoughts on a joystick implementation and some joystick docs. --- .../enums/joystick_power_level.md | 10 ++ .../user interface/enums/joystick_type.md | 17 +++ .../builtin/user interface/enums/key_code.md | 2 +- src/input.cpp | 105 +++++++++++++++++- src/input.h | 75 +++++++++++++ test/quick/joystick.nvgt | 4 + 6 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 doc/src/references/builtin/user interface/enums/joystick_power_level.md create mode 100644 doc/src/references/builtin/user interface/enums/joystick_type.md create mode 100644 test/quick/joystick.nvgt diff --git a/doc/src/references/builtin/user interface/enums/joystick_power_level.md b/doc/src/references/builtin/user interface/enums/joystick_power_level.md new file mode 100644 index 00000000..df6ae8ac --- /dev/null +++ b/doc/src/references/builtin/user interface/enums/joystick_power_level.md @@ -0,0 +1,10 @@ +# joystick_power_level +Represents various charging states of a joystick. + +* JOYSTICK_POWER_UNKNOWN: the charging state is unknown. +* JOYSTICK_POWER_EMPTY: the battery is empty (<= 5%). +* JOYSTICK_POWER_LOW: the battery is low (<= 20%). +* JOYSTICK_POWER_MEDIUM: the battery is medium (<= 70%). +* JOYSTICK_POWER_FULL: the battery is full (<= 100%). +* JOYSTICK_POWER_WIRED: the joystick is currently plugged in. + * Note: it is not possible to get the battery level of the joystick while it is charging. diff --git a/doc/src/references/builtin/user interface/enums/joystick_type.md b/doc/src/references/builtin/user interface/enums/joystick_type.md new file mode 100644 index 00000000..a50d15a2 --- /dev/null +++ b/doc/src/references/builtin/user interface/enums/joystick_type.md @@ -0,0 +1,17 @@ +# joystick_type +This enum represents the types of joysticks NVGT knows about. DO note that if you have a joystick that's not in this list, it will most likely still work, but you just won't be able to identify it by type. + +* JOYSTICK_TYPE_UNKNOWN: unknown joystick type. +* JOYSTICK_TYPE_XBOX360: an XBOX 360 controller. +* JOYSTICK_TYPE_XBOX1: an XBOX 1 series controller. +* JOYSTICK_TYPE_PS3: a Playstation 3 controller. +* JOYSTICK_TYPE_PS4: a Playstation 4 controller. +* JOYSTICK_TYPE_NINTENDO_SWITCH_PRO: a controller for a non-lite (pro) Nintendo Switch. +* JOYSTICK_TYPE_VIRTUAL: a virtual joystick (for example from a program like JoyToKey). +* JOYSTICK_TYPE_PS5: a Playstation 5 controller. +* JOYSTICK_TYPE_AMAZON_LUNA: an Amazon Luna controller. +* JOYSTICK_TYPE_GOOGLE_STADIA: a Google Stadia controller. +* JOYSTICK_TYPE_NVIDIA_SHIELD: an NVIDIA shield controller. +* JOYSTICK_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: the left joycon of a Nintendo Switch. +* JOYSTICK_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: the right joycon of a Nintendo Switch. +* JOYSTICK_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: both joycons of a Nintendo switch. diff --git a/doc/src/references/builtin/user interface/enums/key_code.md b/doc/src/references/builtin/user interface/enums/key_code.md index 39ac58d4..cb2cb10a 100644 --- a/doc/src/references/builtin/user interface/enums/key_code.md +++ b/doc/src/references/builtin/user interface/enums/key_code.md @@ -1,5 +1,5 @@ # key_code -This is a complete list of possible keycodes in NVGT, as well as a short description of what they are. These are registered in the key_code enum, meaning you can use this type to pass any value listed here around though it is also safe to use integers. +This is a complete list of possible keycodes in NVGT, as well as a short description of what they are. These are registered in the key_code enum, meaning you can use this type to pass any value listed here around though it is also safe to use unsigned integers. ## Letter keys * KEY_UNKNOWN: unknown. diff --git a/src/input.cpp b/src/input.cpp index 74c6f3bc..a7bfd9b4 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -18,7 +18,6 @@ #endif #include <SDL2/SDL.h> #include <angelscript.h> -#include <scriptarray.h> #include <obfuscate.h> #include <sstream> #include <string> @@ -200,6 +199,57 @@ void mouse_update() { g_MousePrevZ = g_MouseAbsZ; } +int joystick_count(bool only_active = true) { + int total_joysticks = SDL_NumJoysticks(); + if (!only_active) return total_joysticks; + int ret = 0; + for (int i = 0; i < total_joysticks; i++) { + if (SDL_IsGameController(i)) + ret++; + } + return ret; +} + +joystick::joystick() { + if (joystick_count() > 0) + stick = SDL_GameControllerOpen(0); +} +joystick::~joystick() { + SDL_GameControllerClose(stick); +} + +unsigned int joystick::type() const { + return SDL_GameControllerGetType(stick); +} +unsigned int joystick::power_level() const { + return SDL_JoystickCurrentPowerLevel(SDL_GameControllerGetJoystick(stick)); +} +std::string joystick::name() const { + return SDL_GameControllerName(stick); +} +bool joystick::active() const { + return SDL_GameControllerGetAttached(stick); +} +bool joystick::has_led() const { + return SDL_GameControllerHasLED(stick); +} +bool joystick::can_vibrate() const { + return SDL_GameControllerHasRumble(stick); +} +bool joystick::can_vibrate_triggers() const { + return SDL_GameControllerHasRumbleTriggers(stick); +} + +bool joystick::set_led(unsigned char red, unsigned char green, unsigned char blue) { + return SDL_GameControllerSetLED(stick, red, green, blue); +} +bool joystick::vibrate(unsigned short low_frequency, unsigned short high_frequency, int duration) { + return SDL_GameControllerRumble(stick, low_frequency, high_frequency, duration); +} +bool joystick::vibrate_triggers(unsigned short left, unsigned short right, int duration) { + return SDL_GameControllerRumbleTriggers(stick, left, right, duration); +} + bool keyhook_active = true; #ifdef _WIN32 // Thanks Quentin Cosendey (Universal Speech) for this jaws keyboard hook code. @@ -271,6 +321,10 @@ void uninstall_keyhook() { void RegisterInput(asIScriptEngine* engine) { engine->RegisterEnum(_O("key_modifier")); engine->RegisterEnum(_O("key_code")); + engine->RegisterEnum(_O("joystick_type")); + engine->RegisterEnum(_O("joystick_bind_type")); + engine->RegisterEnum(_O("joystick_power_level")); + engine->RegisterEnum(_O("joystick_control_type")); engine->RegisterGlobalFunction(_O("bool key_pressed(uint)"), asFUNCTION(KeyPressed), asCALL_CDECL); engine->RegisterGlobalFunction(_O("bool key_repeating(uint)"), asFUNCTION(KeyRepeating), asCALL_CDECL); engine->RegisterGlobalFunction(_O("bool key_down(uint)"), asFUNCTION(key_down), asCALL_CDECL); @@ -566,4 +620,51 @@ void RegisterInput(asIScriptEngine* engine) { engine->RegisterEnumValue("key_code", "KEY_SOFTRIGHT", SDL_SCANCODE_SOFTRIGHT); engine->RegisterEnumValue("key_code", "KEY_CALL", SDL_SCANCODE_CALL); engine->RegisterEnumValue("key_code", "KEY_ENDCALL", SDL_SCANCODE_ENDCALL); -} + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_UNKNOWN", SDL_CONTROLLER_TYPE_UNKNOWN); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_XBOX360", SDL_CONTROLLER_TYPE_XBOX360); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_XBOX1", SDL_CONTROLLER_TYPE_XBOXONE); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_PS3", SDL_CONTROLLER_TYPE_PS3); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_PS4", SDL_CONTROLLER_TYPE_PS4); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_NINTENDO_SWITCH_PRO", SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_VIRTUAL", SDL_CONTROLLER_TYPE_VIRTUAL); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_PS5", SDL_CONTROLLER_TYPE_PS5); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_AMAZON_LUNA", SDL_CONTROLLER_TYPE_AMAZON_LUNA); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_GOOGLE_STADIA", SDL_CONTROLLER_TYPE_GOOGLE_STADIA); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_NVIDIA_SHIELD", SDL_CONTROLLER_TYPE_NVIDIA_SHIELD); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_NINTENDO_SWITCH_JOYCON_LEFT", SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT", SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT); + engine->RegisterEnumValue("joystick_type", "JOYSTICK_TYPE_NINTENDO_SWITCH_JOYCON_PAIR", SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR); + engine->RegisterEnumValue("joystick_bind_type", "JOYSTICK_BIND_TYPE_NONE", SDL_CONTROLLER_BINDTYPE_NONE); + engine->RegisterEnumValue("joystick_bind_type", "JOYSTICK_BIND_TYPE_BUTTON", SDL_CONTROLLER_BINDTYPE_BUTTON); + engine->RegisterEnumValue("joystick_bind_type", "JOYSTICK_BIND_TYPE_AXIS", SDL_CONTROLLER_BINDTYPE_AXIS); + engine->RegisterEnumValue("joystick_bind_type", "JOYSTICK_BIND_TYPE_HAT", SDL_CONTROLLER_BINDTYPE_HAT); + engine->RegisterEnumValue("joystick_power_level", "JOYSTICK_POWER_UNKNOWN", SDL_JOYSTICK_POWER_UNKNOWN); + engine->RegisterEnumValue("joystick_power_level", "JOYSTICK_POWER_EMPTY", SDL_JOYSTICK_POWER_EMPTY); + engine->RegisterEnumValue("joystick_power_level", "JOYSTICK_POWER_LOW", SDL_JOYSTICK_POWER_LOW); + engine->RegisterEnumValue("joystick_power_level", "JOYSTICK_POWER_MEDIUM", SDL_JOYSTICK_POWER_MEDIUM); + engine->RegisterEnumValue("joystick_power_level", "JOYSTICK_POWER_FULL", SDL_JOYSTICK_POWER_FULL); + engine->RegisterEnumValue("joystick_power_level", "JOYSTICK_POWER_WIRED", SDL_JOYSTICK_POWER_WIRED); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_INVALID", SDL_CONTROLLER_BUTTON_INVALID); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_A", SDL_CONTROLLER_BUTTON_A); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_B", SDL_CONTROLLER_BUTTON_B); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_X", SDL_CONTROLLER_BUTTON_X); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_Y", SDL_CONTROLLER_BUTTON_Y); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_BACK", SDL_CONTROLLER_BUTTON_BACK); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_GUIDE", SDL_CONTROLLER_BUTTON_GUIDE); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_START", SDL_CONTROLLER_BUTTON_START); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_LEFT_STICK", SDL_CONTROLLER_BUTTON_LEFTSTICK); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_RIGHT_STICK", SDL_CONTROLLER_BUTTON_RIGHTSTICK); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_LEFT_SHOULDER", SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_RIGHT_SHOULDER", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_DPAD_UP", SDL_CONTROLLER_BUTTON_DPAD_UP); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_DPAD_DOWN", SDL_CONTROLLER_BUTTON_DPAD_DOWN); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_DPAD_LEFT", SDL_CONTROLLER_BUTTON_DPAD_LEFT); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_DPAD_RIGHT", SDL_CONTROLLER_BUTTON_DPAD_RIGHT); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_BUTTON_MISC", SDL_CONTROLLER_BUTTON_MISC1); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_PADDLE1", SDL_CONTROLLER_BUTTON_PADDLE1); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_PADDLE2", SDL_CONTROLLER_BUTTON_PADDLE2); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_PADDLE3", SDL_CONTROLLER_BUTTON_PADDLE3); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_PADDLE4", SDL_CONTROLLER_BUTTON_PADDLE4); + engine->RegisterEnumValue("joystick_control_type", "JOYSTICK_CONTROL_TOUCHPAD", SDL_CONTROLLER_BUTTON_TOUCHPAD); + engine->RegisterGlobalFunction("int joystick_count(bool = true)", asFUNCTION(joystick_count), asCALL_CDECL); +}; diff --git a/src/input.h b/src/input.h index fe532ea2..0ab0a1e5 100644 --- a/src/input.h +++ b/src/input.h @@ -11,12 +11,87 @@ */ #pragma once + #include <string> #include <angelscript.h> +#include <scriptarray.h> +#include <Poco/RefCountedObject.h> + union SDL_Event; extern std::string g_UserInput; extern bool keyhook_active; +class joystick : Poco::RefCountedObject { + SDL_GameController* stick; + +public: + unsigned int type() const; + unsigned int power_level() const; + bool has_led() const; + bool can_vibrate() const; + bool can_vibrate_triggers() const; + unsigned int buttons() const; + unsigned int sliders() const; + unsigned int povs() const; + std::string name() const; + bool active() const; + int preferred_joystick() const; + unsigned int x() const; + unsigned int y() const; + unsigned int z() const; + unsigned int r_x() const; + unsigned int r_y() const; + unsigned int r_z() const; + unsigned int slider_1() const; + unsigned int slider_2() const; + unsigned int pov_1() const; + unsigned int pov_2() const; + unsigned int pov_3() const; + unsigned int pov_4() const; + unsigned int v_x() const; + unsigned int v_y() const; + unsigned int v_z() const; + unsigned int vr_x() const; + unsigned int vr_y() const; + unsigned int vr_z() const; + unsigned int v_slider_1() const; + unsigned int v_slider_2() const; + unsigned int a_x() const; + unsigned int a_y() const; + unsigned int a_z() const; + unsigned int ar_x() const; + unsigned int ar_y() const; + unsigned int ar_z() const; + unsigned int a_slider_1() const; + unsigned int a_slider_2() const; + unsigned int f_x() const; + unsigned int f_y() const; + unsigned int f_z() const; + unsigned int fr_x() const; + unsigned int fr_y() const; + unsigned int fr_z() const; + unsigned int f_slider_1() const; + unsigned int f_slider_2() const; + + joystick(); + ~joystick(); + bool button_down(int button); + bool button_pressed(int button); + bool button_released(int button); + bool button_up(int button); + CScriptArray* buttons_down(); + CScriptArray* buttons_pressed(); + CScriptArray* buttons_released(); + CScriptArray* buttons_up(); + CScriptArray* list_joysticks(); + bool pov_centered(int pov); + bool set_led(unsigned char red, unsigned char green, unsigned char blue); + bool vibrate(unsigned short low_frequency, unsigned short high_frequency, int duration); + bool vibrate_triggers(unsigned short left, unsigned short right, int duration); + bool refresh_joystick_list(); + bool set(int index); +}; + void InputInit(); void InputDestroy(); void InputEvent(SDL_Event* evt); diff --git a/test/quick/joystick.nvgt b/test/quick/joystick.nvgt new file mode 100644 index 00000000..aefcfc61 --- /dev/null +++ b/test/quick/joystick.nvgt @@ -0,0 +1,4 @@ +void main() { + int joysticks = joystick_count; + screen_reader_speak("Your system has " + joysticks + " " + (joysticks == 1 ? "joystick" : "joysticks") + " connected", true); +}