mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Merged SDL2 changes from bartbes/love-experiments/SDL2 into default.
- Added love.system module, including clipboard functions. - Added custom hardware cursors (love.mouse.newCursor, love.mouse.setCursor.) - Revamped love.joystick: -- added Joystick objects and moved love.joystick functions which operated on individual joysticks to methods on the Joystick objects. -- Added love.joystick.getJoystick and love.joystick.getJoystickCount. -- Added events for when joysticks are connected and disconnected. -- Added 'Gamepad' methods to Joystick objects: Joystick:isGamepad, Joystick:getGamepadAxis, and Joystick:isGamepadDown. They're a common abstraction for xbox controller-like joystick across operating systems. - Added monitor choosing support and "fullscreen desktop" mode to love.window. - Moved unicode text input events to their own callback function (love.textinput), removed the key repeat functions from love.keyboard and made the second argument of love.keypressed a boolean saying whether the keypress was a repeat. - liblove now works with love.window and love.graphics in OS X
This commit is contained in:
@@ -18,15 +18,26 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
// LOVE
|
||||
#include "Joystick.h"
|
||||
|
||||
// STL
|
||||
#include <cmath>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
|
||||
Joystick::~Joystick()
|
||||
float Joystick::clampval(float x) const
|
||||
{
|
||||
if (fabsf(x) < 0.01)
|
||||
return 0.0f;
|
||||
|
||||
if (x < -0.99f) return -1.0f;
|
||||
if (x > 0.99f) return 1.0f;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(const char *in, Joystick::Hat &out)
|
||||
@@ -34,11 +45,41 @@ bool Joystick::getConstant(const char *in, Joystick::Hat &out)
|
||||
return hats.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::Hat in, const char *&out)
|
||||
bool Joystick::getConstant(Joystick::Hat in, const char *&out)
|
||||
{
|
||||
return hats.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(const char *in, Joystick::GamepadAxis &out)
|
||||
{
|
||||
return gpAxes.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::GamepadAxis in, const char *&out)
|
||||
{
|
||||
return gpAxes.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(const char *in, Joystick::GamepadButton &out)
|
||||
{
|
||||
return gpButtons.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::GamepadButton in, const char *&out)
|
||||
{
|
||||
return gpButtons.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(const char *in, Joystick::InputType &out)
|
||||
{
|
||||
return inputTypes.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::InputType in, const char *&out)
|
||||
{
|
||||
return inputTypes.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Joystick::Hat, Joystick::HAT_MAX_ENUM>::Entry Joystick::hatEntries[] =
|
||||
{
|
||||
{"c", Joystick::HAT_CENTERED},
|
||||
@@ -54,5 +95,47 @@ StringMap<Joystick::Hat, Joystick::HAT_MAX_ENUM>::Entry Joystick::hatEntries[] =
|
||||
|
||||
StringMap<Joystick::Hat, Joystick::HAT_MAX_ENUM> Joystick::hats(Joystick::hatEntries, sizeof(Joystick::hatEntries));
|
||||
|
||||
StringMap<Joystick::GamepadAxis, Joystick::GAMEPAD_AXIS_MAX_ENUM>::Entry Joystick::gpAxisEntries[] =
|
||||
{
|
||||
{"leftx", GAMEPAD_AXIS_LEFTX},
|
||||
{"lefty", GAMEPAD_AXIS_LEFTY},
|
||||
{"rightx", GAMEPAD_AXIS_RIGHTX},
|
||||
{"righty", GAMEPAD_AXIS_RIGHTY},
|
||||
{"triggerleft", GAMEPAD_AXIS_TRIGGERLEFT},
|
||||
{"triggerright", GAMEPAD_AXIS_TRIGGERRIGHT},
|
||||
};
|
||||
|
||||
StringMap<Joystick::GamepadAxis, Joystick::GAMEPAD_AXIS_MAX_ENUM> Joystick::gpAxes(Joystick::gpAxisEntries, sizeof(Joystick::gpAxisEntries));
|
||||
|
||||
StringMap<Joystick::GamepadButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM>::Entry Joystick::gpButtonEntries[] =
|
||||
{
|
||||
{"a", GAMEPAD_BUTTON_A},
|
||||
{"b", GAMEPAD_BUTTON_B},
|
||||
{"x", GAMEPAD_BUTTON_X},
|
||||
{"y", GAMEPAD_BUTTON_Y},
|
||||
{"back", GAMEPAD_BUTTON_BACK},
|
||||
{"guide", GAMEPAD_BUTTON_GUIDE},
|
||||
{"start", GAMEPAD_BUTTON_START},
|
||||
{"leftstick", GAMEPAD_BUTTON_LEFTSTICK},
|
||||
{"rightstick", GAMEPAD_BUTTON_RIGHTSTICK},
|
||||
{"leftshoulder", GAMEPAD_BUTTON_LEFTSHOULDER},
|
||||
{"rightshoulder", GAMEPAD_BUTTON_RIGHTSHOULDER},
|
||||
{"dpup", GAMEPAD_BUTTON_DPAD_UP},
|
||||
{"dpdown", GAMEPAD_BUTTON_DPAD_DOWN},
|
||||
{"dpleft", GAMEPAD_BUTTON_DPAD_LEFT},
|
||||
{"dpright", GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||
};
|
||||
|
||||
StringMap<Joystick::GamepadButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM> Joystick::gpButtons(Joystick::gpButtonEntries, sizeof(Joystick::gpButtonEntries));
|
||||
|
||||
StringMap<Joystick::InputType, Joystick::INPUT_TYPE_MAX_ENUM>::Entry Joystick::inputTypeEntries[] =
|
||||
{
|
||||
{"axis", Joystick::INPUT_TYPE_AXIS},
|
||||
{"button", Joystick::INPUT_TYPE_BUTTON},
|
||||
{"hat", Joystick::INPUT_TYPE_HAT},
|
||||
};
|
||||
|
||||
StringMap<Joystick::InputType, Joystick::INPUT_TYPE_MAX_ENUM> Joystick::inputTypes(Joystick::inputTypeEntries, sizeof(Joystick::inputTypeEntries));
|
||||
|
||||
} // joystick
|
||||
} // love
|
||||
|
||||
@@ -22,18 +22,23 @@
|
||||
#define LOVE_JOYSTICK_JOYSTICK_H
|
||||
|
||||
// LOVE
|
||||
#include "common/Module.h"
|
||||
#include "common/Object.h"
|
||||
#include "common/StringMap.h"
|
||||
|
||||
// stdlib
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
|
||||
class Joystick : public Module
|
||||
class Joystick : public Object
|
||||
{
|
||||
public:
|
||||
|
||||
// Joystick hat values.
|
||||
enum Hat
|
||||
{
|
||||
HAT_INVALID,
|
||||
@@ -49,19 +54,142 @@ public:
|
||||
HAT_MAX_ENUM = 16
|
||||
};
|
||||
|
||||
virtual ~Joystick();
|
||||
// Valid Gamepad axes.
|
||||
enum GamepadAxis
|
||||
{
|
||||
GAMEPAD_AXIS_INVALID,
|
||||
GAMEPAD_AXIS_LEFTX,
|
||||
GAMEPAD_AXIS_LEFTY,
|
||||
GAMEPAD_AXIS_RIGHTX,
|
||||
GAMEPAD_AXIS_RIGHTY,
|
||||
GAMEPAD_AXIS_TRIGGERLEFT,
|
||||
GAMEPAD_AXIS_TRIGGERRIGHT,
|
||||
GAMEPAD_AXIS_MAX_ENUM
|
||||
};
|
||||
|
||||
// Valid Gamepad buttons.
|
||||
enum GamepadButton
|
||||
{
|
||||
GAMEPAD_BUTTON_INVALID,
|
||||
GAMEPAD_BUTTON_A,
|
||||
GAMEPAD_BUTTON_B,
|
||||
GAMEPAD_BUTTON_X,
|
||||
GAMEPAD_BUTTON_Y,
|
||||
GAMEPAD_BUTTON_BACK,
|
||||
GAMEPAD_BUTTON_GUIDE,
|
||||
GAMEPAD_BUTTON_START,
|
||||
GAMEPAD_BUTTON_LEFTSTICK,
|
||||
GAMEPAD_BUTTON_RIGHTSTICK,
|
||||
GAMEPAD_BUTTON_LEFTSHOULDER,
|
||||
GAMEPAD_BUTTON_RIGHTSHOULDER,
|
||||
GAMEPAD_BUTTON_DPAD_UP,
|
||||
GAMEPAD_BUTTON_DPAD_DOWN,
|
||||
GAMEPAD_BUTTON_DPAD_LEFT,
|
||||
GAMEPAD_BUTTON_DPAD_RIGHT,
|
||||
GAMEPAD_BUTTON_MAX_ENUM
|
||||
};
|
||||
|
||||
// Different types of inputs for a joystick.
|
||||
enum InputType
|
||||
{
|
||||
INPUT_TYPE_AXIS,
|
||||
INPUT_TYPE_BUTTON,
|
||||
INPUT_TYPE_HAT,
|
||||
INPUT_TYPE_MAX_ENUM
|
||||
};
|
||||
|
||||
// Represents a gamepad input value, e.g. the "x" button or the left trigger.
|
||||
struct GamepadInput
|
||||
{
|
||||
InputType type;
|
||||
union
|
||||
{
|
||||
GamepadAxis axis;
|
||||
GamepadButton button;
|
||||
};
|
||||
};
|
||||
|
||||
// Represents a joystick input value, e.g. button 6 or axis 1.
|
||||
struct JoystickInput
|
||||
{
|
||||
InputType type;
|
||||
union
|
||||
{
|
||||
int axis;
|
||||
int button;
|
||||
struct
|
||||
{
|
||||
int index;
|
||||
Hat value;
|
||||
} hat;
|
||||
};
|
||||
};
|
||||
|
||||
virtual ~Joystick() {}
|
||||
|
||||
virtual bool open(int deviceindex) = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual bool isConnected() const = 0;
|
||||
|
||||
virtual const char *getName() const = 0;
|
||||
|
||||
virtual int getAxisCount() const = 0;
|
||||
virtual int getButtonCount() const = 0;
|
||||
virtual int getHatCount() const = 0;
|
||||
|
||||
virtual float getAxis(int axisindex) const = 0;
|
||||
virtual std::vector<float> getAxes() const = 0;
|
||||
virtual Hat getHat(int hatindex) const = 0;
|
||||
|
||||
virtual bool isDown(const std::vector<int> &buttonlist) const = 0;
|
||||
|
||||
virtual bool openGamepad(int deviceindex) = 0;
|
||||
virtual bool isGamepad() const = 0;
|
||||
|
||||
virtual float getGamepadAxis(GamepadAxis axis) const = 0;
|
||||
virtual bool isGamepadDown(const std::vector<GamepadButton> &blist) const = 0;
|
||||
|
||||
virtual void *getHandle() const = 0;
|
||||
|
||||
virtual std::string getGUID() const = 0;
|
||||
virtual int getInstanceID() const = 0;
|
||||
virtual int getID() const = 0;
|
||||
|
||||
static bool getConstant(const char *in, Hat &out);
|
||||
static bool getConstant(Hat in, const char *&out);
|
||||
static bool getConstant(Hat in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, GamepadAxis &out);
|
||||
static bool getConstant(GamepadAxis in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, GamepadButton &out);
|
||||
static bool getConstant(GamepadButton in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, InputType &out);
|
||||
static bool getConstant(InputType in, const char *&out);
|
||||
|
||||
protected:
|
||||
|
||||
float clampval(float x) const;
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<Hat, HAT_MAX_ENUM>::Entry hatEntries[];
|
||||
static StringMap<Hat, HAT_MAX_ENUM> hats;
|
||||
|
||||
static StringMap<GamepadAxis, GAMEPAD_AXIS_MAX_ENUM>::Entry gpAxisEntries[];
|
||||
static StringMap<GamepadAxis, GAMEPAD_AXIS_MAX_ENUM> gpAxes;
|
||||
|
||||
static StringMap<GamepadButton, GAMEPAD_BUTTON_MAX_ENUM>::Entry gpButtonEntries[];
|
||||
static StringMap<GamepadButton, GAMEPAD_BUTTON_MAX_ENUM> gpButtons;
|
||||
|
||||
static StringMap<InputType, INPUT_TYPE_MAX_ENUM>::Entry inputTypeEntries[];
|
||||
static StringMap<InputType, INPUT_TYPE_MAX_ENUM> inputTypes;
|
||||
|
||||
}; // Joystick
|
||||
|
||||
} // joystick
|
||||
} // love
|
||||
|
||||
#endif // LOVE_JOYSTICK_JOYSTICK_H
|
||||
|
||||
#endif // LOVE_JOYSTICK_JOYSTICK_H
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2013 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_JOYSTICK_JOYSTICK_MODULE_H
|
||||
#define LOVE_JOYSTICK_JOYSTICK_MODULE_H
|
||||
|
||||
// LOVE
|
||||
#include "common/Module.h"
|
||||
#include "Joystick.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
|
||||
class JoystickModule : public Module
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~JoystickModule() {}
|
||||
|
||||
/**
|
||||
* Adds a connected Joystick device and opens it for use.
|
||||
* Returns NULL if the Joystick could not be added.
|
||||
**/
|
||||
virtual Joystick *addJoystick(int deviceindex) = 0;
|
||||
|
||||
/**
|
||||
* Removes a disconnected Joystick device.
|
||||
**/
|
||||
virtual void removeJoystick(Joystick *joystick) = 0;
|
||||
|
||||
/**
|
||||
* Gets a connected Joystick from its unique Instance ID.
|
||||
* Returns NULL if the instance ID does not correspond to a connected stick.
|
||||
**/
|
||||
virtual Joystick *getJoystickFromID(int instanceid) = 0;
|
||||
|
||||
/**
|
||||
* Gets a connected Joystick.
|
||||
* Returns NULL if joyindex is not in the range of [0, getJoystickCount()).
|
||||
**/
|
||||
virtual Joystick *getJoystick(int joyindex) = 0;
|
||||
|
||||
/**
|
||||
* Gets the index of a connected joystick.
|
||||
* Returns -1 if the joystick is not connected.
|
||||
**/
|
||||
virtual int getIndex(const Joystick *joystick) = 0;
|
||||
|
||||
/**
|
||||
* Gets the number of currently connected Joysticks.
|
||||
**/
|
||||
virtual int getJoystickCount() const = 0;
|
||||
|
||||
/**
|
||||
* Determines whether the Joystick at the specified index is a recognized
|
||||
* Gamepad.
|
||||
**/
|
||||
virtual bool isGamepad(int joyindex) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the virtual Gamepad mapping for a joystick input value for all
|
||||
* joystick devices with the specified joystick GUID.
|
||||
* If any joysticks with the specified GUID are connected, they will be
|
||||
* added as Gamepads if they aren't already, otherwise their Gamepad mapping
|
||||
* will be updated.
|
||||
**/
|
||||
virtual bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput) = 0;
|
||||
|
||||
/**
|
||||
* Gets the joystick input value the gamepad input value is bound to for the
|
||||
* specified joystick GUID.
|
||||
**/
|
||||
virtual Joystick::JoystickInput getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput) = 0;
|
||||
|
||||
}; // JoystickModule
|
||||
|
||||
} // joystick
|
||||
} // love
|
||||
|
||||
#endif // LOVE_JOYSTICK_JOYSTICK_MODULE_H
|
||||
@@ -20,9 +20,6 @@
|
||||
|
||||
#include "Joystick.h"
|
||||
|
||||
// STD
|
||||
#include <cmath>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
@@ -30,206 +27,260 @@ namespace joystick
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
Joystick::Joystick()
|
||||
: joysticks(0)
|
||||
Joystick::Joystick(int id)
|
||||
: joyhandle(0)
|
||||
, controller(0)
|
||||
, instanceid(-1)
|
||||
, id(id)
|
||||
{
|
||||
// Init the SDL joystick system.
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||
throw love::Exception("%s", SDL_GetError());
|
||||
}
|
||||
|
||||
// Start joystick event watching.
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
|
||||
// Open all connected joysticks.
|
||||
int numjoysticks = getJoystickCount();
|
||||
if (numjoysticks > 0)
|
||||
this->joysticks = (SDL_Joystick **)calloc(numjoysticks, sizeof(SDL_Joystick *));
|
||||
|
||||
for (int i = 0; i<numjoysticks; i++)
|
||||
this->open(i);
|
||||
Joystick::Joystick(int id, int joyindex)
|
||||
: joyhandle(0)
|
||||
, controller(0)
|
||||
, instanceid(-1)
|
||||
, id(id)
|
||||
{
|
||||
open(joyindex);
|
||||
}
|
||||
|
||||
Joystick::~Joystick()
|
||||
{
|
||||
// Closes any open joysticks.
|
||||
for (int i = 0; i != getJoystickCount(); i++)
|
||||
{
|
||||
if (isOpen(i))
|
||||
close(i);
|
||||
}
|
||||
|
||||
free(joysticks);
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
close();
|
||||
}
|
||||
|
||||
void Joystick::reload()
|
||||
bool Joystick::open(int deviceindex)
|
||||
{
|
||||
// Closes any open joysticks.
|
||||
for (int i = 0; i != getJoystickCount(); i++)
|
||||
close();
|
||||
|
||||
joyhandle = SDL_JoystickOpen(deviceindex);
|
||||
|
||||
if (joyhandle)
|
||||
{
|
||||
if (isOpen(i))
|
||||
close(i);
|
||||
instanceid = SDL_JoystickInstanceID(joyhandle);
|
||||
|
||||
// SDL_JoystickGetGUIDString uses 32 bytes plus the null terminator.
|
||||
char cstr[33];
|
||||
|
||||
SDL_JoystickGUID sdlguid = SDL_JoystickGetGUID(joyhandle);
|
||||
SDL_JoystickGetGUIDString(sdlguid, cstr, (int) sizeof(cstr));
|
||||
|
||||
guid = std::string(cstr);
|
||||
|
||||
// See if SDL thinks this is a Game Controller.
|
||||
openGamepad(deviceindex);
|
||||
|
||||
// Prefer the GameController name.
|
||||
if (controller)
|
||||
name = SDL_GameControllerName(controller);
|
||||
else
|
||||
name = SDL_JoystickName(joyhandle);
|
||||
}
|
||||
|
||||
free(joysticks);
|
||||
return isConnected();
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
void Joystick::close()
|
||||
{
|
||||
if (controller)
|
||||
SDL_GameControllerClose(controller);
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||
throw love::Exception("%s", SDL_GetError());
|
||||
if (joyhandle)
|
||||
SDL_JoystickClose(joyhandle);
|
||||
|
||||
int numjoysticks = this->getJoystickCount();
|
||||
if (numjoysticks > 0)
|
||||
this->joysticks = (SDL_Joystick **)calloc(numjoysticks, sizeof(SDL_Joystick *));
|
||||
joyhandle = 0;
|
||||
controller = 0;
|
||||
instanceid = -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i<numjoysticks; i++)
|
||||
this->open(i);
|
||||
bool Joystick::isConnected() const
|
||||
{
|
||||
return joyhandle != 0 && SDL_JoystickGetAttached(joyhandle);
|
||||
}
|
||||
|
||||
const char *Joystick::getName() const
|
||||
{
|
||||
return "love.joystick.sdl";
|
||||
// Use the saved name if this Joystick isn't connected anymore.
|
||||
if (!isConnected())
|
||||
return name.c_str();
|
||||
|
||||
// Prefer SDL's GameController name, if possible.
|
||||
if (isGamepad())
|
||||
return SDL_GameControllerName(controller);
|
||||
|
||||
return SDL_JoystickName(joyhandle);
|
||||
}
|
||||
|
||||
bool Joystick::checkIndex(int index)
|
||||
int Joystick::getAxisCount() const
|
||||
{
|
||||
return index >= 0 && index < getJoystickCount();
|
||||
return isConnected() ? SDL_JoystickNumAxes(joyhandle) : 0;
|
||||
}
|
||||
|
||||
int Joystick::getJoystickCount()
|
||||
int Joystick::getButtonCount() const
|
||||
{
|
||||
int num = SDL_NumJoysticks();
|
||||
return num < 0 ? 0 : num;
|
||||
return isConnected() ? SDL_JoystickNumButtons(joyhandle) : 0;
|
||||
}
|
||||
|
||||
const char *Joystick::getName(int index)
|
||||
int Joystick::getHatCount() const
|
||||
{
|
||||
return SDL_JoystickName(index);
|
||||
return isConnected() ? SDL_JoystickNumHats(joyhandle) : 0;
|
||||
}
|
||||
|
||||
bool Joystick::open(int index)
|
||||
float Joystick::getAxis(int axisindex) const
|
||||
{
|
||||
if (isOpen(index))
|
||||
return true;
|
||||
|
||||
if (!checkIndex(index))
|
||||
return false;
|
||||
|
||||
if (!(joysticks[index] = SDL_JoystickOpen(index)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Joystick::isOpen(int index)
|
||||
{
|
||||
if (!checkIndex(index))
|
||||
return false;
|
||||
|
||||
return joysticks[index] != 0 ? true : false;
|
||||
}
|
||||
|
||||
bool Joystick::verifyJoystick(int index)
|
||||
{
|
||||
if (!checkIndex(index))
|
||||
return false;
|
||||
|
||||
if (!isOpen(index))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Joystick::getAxisCount(int index)
|
||||
{
|
||||
return verifyJoystick(index) ? SDL_JoystickNumAxes(joysticks[index]) : 0;
|
||||
}
|
||||
|
||||
int Joystick::getButtonCount(int index)
|
||||
{
|
||||
return verifyJoystick(index) ? SDL_JoystickNumButtons(joysticks[index]) : 0;
|
||||
}
|
||||
|
||||
int Joystick::getHatCount(int index)
|
||||
{
|
||||
return verifyJoystick(index) ? SDL_JoystickNumHats(joysticks[index]) : 0;
|
||||
}
|
||||
|
||||
float Joystick::clampval(float x)
|
||||
{
|
||||
if (fabs((double)x) < 0.01) return 0.0f;
|
||||
if (x < -0.99f) return -1.0f;
|
||||
if (x > 0.99f) return 1.0f;
|
||||
return x;
|
||||
}
|
||||
|
||||
float Joystick::getAxis(int index, int axis)
|
||||
{
|
||||
if (!verifyJoystick(index))
|
||||
if (!isConnected() || axisindex < 0 || axisindex >= getAxisCount())
|
||||
return 0;
|
||||
|
||||
if (axis >= getAxisCount(index))
|
||||
return 0;
|
||||
|
||||
return clampval(((float)SDL_JoystickGetAxis(joysticks[index], axis))/32768.0f);
|
||||
return clampval(((float) SDL_JoystickGetAxis(joyhandle, axisindex))/32768.0f);
|
||||
}
|
||||
|
||||
int Joystick::getAxes(lua_State *L)
|
||||
std::vector<float> Joystick::getAxes() const
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
std::vector<float> axes;
|
||||
int count = getAxisCount();
|
||||
|
||||
if (!verifyJoystick(index))
|
||||
return 0;
|
||||
if (!isConnected() || count <= 0)
|
||||
return axes;
|
||||
|
||||
int num = getAxisCount(index);
|
||||
axes.reserve(count);
|
||||
|
||||
for (int i = 0; i<num; i++)
|
||||
lua_pushnumber(L, clampval(((float)SDL_JoystickGetAxis(joysticks[index], i))/32768.0f));
|
||||
return num;
|
||||
for (int i = 0; i < count; i++)
|
||||
axes.push_back(clampval(((float) SDL_JoystickGetAxis(joyhandle, i))/32768.0f));
|
||||
|
||||
return axes;
|
||||
}
|
||||
|
||||
bool Joystick::isDown(int index, int *buttonlist)
|
||||
Joystick::Hat Joystick::getHat(int hatindex) const
|
||||
{
|
||||
if (!verifyJoystick(index))
|
||||
Hat h = HAT_INVALID;
|
||||
|
||||
if (!isConnected() || hatindex < 0 || hatindex >= getHatCount())
|
||||
return h;
|
||||
|
||||
getConstant(SDL_JoystickGetHat(joyhandle, hatindex), h);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
bool Joystick::isDown(const std::vector<int> &buttonlist) const
|
||||
{
|
||||
if (!isConnected())
|
||||
return false;
|
||||
|
||||
int num = getButtonCount(index);
|
||||
int num = getButtonCount();
|
||||
|
||||
for (int button = *buttonlist; button != -1; button = *(++buttonlist))
|
||||
for (size_t i = 0; i < buttonlist.size(); i++)
|
||||
{
|
||||
if (button >= 0 && button < num && SDL_JoystickGetButton(joysticks[index], button) == 1)
|
||||
int button = buttonlist[i];
|
||||
if (button >= 0 && button < num && SDL_JoystickGetButton(joyhandle, button) == 1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Joystick::Hat Joystick::getHat(int index, int hat)
|
||||
bool Joystick::openGamepad(int deviceindex)
|
||||
{
|
||||
Hat h = HAT_INVALID;
|
||||
if (!SDL_IsGameController(deviceindex))
|
||||
return false;
|
||||
|
||||
if (!verifyJoystick(index))
|
||||
return h;
|
||||
if (isGamepad())
|
||||
{
|
||||
SDL_GameControllerClose(controller);
|
||||
controller = 0;
|
||||
}
|
||||
|
||||
if (hat >= getHatCount(index))
|
||||
return h;
|
||||
|
||||
hats.find(SDL_JoystickGetHat(joysticks[index], hat), h);
|
||||
|
||||
return h;
|
||||
controller = SDL_GameControllerOpen(deviceindex);
|
||||
return isGamepad();
|
||||
}
|
||||
|
||||
void Joystick::close(int index)
|
||||
bool Joystick::isGamepad() const
|
||||
{
|
||||
if (!checkIndex(index))
|
||||
return;
|
||||
return controller != 0;
|
||||
}
|
||||
|
||||
if (joysticks[index]!=0)
|
||||
float Joystick::getGamepadAxis(love::joystick::Joystick::GamepadAxis axis) const
|
||||
{
|
||||
if (!isConnected() || !isGamepad())
|
||||
return 0.f;
|
||||
|
||||
SDL_GameControllerAxis sdlaxis;
|
||||
if (!getConstant(axis, sdlaxis))
|
||||
return 0.f;
|
||||
|
||||
Sint16 value = SDL_GameControllerGetAxis(controller, sdlaxis);
|
||||
|
||||
return clampval((float) value / 32768.0f);
|
||||
}
|
||||
|
||||
bool Joystick::isGamepadDown(const std::vector<GamepadButton> &blist) const
|
||||
{
|
||||
if (!isConnected() || !isGamepad())
|
||||
return false;
|
||||
|
||||
SDL_GameControllerButton sdlbutton;
|
||||
|
||||
for (size_t i = 0; i < blist.size(); i++)
|
||||
{
|
||||
SDL_JoystickClose(joysticks[index]);
|
||||
joysticks[index] = 0;
|
||||
if (!getConstant(blist[i], sdlbutton))
|
||||
continue;
|
||||
|
||||
if (SDL_GameControllerGetButton(controller, sdlbutton) == 1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void *Joystick::getHandle() const
|
||||
{
|
||||
return joyhandle;
|
||||
}
|
||||
|
||||
std::string Joystick::getGUID() const
|
||||
{
|
||||
// SDL2's GUIDs identify *classes* of devices, instead of unique devices.
|
||||
return guid;
|
||||
}
|
||||
|
||||
int Joystick::getInstanceID() const
|
||||
{
|
||||
return instanceid;
|
||||
}
|
||||
|
||||
int Joystick::getID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Uint8 in, Joystick::Hat &out)
|
||||
{
|
||||
return hats.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::Hat in, Uint8 &out)
|
||||
{
|
||||
return hats.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(SDL_GameControllerAxis in, Joystick::GamepadAxis &out)
|
||||
{
|
||||
return gpAxes.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::GamepadAxis in, SDL_GameControllerAxis &out)
|
||||
{
|
||||
return gpAxes.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(SDL_GameControllerButton in, Joystick::GamepadButton &out)
|
||||
{
|
||||
return gpButtons.find(in, out);
|
||||
}
|
||||
|
||||
bool Joystick::getConstant(Joystick::GamepadButton in, SDL_GameControllerButton &out)
|
||||
{
|
||||
return gpButtons.find(in, out);
|
||||
}
|
||||
|
||||
EnumMap<Joystick::Hat, Uint8, Joystick::HAT_MAX_ENUM>::Entry Joystick::hatEntries[] =
|
||||
@@ -247,6 +298,39 @@ EnumMap<Joystick::Hat, Uint8, Joystick::HAT_MAX_ENUM>::Entry Joystick::hatEntrie
|
||||
|
||||
EnumMap<Joystick::Hat, Uint8, Joystick::HAT_MAX_ENUM> Joystick::hats(Joystick::hatEntries, sizeof(Joystick::hatEntries));
|
||||
|
||||
EnumMap<Joystick::GamepadAxis, SDL_GameControllerAxis, Joystick::GAMEPAD_AXIS_MAX_ENUM>::Entry Joystick::gpAxisEntries[] =
|
||||
{
|
||||
{Joystick::GAMEPAD_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTX},
|
||||
{Joystick::GAMEPAD_AXIS_LEFTY, SDL_CONTROLLER_AXIS_LEFTY},
|
||||
{Joystick::GAMEPAD_AXIS_RIGHTX, SDL_CONTROLLER_AXIS_RIGHTX},
|
||||
{Joystick::GAMEPAD_AXIS_RIGHTY, SDL_CONTROLLER_AXIS_RIGHTY},
|
||||
{Joystick::GAMEPAD_AXIS_TRIGGERLEFT, SDL_CONTROLLER_AXIS_TRIGGERLEFT},
|
||||
{Joystick::GAMEPAD_AXIS_TRIGGERRIGHT, SDL_CONTROLLER_AXIS_TRIGGERRIGHT},
|
||||
};
|
||||
|
||||
EnumMap<Joystick::GamepadAxis, SDL_GameControllerAxis, Joystick::GAMEPAD_AXIS_MAX_ENUM> Joystick::gpAxes(Joystick::gpAxisEntries, sizeof(Joystick::gpAxisEntries));
|
||||
|
||||
EnumMap<Joystick::GamepadButton, SDL_GameControllerButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM>::Entry Joystick::gpButtonEntries[] =
|
||||
{
|
||||
{Joystick::GAMEPAD_BUTTON_A, SDL_CONTROLLER_BUTTON_A},
|
||||
{Joystick::GAMEPAD_BUTTON_B, SDL_CONTROLLER_BUTTON_B},
|
||||
{Joystick::GAMEPAD_BUTTON_X, SDL_CONTROLLER_BUTTON_X},
|
||||
{Joystick::GAMEPAD_BUTTON_Y, SDL_CONTROLLER_BUTTON_Y},
|
||||
{Joystick::GAMEPAD_BUTTON_BACK, SDL_CONTROLLER_BUTTON_BACK},
|
||||
{Joystick::GAMEPAD_BUTTON_GUIDE, SDL_CONTROLLER_BUTTON_GUIDE},
|
||||
{Joystick::GAMEPAD_BUTTON_START, SDL_CONTROLLER_BUTTON_START},
|
||||
{Joystick::GAMEPAD_BUTTON_LEFTSTICK, SDL_CONTROLLER_BUTTON_LEFTSTICK},
|
||||
{Joystick::GAMEPAD_BUTTON_RIGHTSTICK, SDL_CONTROLLER_BUTTON_RIGHTSTICK},
|
||||
{Joystick::GAMEPAD_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||
{Joystick::GAMEPAD_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||
{Joystick::GAMEPAD_BUTTON_DPAD_UP, SDL_CONTROLLER_BUTTON_DPAD_UP},
|
||||
{Joystick::GAMEPAD_BUTTON_DPAD_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN},
|
||||
{Joystick::GAMEPAD_BUTTON_DPAD_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
|
||||
{Joystick::GAMEPAD_BUTTON_DPAD_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
|
||||
};
|
||||
|
||||
EnumMap<Joystick::GamepadButton, SDL_GameControllerButton, Joystick::GAMEPAD_BUTTON_MAX_ENUM> Joystick::gpButtons(Joystick::gpButtonEntries, sizeof(Joystick::gpButtonEntries));
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
} // love
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#include "common/EnumMap.h"
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
#include <SDL_joystick.h>
|
||||
#include <SDL_gamecontroller.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -37,38 +38,74 @@ namespace sdl
|
||||
|
||||
class Joystick : public love::joystick::Joystick
|
||||
{
|
||||
private:
|
||||
SDL_Joystick **joysticks;
|
||||
public:
|
||||
Joystick();
|
||||
|
||||
Joystick(int id);
|
||||
Joystick(int id, int joyindex);
|
||||
|
||||
virtual ~Joystick();
|
||||
|
||||
// Implements Module.
|
||||
bool open(int deviceindex);
|
||||
void close();
|
||||
|
||||
bool isConnected() const;
|
||||
|
||||
const char *getName() const;
|
||||
|
||||
void reload();
|
||||
bool checkIndex(int index);
|
||||
int getJoystickCount();
|
||||
const char *getName(int index);
|
||||
bool open(int index);
|
||||
bool isOpen(int index);
|
||||
bool verifyJoystick(int index);
|
||||
int getAxisCount(int index);
|
||||
int getButtonCount(int index);
|
||||
int getHatCount(int index);
|
||||
float clampval(float x);
|
||||
float getAxis(int index, int axis);
|
||||
int getAxes(lua_State *L);
|
||||
bool isDown(int index, int *buttonlist);
|
||||
Hat getHat(int index, int hat);
|
||||
void close(int index);
|
||||
int getAxisCount() const;
|
||||
int getButtonCount() const;
|
||||
int getHatCount() const;
|
||||
|
||||
float getAxis(int axisindex) const;
|
||||
std::vector<float> getAxes() const;
|
||||
Hat getHat(int hatindex) const;
|
||||
|
||||
bool isDown(const std::vector<int> &buttonlist) const;
|
||||
|
||||
bool openGamepad(int deviceindex);
|
||||
bool isGamepad() const;
|
||||
|
||||
float getGamepadAxis(GamepadAxis axis) const;
|
||||
bool isGamepadDown(const std::vector<GamepadButton> &blist) const;
|
||||
|
||||
void *getHandle() const;
|
||||
|
||||
std::string getGUID() const;
|
||||
int getInstanceID() const;
|
||||
int getID() const;
|
||||
|
||||
static bool getConstant(Hat in, Uint8 &out);
|
||||
static bool getConstant(Uint8 in, Hat &out);
|
||||
|
||||
static bool getConstant(SDL_GameControllerAxis in, GamepadAxis &out);
|
||||
static bool getConstant(GamepadAxis in, SDL_GameControllerAxis &out);
|
||||
|
||||
static bool getConstant(SDL_GameControllerButton in, GamepadButton &out);
|
||||
static bool getConstant(GamepadButton in, SDL_GameControllerButton &out);
|
||||
|
||||
private:
|
||||
|
||||
Joystick() {}
|
||||
|
||||
SDL_Joystick *joyhandle;
|
||||
SDL_GameController *controller;
|
||||
|
||||
SDL_JoystickID instanceid;
|
||||
std::string guid;
|
||||
int id;
|
||||
|
||||
std::string name;
|
||||
|
||||
static EnumMap<Hat, Uint8, Joystick::HAT_MAX_ENUM>::Entry hatEntries[];
|
||||
static EnumMap<Hat, Uint8, Joystick::HAT_MAX_ENUM> hats;
|
||||
|
||||
}; // Joystick
|
||||
static EnumMap<GamepadAxis, SDL_GameControllerAxis, GAMEPAD_AXIS_MAX_ENUM>::Entry gpAxisEntries[];
|
||||
static EnumMap<GamepadAxis, SDL_GameControllerAxis, GAMEPAD_AXIS_MAX_ENUM> gpAxes;
|
||||
|
||||
static EnumMap<GamepadButton, SDL_GameControllerButton, GAMEPAD_BUTTON_MAX_ENUM>::Entry gpButtonEntries[];
|
||||
static EnumMap<GamepadButton, SDL_GameControllerButton, GAMEPAD_BUTTON_MAX_ENUM> gpButtons;
|
||||
|
||||
};
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2013 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "common/config.h"
|
||||
#include "JoystickModule.h"
|
||||
#include "Joystick.h"
|
||||
|
||||
// SDL
|
||||
#include <SDL.h>
|
||||
|
||||
// C++
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
// C
|
||||
#include <cstdlib>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
JoystickModule::JoystickModule()
|
||||
{
|
||||
// Init the SDL Joystick and Game Controller systems.
|
||||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0)
|
||||
throw love::Exception("%s", SDL_GetError());
|
||||
|
||||
// Start joystick event watching. Joysticks are automatically added and
|
||||
// removed via love.event.
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
SDL_GameControllerEventState(SDL_ENABLE);
|
||||
}
|
||||
|
||||
JoystickModule::~JoystickModule()
|
||||
{
|
||||
// Close any open Joysticks.
|
||||
for (size_t i = 0; i < joysticks.size(); i++)
|
||||
{
|
||||
joysticks[i]->close();
|
||||
joysticks[i]->release();
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
|
||||
}
|
||||
|
||||
const char *JoystickModule::getName() const
|
||||
{
|
||||
return "love.joystick.sdl";
|
||||
}
|
||||
|
||||
love::joystick::Joystick *JoystickModule::getJoystick(int joyindex)
|
||||
{
|
||||
if (joyindex < 0 || (size_t) joyindex >= activeSticks.size())
|
||||
return 0;
|
||||
|
||||
return activeSticks[joyindex];
|
||||
}
|
||||
|
||||
int JoystickModule::getIndex(const love::joystick::Joystick *joystick)
|
||||
{
|
||||
for (size_t i = 0; i < activeSticks.size(); i++)
|
||||
{
|
||||
if (activeSticks[i] == joystick)
|
||||
return i;
|
||||
}
|
||||
|
||||
// Joystick is not connected.
|
||||
return -1;
|
||||
}
|
||||
|
||||
int JoystickModule::getJoystickCount() const
|
||||
{
|
||||
return (int) activeSticks.size();
|
||||
}
|
||||
|
||||
bool JoystickModule::isGamepad(int joyindex) const
|
||||
{
|
||||
if (joyindex < 0 || (size_t) joyindex >= activeSticks.size())
|
||||
return false;
|
||||
|
||||
return activeSticks[joyindex]->isGamepad();
|
||||
}
|
||||
|
||||
love::joystick::Joystick *JoystickModule::getJoystickFromID(int instanceid)
|
||||
{
|
||||
for (size_t i = 0; i < activeSticks.size(); i++)
|
||||
{
|
||||
if (instanceid == activeSticks[i]->getInstanceID())
|
||||
return activeSticks[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
love::joystick::Joystick *JoystickModule::addJoystick(int deviceindex)
|
||||
{
|
||||
if (deviceindex < 0 || deviceindex >= SDL_NumJoysticks())
|
||||
return 0;
|
||||
|
||||
std::string guidstr = getDeviceGUID(deviceindex);
|
||||
|
||||
joystick::Joystick *joystick = 0;
|
||||
|
||||
for (size_t i = 0; i < joysticks.size(); i++)
|
||||
{
|
||||
// Try to re-use a disconnected Joystick with the same GUID.
|
||||
if (!joysticks[i]->isConnected() && joysticks[i]->getGUID() == guidstr)
|
||||
{
|
||||
joystick = joysticks[i];
|
||||
joystick->open(deviceindex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!joystick)
|
||||
{
|
||||
// Make a new Joystick and add it to the persistent list, if we can't
|
||||
// re-use one.
|
||||
joystick = new Joystick(joysticks.size(), deviceindex);
|
||||
joysticks.push_back(joystick);
|
||||
}
|
||||
|
||||
// Add the Joystick to the connected list, if it's not there already.
|
||||
if (std::find(activeSticks.begin(), activeSticks.end(), joystick) == activeSticks.end())
|
||||
activeSticks.push_back(joystick);
|
||||
|
||||
return joystick;
|
||||
}
|
||||
|
||||
void JoystickModule::removeJoystick(love::joystick::Joystick *joystick)
|
||||
{
|
||||
if (!joystick)
|
||||
return;
|
||||
|
||||
// Close the Joystick and remove it from the active joystick list.
|
||||
std::vector<joystick::Joystick *>::iterator it = std::find(activeSticks.begin(), activeSticks.end(), joystick);
|
||||
if (it != activeSticks.end())
|
||||
{
|
||||
(*it)->close();
|
||||
activeSticks.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool JoystickModule::setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput)
|
||||
{
|
||||
// All SDL joystick GUID strings are 32 characters.
|
||||
if (guid.length() != 32)
|
||||
throw love::Exception("Invalid joystick GUID: %s", guid.c_str());
|
||||
|
||||
SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(guid.c_str());
|
||||
std::string mapstr;
|
||||
|
||||
char *sdlmapstr = SDL_GameControllerMappingForGUID(sdlguid);
|
||||
if (sdlmapstr)
|
||||
{
|
||||
mapstr = sdlmapstr;
|
||||
SDL_free(sdlmapstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a generic name if we have to create a new mapping string.
|
||||
mapstr = guid + ",Controller,";
|
||||
}
|
||||
|
||||
std::stringstream joyinputstream;
|
||||
Uint8 sdlhat;
|
||||
|
||||
// We can't have negative int values in the bind string.
|
||||
switch (joyinput.type)
|
||||
{
|
||||
case Joystick::INPUT_TYPE_AXIS:
|
||||
if (joyinput.axis >= 0)
|
||||
joyinputstream << "a" << joyinput.axis;
|
||||
break;
|
||||
case Joystick::INPUT_TYPE_BUTTON:
|
||||
if (joyinput.button >= 0)
|
||||
joyinputstream << "b" << joyinput.button;
|
||||
break;
|
||||
case Joystick::INPUT_TYPE_HAT:
|
||||
if (joyinput.hat.value >= 0 && Joystick::getConstant(joyinput.hat.value, sdlhat))
|
||||
joyinputstream << "h" << joyinput.hat.value << "." << int(sdlhat);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::string joyinputstr = joyinputstream.str();
|
||||
|
||||
if (joyinputstr.length() == 0)
|
||||
throw love::Exception("Invalid joystick input value.");
|
||||
|
||||
// SDL's name for the gamepad input value, e.g. "guide".
|
||||
std::string gpinputname = stringFromGamepadInput(gpinput);
|
||||
|
||||
// We should remove any existing joystick bind for this gamepad buttton/axis
|
||||
// so SDL's parser doesn't get mixed up.
|
||||
removeBindFromMapString(mapstr, joyinputstr);
|
||||
|
||||
// The string we'll be adding to the mapping string, e.g. "guide:b10,"
|
||||
std::string insertstr = gpinputname + ":" + joyinputstr + ",";
|
||||
|
||||
// We should replace any existing gamepad bind.
|
||||
size_t findpos = mapstr.find(gpinputname + ":");
|
||||
if (findpos != std::string::npos)
|
||||
{
|
||||
// The bind string ends at the next comma, or the end of the string.
|
||||
size_t endpos = mapstr.find_first_of(',', findpos);
|
||||
if (endpos == std::string::npos)
|
||||
endpos = mapstr.length() - 1;
|
||||
|
||||
mapstr.replace(findpos, endpos - findpos + 1, insertstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just append to the end if we don't need to replace anything.
|
||||
mapstr += insertstr;
|
||||
}
|
||||
|
||||
// 1 == added, 0 == updated, -1 == error.
|
||||
int status = SDL_GameControllerAddMapping(mapstr.c_str());
|
||||
|
||||
// FIXME: massive hack until missing APIs are added to SDL 2:
|
||||
// https://bugzilla.libsdl.org/show_bug.cgi?id=1975
|
||||
if (status == 1)
|
||||
checkGamepads(guid);
|
||||
|
||||
return status >= 0;
|
||||
}
|
||||
|
||||
Joystick::JoystickInput JoystickModule::getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput)
|
||||
{
|
||||
// All SDL joystick GUID strings are 32 characters.
|
||||
if (guid.length() != 32)
|
||||
throw love::Exception("Invalid joystick GUID: %s", guid.c_str());
|
||||
|
||||
Joystick::JoystickInput jinput;
|
||||
jinput.type = Joystick::INPUT_TYPE_MAX_ENUM;
|
||||
|
||||
SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(guid.c_str());
|
||||
|
||||
std::string mapstr;
|
||||
|
||||
char *sdlmapstr = SDL_GameControllerMappingForGUID(sdlguid);
|
||||
if (!sdlmapstr)
|
||||
return jinput;
|
||||
|
||||
mapstr = sdlmapstr;
|
||||
SDL_free(sdlmapstr);
|
||||
|
||||
std::string gpbindname = stringFromGamepadInput(gpinput);
|
||||
|
||||
size_t findpos = mapstr.find(std::string(",") + gpbindname + ":");
|
||||
if (findpos == std::string::npos)
|
||||
return jinput;
|
||||
|
||||
size_t endpos = mapstr.find_first_of(',', findpos);
|
||||
if (endpos == std::string::npos)
|
||||
{
|
||||
// Assume end-of-string if we can't find the next comma.
|
||||
endpos = mapstr.length() - 1;
|
||||
}
|
||||
|
||||
if (endpos >= mapstr.length())
|
||||
return jinput; // Something went wrong.
|
||||
|
||||
// Strip out the trailing comma from our search position, if it exists.
|
||||
if (mapstr[endpos] == ',')
|
||||
endpos--;
|
||||
|
||||
// New start position: comma + gamepadinputlength + ":".
|
||||
findpos += 1 + gpbindname.length() + 1;
|
||||
std::string jbindstr = mapstr.substr(findpos, endpos - findpos + 1);
|
||||
|
||||
jinput = JoystickInputFromString(jbindstr);
|
||||
return jinput;
|
||||
}
|
||||
|
||||
std::string JoystickModule::stringFromGamepadInput(Joystick::GamepadInput gpinput) const
|
||||
{
|
||||
SDL_GameControllerAxis sdlaxis;
|
||||
SDL_GameControllerButton sdlbutton;
|
||||
|
||||
const char *gpinputname = 0;
|
||||
|
||||
switch (gpinput.type)
|
||||
{
|
||||
case Joystick::INPUT_TYPE_AXIS:
|
||||
if (Joystick::getConstant(gpinput.axis, sdlaxis))
|
||||
gpinputname = SDL_GameControllerGetStringForAxis(sdlaxis);
|
||||
break;
|
||||
case Joystick::INPUT_TYPE_BUTTON:
|
||||
if (Joystick::getConstant(gpinput.button, sdlbutton))
|
||||
gpinputname = SDL_GameControllerGetStringForButton(sdlbutton);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!gpinputname)
|
||||
throw love::Exception("Invalid gamepad axis/button.");
|
||||
|
||||
return std::string(gpinputname);
|
||||
}
|
||||
|
||||
Joystick::JoystickInput JoystickModule::JoystickInputFromString(const std::string &str) const
|
||||
{
|
||||
Joystick::JoystickInput jinput;
|
||||
jinput.type = Joystick::INPUT_TYPE_MAX_ENUM;
|
||||
|
||||
// Return an invalid value rather than throwing an exception.
|
||||
if (str.length() < 2)
|
||||
return jinput;
|
||||
|
||||
// The input type will always be the first character in the string.
|
||||
char inputtype = str[0];
|
||||
std::string bindvalues = str.substr(1);
|
||||
|
||||
Uint8 sdlhat;
|
||||
switch (inputtype)
|
||||
{
|
||||
case 'a':
|
||||
jinput.type = Joystick::INPUT_TYPE_AXIS;
|
||||
jinput.axis = atoi(bindvalues.c_str());
|
||||
break;
|
||||
case 'b':
|
||||
jinput.type = Joystick::INPUT_TYPE_BUTTON;
|
||||
jinput.button = atoi(bindvalues.c_str());
|
||||
break;
|
||||
case 'h':
|
||||
// Hat string syntax is "index.value".
|
||||
if (bindvalues.length() < 3)
|
||||
break;
|
||||
jinput.type = Joystick::INPUT_TYPE_HAT;
|
||||
jinput.hat.index = atoi(bindvalues.substr(0, 1).c_str());
|
||||
sdlhat = (Uint8) atoi(bindvalues.substr(2, 1).c_str());
|
||||
if (!Joystick::getConstant(sdlhat, jinput.hat.value))
|
||||
{
|
||||
// Return an invalid value if we can't find the hat constant.
|
||||
jinput.type = Joystick::INPUT_TYPE_MAX_ENUM;
|
||||
return jinput;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return jinput;
|
||||
}
|
||||
|
||||
void JoystickModule::removeBindFromMapString(std::string &mapstr, const std::string &joybindstr) const
|
||||
{
|
||||
// Find the joystick part of the bind in the string.
|
||||
size_t joybindpos = mapstr.find(joybindstr + ",");
|
||||
if (joybindpos == std::string::npos)
|
||||
{
|
||||
joybindpos = mapstr.rfind(joybindstr);
|
||||
if (joybindpos != mapstr.length() - joybindstr.length())
|
||||
return;
|
||||
}
|
||||
|
||||
if (joybindpos == std::string::npos)
|
||||
return;
|
||||
|
||||
// Find the start of the entire bind.
|
||||
size_t bindstart = mapstr.rfind(',', joybindpos);
|
||||
if (bindstart != std::string::npos && bindstart < mapstr.length() - 1)
|
||||
{
|
||||
size_t bindend = mapstr.find(',', bindstart + 1);
|
||||
if (bindend == std::string::npos)
|
||||
bindend = mapstr.length() - 1;
|
||||
|
||||
// Replace it with an empty string (remove it.)
|
||||
mapstr.replace(bindstart, bindend - bindstart + 1, "");
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickModule::checkGamepads(const std::string &guid) const
|
||||
{
|
||||
// FIXME: massive hack until missing APIs are added to SDL 2:
|
||||
// https://bugzilla.libsdl.org/show_bug.cgi?id=1975
|
||||
|
||||
// Make sure all connected joysticks of a certain guid that are
|
||||
// gamepad-capable are opened as such.
|
||||
for (int d_index = 0; d_index < SDL_NumJoysticks(); d_index++)
|
||||
{
|
||||
if (!SDL_IsGameController(d_index))
|
||||
continue;
|
||||
|
||||
if (guid.compare(getDeviceGUID(d_index)) != 0)
|
||||
continue;
|
||||
|
||||
std::vector<love::joystick::Joystick *>::const_iterator it;
|
||||
for (it = activeSticks.begin(); it != activeSticks.end(); ++it)
|
||||
{
|
||||
if ((*it)->isGamepad() || guid.compare((*it)->getGUID()) != 0)
|
||||
continue;
|
||||
|
||||
// Big hack time: open the index as a game controller and compare
|
||||
// the underlying joystick handle to the active stick's.
|
||||
SDL_GameController *ctrl = SDL_GameControllerOpen(d_index);
|
||||
if (ctrl == NULL)
|
||||
continue;
|
||||
|
||||
SDL_Joystick *stick = SDL_GameControllerGetJoystick(ctrl);
|
||||
if (stick == (SDL_Joystick *) (*it)->getHandle())
|
||||
(*it)->openGamepad(d_index);
|
||||
|
||||
SDL_GameControllerClose(ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string JoystickModule::getDeviceGUID(int deviceindex) const
|
||||
{
|
||||
if (deviceindex < 0 || deviceindex >= SDL_NumJoysticks())
|
||||
return std::string("");
|
||||
|
||||
// SDL_JoystickGetGUIDString uses 32 bytes plus the null terminator.
|
||||
char guidstr[33] = {'\0'};
|
||||
|
||||
// SDL2's GUIDs identify *classes* of devices, instead of unique devices.
|
||||
SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(deviceindex);
|
||||
SDL_JoystickGetGUIDString(guid, guidstr, sizeof(guidstr));
|
||||
|
||||
return std::string(guidstr);
|
||||
}
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
} // love
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2013 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_JOYSTICK_SDL_JOYSTICK_MODULE_H
|
||||
#define LOVE_JOYSTICK_SDL_JOYSTICK_MODULE_H
|
||||
|
||||
// LOVE
|
||||
#include "joystick/JoystickModule.h"
|
||||
|
||||
// STL
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
class JoystickModule : public love::joystick::JoystickModule
|
||||
{
|
||||
public:
|
||||
|
||||
JoystickModule();
|
||||
virtual ~JoystickModule();
|
||||
|
||||
// Implements Module.
|
||||
const char *getName() const;
|
||||
|
||||
// Implements JoystickModule.
|
||||
love::joystick::Joystick *addJoystick(int deviceindex);
|
||||
void removeJoystick(love::joystick::Joystick *joystick);
|
||||
love::joystick::Joystick *getJoystickFromID(int instanceid);
|
||||
love::joystick::Joystick *getJoystick(int joyindex);
|
||||
int getIndex(const love::joystick::Joystick *joystick);
|
||||
int getJoystickCount() const;
|
||||
bool isGamepad(int joyindex) const;
|
||||
bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput);
|
||||
Joystick::JoystickInput getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput);
|
||||
|
||||
private:
|
||||
|
||||
std::string stringFromGamepadInput(Joystick::GamepadInput gpinput) const;
|
||||
Joystick::JoystickInput JoystickInputFromString(const std::string &str) const;
|
||||
void removeBindFromMapString(std::string &mapstr, const std::string &joybindstr) const;
|
||||
void checkGamepads(const std::string &guid) const;
|
||||
|
||||
// SDL2's GUIDs identify *classes* of devices, instead of unique devices.
|
||||
std::string getDeviceGUID(int deviceindex) const;
|
||||
|
||||
// Lists of currently connected Joysticks.
|
||||
std::vector<Joystick *> activeSticks;
|
||||
|
||||
// Persistent list of all Joysticks which have been connected at some point.
|
||||
std::vector<Joystick *> joysticks;
|
||||
|
||||
}; // JoystickModule
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
} // love
|
||||
|
||||
#endif // LOVE_JOYSTICK_SDL_JOYSTICK_MODULE_H
|
||||
@@ -18,7 +18,11 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
// LOVE
|
||||
#include "wrap_Joystick.h"
|
||||
#include "wrap_JoystickModule.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -27,141 +31,179 @@ namespace joystick
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
static Joystick *instance = 0;
|
||||
|
||||
int w_reload(lua_State *L)
|
||||
Joystick *luax_checkjoystick(lua_State *L, int idx)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance->reload();
|
||||
}
|
||||
catch(love::Exception &e)
|
||||
{
|
||||
return luaL_error(L, "%s", e.what());
|
||||
}
|
||||
return 0;
|
||||
return luax_checktype<Joystick>(L, idx, "Joystick", JOYSTICK_JOYSTICK_T);
|
||||
}
|
||||
|
||||
int w_getJoystickCount(lua_State *L)
|
||||
int w_Joystick_isConnected(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance->getJoystickCount());
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
luax_pushboolean(L, j->isConnected());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getName(lua_State *L)
|
||||
int w_Joystick_getName(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
lua_pushstring(L, instance->getName(index));
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
lua_pushstring(L, j->getName());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getAxisCount(lua_State *L)
|
||||
int w_Joystick_getID(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
lua_pushinteger(L, instance->getAxisCount(index));
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
lua_pushinteger(L, j->getID());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getButtonCount(lua_State *L)
|
||||
int w_Joystick_getGUID(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
lua_pushinteger(L, instance->getButtonCount(index));
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
luax_pushstring(L, j->getGUID());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getHatCount(lua_State *L)
|
||||
int w_Joystick_getAxisCount(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
lua_pushinteger(L, instance->getHatCount(index));
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
lua_pushinteger(L, j->getAxisCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getAxis(lua_State *L)
|
||||
int w_Joystick_getButtonCount(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
int axis = luaL_checkint(L, 2) - 1;
|
||||
lua_pushnumber(L, instance->getAxis(index, axis));
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
lua_pushinteger(L, j->getButtonCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getAxes(lua_State *L)
|
||||
int w_Joystick_getHatCount(lua_State *L)
|
||||
{
|
||||
return instance->getAxes(L);
|
||||
}
|
||||
|
||||
int w_isDown(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
int num = lua_gettop(L);
|
||||
|
||||
int *buttonlist = new int[num];
|
||||
int counter = 0;
|
||||
|
||||
for (int i = 1; i < num; i++)
|
||||
buttonlist[counter++] = luaL_checkint(L, i + 1) - 1;
|
||||
|
||||
buttonlist[counter] = -1;
|
||||
|
||||
luax_pushboolean(L, instance->isDown(index, buttonlist));
|
||||
delete[] buttonlist;
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
lua_pushinteger(L, j->getHatCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getHat(lua_State *L)
|
||||
int w_Joystick_getAxis(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1)-1;
|
||||
int hat = luaL_checkint(L, 2)-1;
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
int axisindex = luaL_checkint(L, 2) - 1;
|
||||
lua_pushnumber(L, j->getAxis(axisindex));
|
||||
return 1;
|
||||
}
|
||||
|
||||
Joystick::Hat h = instance->getHat(index, hat);
|
||||
int w_Joystick_getAxes(lua_State *L)
|
||||
{
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
std::vector<float> axes = j->getAxes();
|
||||
|
||||
for (size_t i = 0; i < axes.size(); i++)
|
||||
lua_pushnumber(L, axes[i]);
|
||||
|
||||
return (int) axes.size();
|
||||
}
|
||||
|
||||
int w_Joystick_getHat(lua_State *L)
|
||||
{
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
int hatindex = luaL_checkint(L, 2) - 1;
|
||||
|
||||
Joystick::Hat h = j->getHat(hatindex);
|
||||
|
||||
const char *direction = "";
|
||||
Joystick::getConstant(h, direction);
|
||||
lua_pushstring(L, direction);
|
||||
love::joystick::Joystick::getConstant(h, direction);
|
||||
|
||||
lua_pushstring(L, direction);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Joystick_isDown(lua_State *L)
|
||||
{
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
|
||||
luaL_checkinteger(L, 2);
|
||||
|
||||
std::vector<int> buttons;
|
||||
for (int i = 2; i <= lua_gettop(L); i++)
|
||||
buttons.push_back(luaL_checkint(L, i));
|
||||
|
||||
luax_pushboolean(L, j->isDown(buttons));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Joystick_isGamepad(lua_State *L)
|
||||
{
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
luax_pushboolean(L, j->isGamepad());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Joystick_getGamepadAxis(lua_State *L)
|
||||
{
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
|
||||
const char *str = luaL_checkstring(L, 2);
|
||||
Joystick::GamepadAxis axis;
|
||||
|
||||
if (!joystick::Joystick::getConstant(str, axis))
|
||||
return luaL_error(L, "Invalid gamepad axis: %s", str);
|
||||
|
||||
lua_pushnumber(L, j->getGamepadAxis(axis));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Joystick_isGamepadDown(lua_State *L)
|
||||
{
|
||||
Joystick *j = luax_checkjoystick(L, 1);
|
||||
|
||||
std::vector<Joystick::GamepadButton> buttons;
|
||||
buttons.reserve(lua_gettop(L) - 1);
|
||||
|
||||
luaL_checkstring(L, 2);
|
||||
|
||||
for (int i = 2; i <= lua_gettop(L); i++)
|
||||
{
|
||||
const char *str = luaL_checkstring(L, i);
|
||||
Joystick::GamepadButton button;
|
||||
|
||||
if (!joystick::Joystick::getConstant(str, button))
|
||||
return luaL_error(L, "Invalid gamepad button: %s", str);
|
||||
|
||||
buttons.push_back(button);
|
||||
}
|
||||
|
||||
luax_pushboolean(L, j->isGamepadDown(buttons));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "reload", w_reload },
|
||||
{ "getJoystickCount", w_getJoystickCount },
|
||||
{ "getName", w_getName },
|
||||
{ "getAxisCount", w_getAxisCount },
|
||||
{ "getButtonCount", w_getButtonCount },
|
||||
{ "getHatCount", w_getHatCount },
|
||||
{ "getAxis", w_getAxis },
|
||||
{ "getAxes", w_getAxes },
|
||||
{ "isDown", w_isDown },
|
||||
{ "getHat", w_getHat },
|
||||
{ 0, 0 }
|
||||
{ "isConnected", w_Joystick_isConnected },
|
||||
{ "getName", w_Joystick_getName },
|
||||
{ "getID", w_Joystick_getID },
|
||||
{ "getGUID", w_Joystick_getGUID },
|
||||
{ "getAxisCount", w_Joystick_getAxisCount },
|
||||
{ "getButtonCount", w_Joystick_getButtonCount },
|
||||
{ "getHatCount", w_Joystick_getHatCount },
|
||||
{ "getAxis", w_Joystick_getAxis },
|
||||
{ "getAxes", w_Joystick_getAxes },
|
||||
{ "getHat", w_Joystick_getHat },
|
||||
{ "isDown", w_Joystick_isDown },
|
||||
{ "isGamepad", w_Joystick_isGamepad },
|
||||
{ "getGamepadAxis", w_Joystick_getGamepadAxis },
|
||||
{ "isGamepadDown", w_Joystick_isGamepadDown },
|
||||
|
||||
// From wrap_JoystickModule.
|
||||
{ "getIndex", w_getIndex },
|
||||
{ "getGamepadMapping", w_getGamepadMapping },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
extern "C" int luaopen_love_joystick(lua_State *L)
|
||||
extern "C" int luaopen_joystick(lua_State *L)
|
||||
{
|
||||
if (instance == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance = new Joystick();
|
||||
}
|
||||
catch(Exception &e)
|
||||
{
|
||||
return luaL_error(L, e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
instance->retain();
|
||||
|
||||
|
||||
WrappedModule w;
|
||||
w.module = instance;
|
||||
w.name = "joystick";
|
||||
w.flags = MODULE_T;
|
||||
w.functions = functions;
|
||||
w.types = 0;
|
||||
|
||||
return luax_register_module(L, w);
|
||||
return luax_register_type(L, "Joystick", functions);
|
||||
}
|
||||
|
||||
} // sdl
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
// LOVE
|
||||
#include "common/config.h"
|
||||
#include "Joystick.h"
|
||||
#include "common/runtime.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -32,17 +33,22 @@ namespace joystick
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
int w_reload(lua_State *L);
|
||||
int w_getJoystickCount(lua_State *L);
|
||||
int w_getName(lua_State *L);
|
||||
int w_getAxisCount(lua_State *L);
|
||||
int w_getButtonCount(lua_State *L);
|
||||
int w_getHatCount(lua_State *L);
|
||||
int w_getAxis(lua_State *L);
|
||||
int w_getAxes(lua_State *L);
|
||||
int w_isDown(lua_State *L);
|
||||
int w_getHat(lua_State *L);
|
||||
extern "C" LOVE_EXPORT int luaopen_love_joystick(lua_State *L);
|
||||
Joystick *luax_checkjoystick(lua_State *L, int idx);
|
||||
int w_Joystick_isConnected(lua_State *L);
|
||||
int w_Joystick_getName(lua_State *L);
|
||||
int w_Joystick_getID(lua_State *L);
|
||||
int w_Joystick_getGUID(lua_State *L);
|
||||
int w_Joystick_getAxisCount(lua_State *L);
|
||||
int w_Joystick_getButtonCount(lua_State *L);
|
||||
int w_Joystick_getHatCount(lua_State *L);
|
||||
int w_Joystick_getAxis(lua_State *L);
|
||||
int w_Joystick_getAxes(lua_State *L);
|
||||
int w_Joystick_getHat(lua_State *L);
|
||||
int w_Joystick_isDown(lua_State *L);
|
||||
int w_Joystick_isGamepad(lua_State *L);
|
||||
int w_Joystick_getGamepadAxis(lua_State *L);
|
||||
int w_Joystick_isGamepadDown(lua_State *L);
|
||||
extern "C" int luaopen_joystick(lua_State *L);
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2013 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "wrap_JoystickModule.h"
|
||||
#include "wrap_Joystick.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
static JoystickModule *instance = 0;
|
||||
|
||||
int w_getJoystick(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
love::joystick::Joystick *stick = instance->getJoystick(index);
|
||||
|
||||
if (!stick)
|
||||
return luaL_error(L, "Invalid joystick index");
|
||||
|
||||
stick->retain();
|
||||
luax_newtype(L, "Joystick", JOYSTICK_JOYSTICK_T, (void *) stick);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getIndex(lua_State *L)
|
||||
{
|
||||
love::joystick::Joystick *j = luax_checkjoystick(L, 1);
|
||||
int index = instance->getIndex(j);
|
||||
if (index >= 0)
|
||||
lua_pushinteger(L, index + 1);
|
||||
else
|
||||
lua_pushinteger(L, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getJoystickCount(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance->getJoystickCount());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_isGamepad(lua_State *L)
|
||||
{
|
||||
int index = luaL_checkint(L, 1) - 1;
|
||||
luax_pushboolean(L, instance->isGamepad(index));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_setGamepadMapping(lua_State *L)
|
||||
{
|
||||
// Only accept a GUID string. We don't accept a Joystick object because
|
||||
// the gamepad mapping applies to all joysticks with the same GUID (e.g. all
|
||||
// Xbox 360 controllers on the system), rather than individual objects.
|
||||
std::string guid = luax_checkstring(L, 1);
|
||||
|
||||
const char *gpbindstr = luaL_checkstring(L, 2);
|
||||
Joystick::GamepadInput gpinput;
|
||||
|
||||
if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.axis))
|
||||
gpinput.type = Joystick::INPUT_TYPE_AXIS;
|
||||
else if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.button))
|
||||
gpinput.type = Joystick::INPUT_TYPE_BUTTON;
|
||||
else
|
||||
return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr);
|
||||
|
||||
const char *jinputtypestr = luaL_checkstring(L, 3);
|
||||
Joystick::JoystickInput jinput;
|
||||
|
||||
if (!love::joystick::Joystick::getConstant(jinputtypestr, jinput.type))
|
||||
return luaL_error(L, "Invalid joystick input type: %s", jinputtypestr);
|
||||
|
||||
const char *hatstr;
|
||||
switch (jinput.type)
|
||||
{
|
||||
case Joystick::INPUT_TYPE_AXIS:
|
||||
jinput.axis = luaL_checkint(L, 4) - 1;
|
||||
break;
|
||||
case Joystick::INPUT_TYPE_BUTTON:
|
||||
jinput.button = luaL_checkint(L, 4) - 1;
|
||||
break;
|
||||
case Joystick::INPUT_TYPE_HAT:
|
||||
// Hats need both a hat index and a hat value.
|
||||
jinput.hat.index = luaL_checkint(L, 4) - 1;
|
||||
hatstr = luaL_checkstring(L, 5);
|
||||
if (!love::joystick::Joystick::getConstant(hatstr, jinput.hat.value))
|
||||
return luaL_error(L, "Invalid joystick hat: %s", hatstr);
|
||||
break;
|
||||
default:
|
||||
return luaL_error(L, "Invalid joystick input type: %s", jinputtypestr);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
try
|
||||
{
|
||||
success = instance->setGamepadMapping(guid, gpinput, jinput);
|
||||
}
|
||||
catch (love::Exception &e)
|
||||
{
|
||||
return luaL_error(L, "%s", e.what());
|
||||
}
|
||||
luax_pushboolean(L, success);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getGamepadMapping(lua_State *L)
|
||||
{
|
||||
std::string guid;
|
||||
|
||||
// Accept either a GUID string or a Joystick object. This way we can re-use
|
||||
// the function for Joystick:getGamepadMapping.
|
||||
if (lua_type(L, 1) == LUA_TSTRING)
|
||||
guid = luax_checkstring(L, 1);
|
||||
else
|
||||
{
|
||||
love::joystick::Joystick *stick = luax_checkjoystick(L, 1);
|
||||
guid = stick->getGUID();
|
||||
}
|
||||
|
||||
const char *gpbindstr = luaL_checkstring(L, 2);
|
||||
Joystick::GamepadInput gpinput;
|
||||
|
||||
if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.axis))
|
||||
gpinput.type = Joystick::INPUT_TYPE_AXIS;
|
||||
else if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.button))
|
||||
gpinput.type = Joystick::INPUT_TYPE_BUTTON;
|
||||
else
|
||||
return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr);
|
||||
|
||||
Joystick::JoystickInput jinput;
|
||||
jinput.type = Joystick::INPUT_TYPE_MAX_ENUM;
|
||||
|
||||
try
|
||||
{
|
||||
jinput = instance->getGamepadMapping(guid, gpinput);
|
||||
}
|
||||
catch (love::Exception &e)
|
||||
{
|
||||
return luaL_error(L, "%s", e.what());
|
||||
}
|
||||
|
||||
if (jinput.type == Joystick::INPUT_TYPE_MAX_ENUM)
|
||||
return 0;
|
||||
|
||||
const char *inputtypestr;
|
||||
if (!love::joystick::Joystick::getConstant(jinput.type, inputtypestr))
|
||||
return luaL_error(L, "Unknown joystick input type.");
|
||||
|
||||
lua_pushstring(L, inputtypestr);
|
||||
|
||||
const char *hatstr;
|
||||
switch (jinput.type)
|
||||
{
|
||||
case Joystick::INPUT_TYPE_AXIS:
|
||||
lua_pushinteger(L, jinput.axis + 1);
|
||||
return 2;
|
||||
case Joystick::INPUT_TYPE_BUTTON:
|
||||
lua_pushinteger(L, jinput.button + 1);
|
||||
return 2;
|
||||
case Joystick::INPUT_TYPE_HAT:
|
||||
lua_pushinteger(L, jinput.hat.index + 1);
|
||||
if (love::joystick::Joystick::getConstant(jinput.hat.value, hatstr))
|
||||
{
|
||||
lua_pushstring(L, hatstr);
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
return luaL_error(L, "Unknown joystick hat.");
|
||||
default:
|
||||
break; // ?
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "getJoystick", w_getJoystick },
|
||||
{ "getIndex", w_getIndex },
|
||||
{ "getJoystickCount", w_getJoystickCount },
|
||||
{ "isGamepad", w_isGamepad },
|
||||
{ "setGamepadMapping", w_setGamepadMapping },
|
||||
{ "getGamepadMapping", w_getGamepadMapping },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const lua_CFunction types[] =
|
||||
{
|
||||
luaopen_joystick,
|
||||
0,
|
||||
};
|
||||
|
||||
extern "C" int luaopen_love_joystick(lua_State *L)
|
||||
{
|
||||
if (instance == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance = new JoystickModule();
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
return luaL_error(L, e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
instance->retain();
|
||||
|
||||
|
||||
WrappedModule w;
|
||||
w.module = instance;
|
||||
w.name = "joystick";
|
||||
w.flags = MODULE_T;
|
||||
w.functions = functions;
|
||||
w.types = types;
|
||||
|
||||
return luax_register_module(L, w);
|
||||
}
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
} // love
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2013 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_JOYSTICK_SDL_WRAP_JOYSTICK_MODULE_H
|
||||
#define LOVE_JOYSTICK_SDL_WRAP_JOYSTICK_MODULE_H
|
||||
|
||||
// LOVE
|
||||
#include "common/config.h"
|
||||
#include "JoystickModule.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace joystick
|
||||
{
|
||||
namespace sdl
|
||||
{
|
||||
|
||||
int w_getJoystick(lua_State *L);
|
||||
int w_getIndex(lua_State *L);
|
||||
int w_getJoystickCount(lua_State *L);
|
||||
int w_isGamepad(lua_State *L);
|
||||
int w_setGamepadMapping(lua_State *L);
|
||||
int w_getGamepadMapping(lua_State *L);
|
||||
extern "C" LOVE_EXPORT int luaopen_love_joystick(lua_State *L);
|
||||
|
||||
} // sdl
|
||||
} // joystick
|
||||
} // love
|
||||
|
||||
#endif // LOVE_JOYSTICK_SDL_WRAP_JOYSTICK_MODULE_H
|
||||
Reference in New Issue
Block a user