Skip to content

Commit

Permalink
Initial thoughts on a joystick implementation and some joystick docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheQuinbox committed May 15, 2024
1 parent 6c2309f commit 3f7f673
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -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.
17 changes: 17 additions & 0 deletions doc/src/references/builtin/user interface/enums/joystick_type.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
105 changes: 103 additions & 2 deletions src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#endif
#include <SDL2/SDL.h>
#include <angelscript.h>
#include <scriptarray.h>
#include <obfuscate.h>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
};
75 changes: 75 additions & 0 deletions src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions test/quick/joystick.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
void main() {
int joysticks = joystick_count;
screen_reader_speak("Your system has " + joysticks + " " + (joysticks == 1 ? "joystick" : "joysticks") + " connected", true);
}

0 comments on commit 3f7f673

Please sign in to comment.