diff --git a/src/modules/joystick/Joystick.h b/src/modules/joystick/Joystick.h index 40002b460..4d201123c 100644 --- a/src/modules/joystick/Joystick.h +++ b/src/modules/joystick/Joystick.h @@ -24,6 +24,7 @@ // LOVE #include "common/Object.h" #include "common/StringMap.h" +#include "sensor/Sensor.h" // stdlib #include @@ -38,6 +39,8 @@ class Joystick : public Object { public: + using Sensor = love::sensor::Sensor; + static love::Type type; // Joystick hat values. @@ -198,6 +201,11 @@ public: virtual bool setVibration() = 0; virtual void getVibration(float &left, float &right) = 0; + virtual bool hasSensor(Sensor::SensorType type) const = 0; + virtual bool isSensorEnabled(Sensor::SensorType type) const = 0; + virtual void setSensorEnabled(Sensor::SensorType type, bool enabled) = 0; + virtual std::vector getSensorData(Sensor::SensorType type) const = 0; + STRINGMAP_CLASS_DECLARE(Hat); STRINGMAP_CLASS_DECLARE(GamepadType); STRINGMAP_CLASS_DECLARE(GamepadAxis); diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index 482a4b48a..44e094990 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -22,6 +22,10 @@ #include "common/config.h" #include "Joystick.h" #include "common/int.h" +#include "sensor/sdl/Sensor.h" + +// SDL +#include // C++ #include @@ -643,6 +647,86 @@ void Joystick::getVibration(float &left, float &right) right = vibration.right; } +bool Joystick::hasSensor(Sensor::SensorType type) const +{ +#if SDL_VERSION_ATLEAST(2, 0, 14) && defined(LOVE_ENABLE_SENSOR) + using SDLSensor = love::sensor::sdl::Sensor; + + if (!isGamepad()) + return false; + + return SDL_GameControllerHasSensor(controller, SDLSensor::convert(type)) == SDL_TRUE; +#else + return false; +#endif +} + +bool Joystick::isSensorEnabled(Sensor::SensorType type) const +{ +#if SDL_VERSION_ATLEAST(2, 0, 14) && defined(LOVE_ENABLE_SENSOR) + using SDLSensor = love::sensor::sdl::Sensor; + + if (!isGamepad()) + return false; + + return SDL_GameControllerIsSensorEnabled(controller, SDLSensor::convert(type)) == SDL_TRUE; +#else + return false; +#endif +} + +void Joystick::setSensorEnabled(Sensor::SensorType type, bool enabled) +{ +#if SDL_VERSION_ATLEAST(2, 0, 14) && defined(LOVE_ENABLE_SENSOR) + using SDLSensor = love::sensor::sdl::Sensor; + + if (!isGamepad()) + throw love::Exception("Sensor is only supported on gamepad"); + + if (SDL_GameControllerSetSensorEnabled(controller, SDLSensor::convert(type), enabled ? SDL_TRUE : SDL_FALSE) != 0) + { + const char *name = nullptr; + SDLSensor::getConstant(type, name); + + throw love::Exception("Could not open \"%s\" SDL gamepad sensor (%s)", name, SDL_GetError()); + } +#else + throw love::Exception("Compiled version of SDL or LOVE does not support gamepad sensor"); +#endif +} + +std::vector Joystick::getSensorData(Sensor::SensorType type) const +{ +#if SDL_VERSION_ATLEAST(2, 0, 14) && defined(LOVE_ENABLE_SENSOR) + using SDLSensor = love::sensor::sdl::Sensor; + + if (!isGamepad()) + throw love::Exception("Sensor is only supported on gamepad"); + + std::vector data(3); + + if (!isSensorEnabled(type)) + { + const char *name = nullptr; + SDLSensor::getConstant(type, name); + + throw love::Exception("\"%s\" gamepad sensor is not enabled", name); + } + + if (SDL_GameControllerGetSensorData(controller, SDLSensor::convert(type), data.data(), data.size()) != 0) + { + const char *name = nullptr; + SDLSensor::getConstant(type, name); + + throw love::Exception("Could not get \"%s\" SDL gamepad sensor data (%s)", name, SDL_GetError()); + } + + return data; +#else + throw love::Exception("Compiled version of SDL or LOVE does not support gamepad sensor"); +#endif +} + bool Joystick::getConstant(Uint8 in, Joystick::Hat &out) { return hats.find(in, out); diff --git a/src/modules/joystick/sdl/Joystick.h b/src/modules/joystick/sdl/Joystick.h index 664ecd627..3cec2f061 100644 --- a/src/modules/joystick/sdl/Joystick.h +++ b/src/modules/joystick/sdl/Joystick.h @@ -88,6 +88,11 @@ public: bool setVibration() override; void getVibration(float &left, float &right) override; + bool hasSensor(Sensor::SensorType type) const override; + bool isSensorEnabled(Sensor::SensorType type) const override; + void setSensorEnabled(Sensor::SensorType type, bool enabled) override; + std::vector getSensorData(Sensor::SensorType type) const override; + static bool getConstant(Hat in, Uint8 &out); static bool getConstant(Uint8 in, Hat &out); diff --git a/src/modules/joystick/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp index e1d66f884..214f7e303 100644 --- a/src/modules/joystick/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -21,6 +21,7 @@ // LOVE #include "wrap_Joystick.h" #include "wrap_JoystickModule.h" +#include "sensor/Sensor.h" #include @@ -367,6 +368,78 @@ int w_Joystick_getVibration(lua_State *L) return 2; } +#ifdef LOVE_ENABLE_SENSOR + +int w_Joystick_hasSensor(lua_State *L) +{ + using namespace love::sensor; + + Joystick *j = luax_checkjoystick(L, 1); + const char *sensorType = luaL_checkstring(L, 2); + + Sensor::SensorType type; + if (!Sensor::getConstant(sensorType, type)) + luax_enumerror(L, "sensor type", Sensor::getConstants(type), sensorType); + + luax_pushboolean(L, j->hasSensor(type)); + return 1; +} + +int w_Joystick_isSensorEnabled(lua_State *L) +{ + using namespace love::sensor; + + Joystick *j = luax_checkjoystick(L, 1); + const char *sensorType = luaL_checkstring(L, 2); + + Sensor::SensorType type; + if (!Sensor::getConstant(sensorType, type)) + luax_enumerror(L, "sensor type", Sensor::getConstants(type), sensorType); + + luax_pushboolean(L, j->isSensorEnabled(type)); + return 1; +} + +int w_Joystick_setSensorEnabled(lua_State *L) +{ + using namespace love::sensor; + + Joystick *j = luax_checkjoystick(L, 1); + const char *sensorType = luaL_checkstring(L, 2); + + Sensor::SensorType type; + if (!Sensor::getConstant(sensorType, type)) + luax_enumerror(L, "sensor type", Sensor::getConstants(type), sensorType); + + bool enabled = luax_checkboolean(L, 3); + + luax_catchexcept(L, [&]() { j->setSensorEnabled(type, enabled); }); + return 0; +} + +int w_Joystick_getSensorData(lua_State *L) +{ + using namespace love::sensor; + + Joystick *j = luax_checkjoystick(L, 1); + const char *sensorType = luaL_checkstring(L, 2); + + Sensor::SensorType type; + if (!Sensor::getConstant(sensorType, type)) + luax_enumerror(L, "sensor type", Sensor::getConstants(type), sensorType); + + std::vector data; + + luax_catchexcept(L, [&]() { data = j->getSensorData(type); }); + + for (float f: data) + lua_pushnumber(L, f); + + return (int) data.size(); +} + +#endif // LOVE_ENABLE_SENSOR + // List of functions to wrap. static const luaL_Reg w_Joystick_functions[] = { @@ -396,6 +469,13 @@ static const luaL_Reg w_Joystick_functions[] = { "setVibration", w_Joystick_setVibration }, { "getVibration", w_Joystick_getVibration }, +#ifdef LOVE_ENABLE_SENSOR + { "hasSensor", w_Joystick_hasSensor }, + { "isSensorEnabled", w_Joystick_isSensorEnabled }, + { "setSensorEnabled", w_Joystick_setSensorEnabled }, + { "getSensorData", w_Joystick_setSensorEnabled }, +#endif + // From wrap_JoystickModule. { "getConnectedIndex", w_getIndex }, diff --git a/src/modules/sensor/sdl/Sensor.cpp b/src/modules/sensor/sdl/Sensor.cpp index 2e5a69f06..b17e0ff00 100644 --- a/src/modules/sensor/sdl/Sensor.cpp +++ b/src/modules/sensor/sdl/Sensor.cpp @@ -156,6 +156,19 @@ Sensor::SensorType Sensor::convert(SDL_SensorType type) } } +SDL_SensorType Sensor::convert(Sensor::SensorType type) +{ + switch (type) + { + case SENSOR_ACCELEROMETER: + return SDL_SENSOR_ACCEL; + case SENSOR_GYROSCOPE: + return SDL_SENSOR_GYRO; + default: + return SDL_SENSOR_UNKNOWN; + } +} + } } } diff --git a/src/modules/sensor/sdl/Sensor.h b/src/modules/sensor/sdl/Sensor.h index 9dc9f6a8f..398dc0415 100644 --- a/src/modules/sensor/sdl/Sensor.h +++ b/src/modules/sensor/sdl/Sensor.h @@ -54,6 +54,7 @@ public: const char *getSensorName(SensorType type) override; static SensorType convert(SDL_SensorType type); + static SDL_SensorType convert(SensorType type); private: std::map sensors;