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:
Alex Szpakowski
2013-08-25 16:51:42 -03:00
parent 035130533b
commit 113ed1cfe7
67 changed files with 4691 additions and 1665 deletions
+4 -2
View File
@@ -26,12 +26,14 @@ namespace love
const char REFERENCE_TABLE_NAME[] = "love-references";
Reference::Reference()
: L(0), idx(LUA_REFNIL)
: L(0)
, idx(LUA_REFNIL)
{
}
Reference::Reference(lua_State *L)
: L(0), idx(LUA_REFNIL)
: L(L)
, idx(LUA_REFNIL)
{
ref(L);
}
+1
View File
@@ -72,6 +72,7 @@
#if defined(LOVE_MACOSX)
# define LOVE_LEGENDARY_LIBSTDCXX_HACK
# define LOVE_LEGENDARY_APP_ARGV_HACK
#endif
// Autotools config.h
+6
View File
@@ -571,6 +571,9 @@ StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[] =
{"ImageData", IMAGE_IMAGE_DATA_ID},
{"CompressedData", IMAGE_COMPRESSED_DATA_ID},
// Joystick
{"Joystick", JOYSTICK_JOYSTICK_ID},
// Math
{"RandomGenerator", MATH_RANDOM_GENERATOR_ID},
{"BezierCurve", MATH_BEZIER_CURVE_ID},
@@ -582,6 +585,9 @@ StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[] =
{"SoundData", SOUND_SOUND_DATA_ID},
{"Decoder", SOUND_DECODER_ID},
// Mouse
{"Cursor", MOUSE_CURSOR_ID},
// Physics
{"World", PHYSICS_WORLD_ID},
{"Contact", PHYSICS_CONTACT_ID},
+12
View File
@@ -58,6 +58,9 @@ enum Type
IMAGE_IMAGE_DATA_ID,
IMAGE_COMPRESSED_DATA_ID,
// Joystick
JOYSTICK_JOYSTICK_ID,
// Math
MATH_RANDOM_GENERATOR_ID,
MATH_BEZIER_CURVE_ID,
@@ -69,6 +72,9 @@ enum Type
SOUND_SOUND_DATA_ID,
SOUND_DECODER_ID,
// Mouse
MOUSE_CURSOR_ID,
// Physics
PHYSICS_WORLD_ID,
PHYSICS_CONTACT_ID,
@@ -135,6 +141,9 @@ const bits GRAPHICS_SHADER_T = (bits(1) << GRAPHICS_SHADER_ID) | OBJECT_T;
const bits IMAGE_IMAGE_DATA_T = (bits(1) << IMAGE_IMAGE_DATA_ID) | DATA_T;
const bits IMAGE_COMPRESSED_DATA_T = (bits(1) << IMAGE_COMPRESSED_DATA_ID) | DATA_T;
// Joystick.
const bits JOYSTICK_JOYSTICK_T = (bits(1) << JOYSTICK_JOYSTICK_ID) | OBJECT_T;
// Math.
const bits MATH_RANDOM_GENERATOR_T = (bits(1) << MATH_RANDOM_GENERATOR_ID) | OBJECT_T;
const bits MATH_BEZIER_CURVE_T = (bits(1) << MATH_BEZIER_CURVE_ID) | OBJECT_T;
@@ -146,6 +155,9 @@ const bits AUDIO_SOURCE_T = (bits(1) << AUDIO_SOURCE_ID) | OBJECT_T;
const bits SOUND_SOUND_DATA_T = (bits(1) << SOUND_SOUND_DATA_ID) | DATA_T;
const bits SOUND_DECODER_T = bits(1) << SOUND_DECODER_ID;
// Mouse.
const bits MOUSE_CURSOR_T = (bits(1) << MOUSE_CURSOR_ID) | OBJECT_T;
// Physics.
const bits PHYSICS_WORLD_T = (bits(1) << PHYSICS_WORLD_ID) | OBJECT_T;
const bits PHYSICS_CONTACT_T = (bits(1) << PHYSICS_CONTACT_ID) | OBJECT_T;
+62 -2
View File
@@ -34,6 +34,10 @@ extern "C" {
#include <windows.h>
#endif // LOVE_WINDOWS
#ifdef LOVE_MACOSX
#include "osx.h"
#endif // LOVE_MACOSX
#ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK
void get_utf8_arguments(int &argc, char **&argv)
@@ -71,6 +75,54 @@ void get_utf8_arguments(int &argc, char **&argv)
#endif // LOVE_LEGENDARY_UTF8_ARGV_HACK
#ifdef LOVE_LEGENDARY_APP_ARGV_HACK
#include <vector>
static void get_app_arguments(int argc, char **argv, int &new_argc, char **&new_argv)
{
std::vector<std::string> temp_argv;
for (int i = 0; i < argc; i++)
{
// Don't copy -psn_xxx argument from argv.
if (i == 0 || strncmp(argv[i], "-psn_", 5) != 0)
temp_argv.push_back(std::string(argv[i]));
}
// Check for a drop file string.
std::string dropfilestr = love::osx::checkDropEvents();
if (!dropfilestr.empty())
{
temp_argv.insert(temp_argv.begin() + 1, dropfilestr);
}
else
{
// If it exists, add the love file in love.app/Contents/Resources/ to argv.
std::string loveResourcesPath = love::osx::getLoveInResources();
if (!loveResourcesPath.empty())
{
// Run in pseudo-fused mode.
std::vector<std::string>::iterator it = temp_argv.begin();
it = temp_argv.insert(it + 1, loveResourcesPath);
temp_argv.insert(it + 1, std::string("--fused"));
}
}
// Copy temp argv vector to new argv array.
new_argc = (int) temp_argv.size();
new_argv = new char *[new_argc+1];
for (int i = 0; i < new_argc; i++)
{
new_argv[i] = new char[temp_argv[i].length() + 1];
strcpy(new_argv[i], temp_argv[i].c_str());
}
new_argv[new_argc+1] = NULL;
}
#endif // LOVE_LEGENDARY_APP_ARGV_HACK
static int love_preload(lua_State *L, lua_CFunction f, const char *name)
{
lua_getglobal(L, "package");
@@ -90,6 +142,14 @@ int main(int argc, char **argv)
argv = hack_argv;
#endif // LOVE_LEGENDARY_UTF8_ARGV_HACK
#ifdef LOVE_LEGENDARY_APP_ARGV_HACK
int hack_argc = 0;
char **hack_argv = 0;
get_app_arguments(argc, argv, hack_argc, hack_argv);
argc = hack_argc;
argv = hack_argv;
#endif // LOVE_LEGENDARY_APP_ARGV_HACK
// Oh, you just want the version? Okay!
if (argc > 1 && strcmp(argv[1],"--version") == 0)
{
@@ -148,14 +208,14 @@ int main(int argc, char **argv)
lua_close(L);
#ifdef LOVE_LEGENDARY_UTF8_ARGV_HACK
#if defined(LOVE_LEGENDARY_UTF8_ARGV_HACK) || defined(LOVE_LEGENDARY_APP_ARGV_HACK)
if (hack_argv)
{
for (int i = 0; i<hack_argc; ++i)
delete [] hack_argv[i];
delete [] hack_argv;
}
#endif // LOVE_LEGENDARY_UTF8_ARGV_HACK
#endif // LOVE_LEGENDARY_UTF8_ARGV_HACK || LOVE_LEGENDARY_APP_ARGV_HACK
return retval;
}
+445 -238
View File
@@ -22,11 +22,13 @@
#include "keyboard/Keyboard.h"
#include "mouse/Mouse.h"
#include "libraries/utf8/utf8.h"
#include "joystick/JoystickModule.h"
#include "joystick/sdl/Joystick.h"
#include "graphics/Graphics.h"
#include "window/Window.h"
#include "common/Exception.h"
#include <cmath>
#include <cstddef>
namespace love
{
@@ -42,7 +44,13 @@ const char *Event::getName() const
Event::Event()
{
SDL_EnableUNICODE(1);
if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0)
throw love::Exception("%s", SDL_GetError());
}
Event::~Event()
{
SDL_QuitSubSystem(SDL_INIT_EVENTS);
}
void Event::pump()
@@ -50,7 +58,6 @@ void Event::pump()
SDL_PumpEvents();
static SDL_Event e;
SDL_EnableUNICODE(1);
Message *msg;
@@ -86,46 +93,65 @@ void Event::clear()
love::event::Event::clear();
}
Message *Event::convert(SDL_Event &e)
Message *Event::convert(const SDL_Event &e) const
{
Message *msg = 0;
Message *msg = NULL;
love::keyboard::Keyboard::Key key;
love::mouse::Mouse::Button button;
love::joystick::Joystick::Hat hat;
Variant *arg1 = 0, *arg2 = 0, *arg3 = 0;
Variant *arg1, *arg2, *arg3;
const char *txt;
std::map<SDL_Keycode, love::keyboard::Keyboard::Key>::const_iterator keyit;
switch (e.type)
{
case SDL_KEYDOWN:
if (!keys.find(e.key.keysym.sym, key))
keyit = keys.find(e.key.keysym.sym);
if (keyit != keys.end())
key = keyit->second;
else
key = love::keyboard::Keyboard::KEY_UNKNOWN;
if (!love::keyboard::Keyboard::getConstant(key, txt))
txt = "unknown";
arg1 = new Variant(txt, strlen(txt));
txt = convertUnicode(e.key.keysym.unicode);
// We don't want to send unprintable unicode text.
if (txt && (txt[0] >= ' ' && txt[0] != 127))
{
arg2 = new Variant(txt, strlen(txt));
msg = new Message("keypressed", arg1, arg2);
arg2->release();
}
else
msg = new Message("keypressed", arg1);
arg2 = new Variant(e.key.repeat == SDL_TRUE);
msg = new Message("keypressed", arg1, arg2);
arg1->release();
arg2->release();
break;
case SDL_KEYUP:
if (!keys.find(e.key.keysym.sym, key))
keyit = keys.find(e.key.keysym.sym);
if (keyit != keys.end())
key = keyit->second;
else
key = love::keyboard::Keyboard::KEY_UNKNOWN;
if (!love::keyboard::Keyboard::getConstant(key, txt))
txt = "unknown";
arg1 = new Variant(txt, strlen(txt));
msg = new Message("keyreleased", arg1);
arg1->release();
break;
case SDL_TEXTINPUT:
txt = e.text.text;
arg1 = new Variant(txt, strlen(txt));
msg = new Message("textinput", arg1);
arg1->release();
break;
case SDL_TEXTEDITING:
txt = e.edit.text;
arg1 = new Variant(txt, strlen(txt));
arg2 = new Variant((double) e.edit.start);
arg3 = new Variant((double) e.edit.length);
msg = new Message("textedit", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
if (buttons.find(e.button.button, button) && love::mouse::Mouse::getConstant(button, txt))
if (buttons.find(e.button.button, button) && mouse::Mouse::getConstant(button, txt))
{
arg1 = new Variant((double) e.button.x);
arg2 = new Variant((double) e.button.y);
@@ -138,9 +164,77 @@ Message *Event::convert(SDL_Event &e)
arg3->release();
}
break;
case SDL_MOUSEWHEEL:
if (e.wheel.y != 0)
{
button = (e.wheel.y > 0) ? mouse::Mouse::BUTTON_WHEELUP : mouse::Mouse::BUTTON_WHEELDOWN;
if (!love::mouse::Mouse::getConstant(button, txt))
break;
int mx, my;
SDL_GetMouseState(&mx, &my);
arg1 = new Variant((double) mx);
arg2 = new Variant((double) my);
arg3 = new Variant(txt, strlen(txt));
msg = new Message("mousepressed", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
}
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
arg1 = new Variant((double)(e.jbutton.which+1));
case SDL_JOYAXISMOTION:
case SDL_JOYBALLMOTION:
case SDL_JOYHATMOTION:
case SDL_JOYDEVICEADDED:
case SDL_JOYDEVICEREMOVED:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERAXISMOTION:
msg = convertJoystickEvent(e);
break;
case SDL_WINDOWEVENT:
msg = convertWindowEvent(e);
break;
case SDL_DROPFILE:
SDL_free(e.drop.file);
break;
case SDL_QUIT:
msg = new Message("quit");
break;
default:
break;
}
return msg;
}
Message *Event::convertJoystickEvent(const SDL_Event &e) const
{
joystick::JoystickModule *joymodule = (joystick::JoystickModule *) Module::findInstance("love.joystick.");
if (!joymodule)
return 0;
Message *msg = 0;
Proxy proxy;
love::joystick::Joystick::Hat hat;
love::joystick::Joystick::GamepadButton padbutton;
love::joystick::Joystick::GamepadAxis padaxis;
Variant *arg1, *arg2, *arg3;
const char *txt;
switch (e.type)
{
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
proxy.flags = JOYSTICK_JOYSTICK_T;
proxy.data = joymodule->getJoystickFromID(e.jbutton.which);
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant((double)(e.jbutton.button+1));
msg = new Message((e.type == SDL_JOYBUTTONDOWN) ?
"joystickpressed" : "joystickreleased",
@@ -150,7 +244,12 @@ Message *Event::convert(SDL_Event &e)
break;
case SDL_JOYAXISMOTION:
{
arg1 = new Variant((double)(e.jaxis.which+1));
proxy.flags = JOYSTICK_JOYSTICK_T;
proxy.data = joymodule->getJoystickFromID(e.jaxis.which);
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant((double)(e.jaxis.axis+1));
float value = e.jaxis.value / 32768.0f;
if (fabsf(value) < 0.001f) value = 0.0f;
@@ -164,52 +263,144 @@ Message *Event::convert(SDL_Event &e)
}
break;
case SDL_JOYHATMOTION:
if (hats.find(e.jhat.value, hat) && love::joystick::Joystick::getConstant(hat, txt))
if (!joystick::sdl::Joystick::getConstant(e.jhat.value, hat) || !joystick::Joystick::getConstant(hat, txt))
break;
proxy.flags = JOYSTICK_JOYSTICK_T;
proxy.data = joymodule->getJoystickFromID(e.jhat.which);
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant((double)(e.jhat.hat+1));
arg3 = new Variant(txt, strlen(txt));
msg = new Message("joystickhat", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
if (!joystick::sdl::Joystick::getConstant((SDL_GameControllerButton) e.cbutton.button, padbutton))
break;
if (!joystick::Joystick::getConstant(padbutton, txt))
break;
proxy.flags = JOYSTICK_JOYSTICK_T;
proxy.data = joymodule->getJoystickFromID(e.cbutton.which);
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant(txt, strlen(txt));
msg = new Message(e.type == SDL_CONTROLLERBUTTONDOWN ?
"gamepadpressed" : "gamepadreleased", arg1, arg2);
arg1->release();
arg2->release();
break;
case SDL_CONTROLLERAXISMOTION:
if (joystick::sdl::Joystick::getConstant((SDL_GameControllerAxis) e.caxis.axis, padaxis))
{
arg1 = new Variant((double)(e.jhat.which+1));
arg2 = new Variant((double)(e.jhat.hat+1));
arg3 = new Variant(txt, strlen(txt));
msg = new Message("joystickhat", arg1, arg2, arg3);
if (!joystick::Joystick::getConstant(padaxis, txt))
break;
proxy.flags = JOYSTICK_JOYSTICK_T;
proxy.data = joymodule->getJoystickFromID(e.caxis.which);
if (!proxy.data)
break;
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
arg2 = new Variant(txt, strlen(txt));
float value = e.jaxis.value / 32768.0f;
if (fabsf(value) < 0.001f) value = 0.0f;
if (value < -0.99f) value = -1.0f;
if (value > 0.99f) value = 1.0f;
arg3 = new Variant((double) value);
msg = new Message("gamepadaxis", arg1, arg2, arg3);
arg1->release();
arg2->release();
arg3->release();
}
break;
case SDL_ACTIVEEVENT:
case SDL_JOYDEVICEADDED:
// jdevice.which is the joystick device index.
proxy.data = joymodule->addJoystick(e.jdevice.which);
proxy.flags = JOYSTICK_JOYSTICK_T;
if (proxy.data)
{
// SDL can send multiple ACTIVEEVENTS in a single SDL_event... we
// have to work around that by re-sending the ones we miss.
SDL_Event e2 = e;
arg1 = new Variant(e.active.gain != 0);
if (e.active.state & SDL_APPINPUTFOCUS)
{
msg = new Message("focus", arg1);
e2.active.state &= ~SDL_APPINPUTFOCUS;
}
else if (e.active.state & SDL_APPMOUSEFOCUS)
{
msg = new Message("mousefocus", arg1);
e2.active.state &= ~SDL_APPMOUSEFOCUS;
}
else if (e.active.state & SDL_APPACTIVE)
{
msg = new Message("visible", arg1);
e2.active.state &= ~SDL_APPACTIVE;
}
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
msg = new Message("joystickadded", arg1);
arg1->release();
// Put any missing active events back in SDL's queue.
if (e2.active.state != 0)
SDL_PushEvent(&e2);
}
break;
case SDL_QUIT:
msg = new Message("quit");
case SDL_JOYDEVICEREMOVED:
// jdevice.which is the joystick instance ID now.
proxy.data = joymodule->getJoystickFromID(e.jdevice.which);
proxy.flags = JOYSTICK_JOYSTICK_T;
if (proxy.data)
{
joymodule->removeJoystick((joystick::Joystick *) proxy.data);
arg1 = new Variant(JOYSTICK_JOYSTICK_ID, (void *) &proxy);
msg = new Message("joystickremoved", arg1);
arg1->release();
}
break;
case SDL_VIDEORESIZE:
arg1 = new Variant((double) e.resize.w);
arg2 = new Variant((double) e.resize.h);
default:
break;
}
return msg;
}
Message *Event::convertWindowEvent(const SDL_Event &e) const
{
Message *msg = 0;
Variant *arg1, *arg2;
window::Window *win = 0;
if (e.type != SDL_WINDOWEVENT)
return 0;
switch (e.window.event)
{
case SDL_WINDOWEVENT_FOCUS_GAINED:
case SDL_WINDOWEVENT_FOCUS_LOST:
// Users won't expect the screensaver to activate if a game is in
// focus. Also, joystick input may not delay the screensaver timer.
if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
SDL_DisableScreenSaver();
else
SDL_EnableScreenSaver();
arg1 = new Variant(e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
msg = new Message("focus", arg1);
arg1->release();
break;
case SDL_WINDOWEVENT_ENTER:
case SDL_WINDOWEVENT_LEAVE:
arg1 = new Variant(e.window.event == SDL_WINDOWEVENT_ENTER);
msg = new Message("mousefocus", arg1);
arg1->release();
break;
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_HIDDEN:
arg1 = new Variant(e.window.event == SDL_WINDOWEVENT_SHOWN);
msg = new Message("visible", arg1);
arg1->release();
break;
case SDL_WINDOWEVENT_RESIZED:
win = (window::Window *) Module::findInstance("love.window.");
if (win)
{
win->onWindowResize(e.window.data1, e.window.data2);
graphics::Graphics *gfx = (graphics::Graphics *) Module::findInstance("love.graphics.");
if (gfx)
gfx->setViewportSize(e.window.data1, e.window.data2);
}
arg1 = new Variant((double) e.window.data1);
arg2 = new Variant((double) e.window.data2);
msg = new Message("resize", arg1, arg2);
arg1->release();
arg2->release();
@@ -219,205 +410,221 @@ Message *Event::convert(SDL_Event &e)
return msg;
}
const char *Event::convertUnicode(Uint16 codepoint) const
std::map<SDL_Keycode, love::keyboard::Keyboard::Key> Event::createKeyMap()
{
// A single unicode character can use up to 4 bytes.
static char str[5] = {'\0'};
ptrdiff_t length = 0;
using love::keyboard::Keyboard;
if (codepoint == 0)
return 0;
std::map<SDL_Keycode, Keyboard::Key> k;
char *end = utf8::unchecked::append(codepoint, str);
length = end - str;
k[SDLK_UNKNOWN] = Keyboard::KEY_UNKNOWN;
if (length <= 0 || !utf8::is_valid(str, str + length))
return 0;
k[SDLK_RETURN] = Keyboard::KEY_RETURN;
k[SDLK_ESCAPE] = Keyboard::KEY_ESCAPE;
k[SDLK_BACKSPACE] = Keyboard::KEY_BACKSPACE;
k[SDLK_TAB] = Keyboard::KEY_TAB;
k[SDLK_SPACE] = Keyboard::KEY_SPACE;
k[SDLK_EXCLAIM] = Keyboard::KEY_EXCLAIM;
k[SDLK_QUOTEDBL] = Keyboard::KEY_QUOTEDBL;
k[SDLK_HASH] = Keyboard::KEY_HASH;
k[SDLK_DOLLAR] = Keyboard::KEY_DOLLAR;
k[SDLK_AMPERSAND] = Keyboard::KEY_AMPERSAND;
k[SDLK_QUOTE] = Keyboard::KEY_QUOTE;
k[SDLK_LEFTPAREN] = Keyboard::KEY_LEFTPAREN;
k[SDLK_RIGHTPAREN] = Keyboard::KEY_RIGHTPAREN;
k[SDLK_ASTERISK] = Keyboard::KEY_ASTERISK;
k[SDLK_PLUS] = Keyboard::KEY_PLUS;
k[SDLK_COMMA] = Keyboard::KEY_COMMA;
k[SDLK_MINUS] = Keyboard::KEY_MINUS;
k[SDLK_PERIOD] = Keyboard::KEY_PERIOD;
k[SDLK_SLASH] = Keyboard::KEY_SLASH;
k[SDLK_0] = Keyboard::KEY_0;
k[SDLK_1] = Keyboard::KEY_1;
k[SDLK_2] = Keyboard::KEY_2;
k[SDLK_3] = Keyboard::KEY_3;
k[SDLK_4] = Keyboard::KEY_4;
k[SDLK_5] = Keyboard::KEY_5;
k[SDLK_6] = Keyboard::KEY_6;
k[SDLK_7] = Keyboard::KEY_7;
k[SDLK_8] = Keyboard::KEY_8;
k[SDLK_9] = Keyboard::KEY_9;
k[SDLK_COLON] = Keyboard::KEY_COLON;
k[SDLK_SEMICOLON] = Keyboard::KEY_SEMICOLON;
k[SDLK_LESS] = Keyboard::KEY_LESS;
k[SDLK_EQUALS] = Keyboard::KEY_EQUALS;
k[SDLK_GREATER] = Keyboard::KEY_GREATER;
k[SDLK_QUESTION] = Keyboard::KEY_QUESTION;
k[SDLK_AT] = Keyboard::KEY_AT;
// Zero out the rest of the string.
for (ptrdiff_t i = length; i < 5; i++)
str[i] = '\0';
k[SDLK_LEFTBRACKET] = Keyboard::KEY_LEFTBRACKET;
k[SDLK_BACKSLASH] = Keyboard::KEY_BACKSLASH;
k[SDLK_RIGHTBRACKET] = Keyboard::KEY_RIGHTBRACKET;
k[SDLK_CARET] = Keyboard::KEY_CARET;
k[SDLK_UNDERSCORE] = Keyboard::KEY_UNDERSCORE;
k[SDLK_BACKQUOTE] = Keyboard::KEY_BACKQUOTE;
k[SDLK_a] = Keyboard::KEY_A;
k[SDLK_b] = Keyboard::KEY_B;
k[SDLK_c] = Keyboard::KEY_C;
k[SDLK_d] = Keyboard::KEY_D;
k[SDLK_e] = Keyboard::KEY_E;
k[SDLK_f] = Keyboard::KEY_F;
k[SDLK_g] = Keyboard::KEY_G;
k[SDLK_h] = Keyboard::KEY_H;
k[SDLK_i] = Keyboard::KEY_I;
k[SDLK_j] = Keyboard::KEY_J;
k[SDLK_k] = Keyboard::KEY_K;
k[SDLK_l] = Keyboard::KEY_L;
k[SDLK_m] = Keyboard::KEY_M;
k[SDLK_n] = Keyboard::KEY_N;
k[SDLK_o] = Keyboard::KEY_O;
k[SDLK_p] = Keyboard::KEY_P;
k[SDLK_q] = Keyboard::KEY_Q;
k[SDLK_r] = Keyboard::KEY_R;
k[SDLK_s] = Keyboard::KEY_S;
k[SDLK_t] = Keyboard::KEY_T;
k[SDLK_u] = Keyboard::KEY_U;
k[SDLK_v] = Keyboard::KEY_V;
k[SDLK_w] = Keyboard::KEY_W;
k[SDLK_x] = Keyboard::KEY_X;
k[SDLK_y] = Keyboard::KEY_Y;
k[SDLK_z] = Keyboard::KEY_Z;
return str;
k[SDLK_CAPSLOCK] = Keyboard::KEY_CAPSLOCK;
k[SDLK_F1] = Keyboard::KEY_F1;
k[SDLK_F2] = Keyboard::KEY_F2;
k[SDLK_F3] = Keyboard::KEY_F3;
k[SDLK_F4] = Keyboard::KEY_F4;
k[SDLK_F5] = Keyboard::KEY_F5;
k[SDLK_F6] = Keyboard::KEY_F6;
k[SDLK_F7] = Keyboard::KEY_F7;
k[SDLK_F8] = Keyboard::KEY_F8;
k[SDLK_F9] = Keyboard::KEY_F9;
k[SDLK_F10] = Keyboard::KEY_F10;
k[SDLK_F11] = Keyboard::KEY_F11;
k[SDLK_F12] = Keyboard::KEY_F12;
k[SDLK_PRINTSCREEN] = Keyboard::KEY_PRINTSCREEN;
k[SDLK_SCROLLLOCK] = Keyboard::KEY_SCROLLLOCK;
k[SDLK_PAUSE] = Keyboard::KEY_PAUSE;
k[SDLK_INSERT] = Keyboard::KEY_INSERT;
k[SDLK_HOME] = Keyboard::KEY_HOME;
k[SDLK_PAGEUP] = Keyboard::KEY_PAGEUP;
k[SDLK_DELETE] = Keyboard::KEY_DELETE;
k[SDLK_END] = Keyboard::KEY_END;
k[SDLK_PAGEDOWN] = Keyboard::KEY_PAGEDOWN;
k[SDLK_RIGHT] = Keyboard::KEY_RIGHT;
k[SDLK_LEFT] = Keyboard::KEY_LEFT;
k[SDLK_DOWN] = Keyboard::KEY_DOWN;
k[SDLK_UP] = Keyboard::KEY_UP;
k[SDLK_NUMLOCKCLEAR] = Keyboard::KEY_NUMLOCKCLEAR;
k[SDLK_KP_DIVIDE] = Keyboard::KEY_KP_DIVIDE;
k[SDLK_KP_MULTIPLY] = Keyboard::KEY_KP_MULTIPLY;
k[SDLK_KP_MINUS] = Keyboard::KEY_KP_MINUS;
k[SDLK_KP_PLUS] = Keyboard::KEY_KP_PLUS;
k[SDLK_KP_ENTER] = Keyboard::KEY_KP_ENTER;
k[SDLK_KP_0] = Keyboard::KEY_KP_0;
k[SDLK_KP_1] = Keyboard::KEY_KP_1;
k[SDLK_KP_2] = Keyboard::KEY_KP_2;
k[SDLK_KP_3] = Keyboard::KEY_KP_3;
k[SDLK_KP_4] = Keyboard::KEY_KP_4;
k[SDLK_KP_5] = Keyboard::KEY_KP_5;
k[SDLK_KP_6] = Keyboard::KEY_KP_6;
k[SDLK_KP_7] = Keyboard::KEY_KP_7;
k[SDLK_KP_8] = Keyboard::KEY_KP_8;
k[SDLK_KP_9] = Keyboard::KEY_KP_9;
k[SDLK_KP_PERIOD] = Keyboard::KEY_KP_PERIOD;
k[SDLK_KP_COMMA] = Keyboard::KEY_KP_COMMA;
k[SDLK_KP_EQUALS] = Keyboard::KEY_KP_EQUALS;
k[SDLK_APPLICATION] = Keyboard::KEY_APPLICATION;
k[SDLK_POWER] = Keyboard::KEY_POWER;
k[SDLK_F13] = Keyboard::KEY_F13;
k[SDLK_F14] = Keyboard::KEY_F14;
k[SDLK_F15] = Keyboard::KEY_F15;
k[SDLK_F16] = Keyboard::KEY_F16;
k[SDLK_F17] = Keyboard::KEY_F17;
k[SDLK_F18] = Keyboard::KEY_F18;
k[SDLK_F19] = Keyboard::KEY_F19;
k[SDLK_F20] = Keyboard::KEY_F20;
k[SDLK_F21] = Keyboard::KEY_F21;
k[SDLK_F22] = Keyboard::KEY_F22;
k[SDLK_F23] = Keyboard::KEY_F23;
k[SDLK_F24] = Keyboard::KEY_F24;
k[SDLK_EXECUTE] = Keyboard::KEY_EXECUTE;
k[SDLK_HELP] = Keyboard::KEY_HELP;
k[SDLK_MENU] = Keyboard::KEY_MENU;
k[SDLK_SELECT] = Keyboard::KEY_SELECT;
k[SDLK_STOP] = Keyboard::KEY_STOP;
k[SDLK_AGAIN] = Keyboard::KEY_AGAIN;
k[SDLK_UNDO] = Keyboard::KEY_UNDO;
k[SDLK_CUT] = Keyboard::KEY_CUT;
k[SDLK_COPY] = Keyboard::KEY_COPY;
k[SDLK_PASTE] = Keyboard::KEY_PASTE;
k[SDLK_FIND] = Keyboard::KEY_FIND;
k[SDLK_MUTE] = Keyboard::KEY_MUTE;
k[SDLK_VOLUMEUP] = Keyboard::KEY_VOLUMEUP;
k[SDLK_VOLUMEDOWN] = Keyboard::KEY_VOLUMEDOWN;
k[SDLK_ALTERASE] = Keyboard::KEY_ALTERASE;
k[SDLK_SYSREQ] = Keyboard::KEY_SYSREQ;
k[SDLK_CANCEL] = Keyboard::KEY_CANCEL;
k[SDLK_CLEAR] = Keyboard::KEY_CLEAR;
k[SDLK_PRIOR] = Keyboard::KEY_PRIOR;
k[SDLK_RETURN2] = Keyboard::KEY_RETURN2;
k[SDLK_SEPARATOR] = Keyboard::KEY_SEPARATOR;
k[SDLK_OUT] = Keyboard::KEY_OUT;
k[SDLK_OPER] = Keyboard::KEY_OPER;
k[SDLK_CLEARAGAIN] = Keyboard::KEY_CLEARAGAIN;
k[SDLK_THOUSANDSSEPARATOR] = Keyboard::KEY_THOUSANDSSEPARATOR;
k[SDLK_DECIMALSEPARATOR] = Keyboard::KEY_DECIMALSEPARATOR;
k[SDLK_CURRENCYUNIT] = Keyboard::KEY_CURRENCYUNIT;
k[SDLK_CURRENCYSUBUNIT] = Keyboard::KEY_CURRENCYSUBUNIT;
k[SDLK_LCTRL] = Keyboard::KEY_LCTRL;
k[SDLK_LSHIFT] = Keyboard::KEY_LSHIFT;
k[SDLK_LALT] = Keyboard::KEY_LALT;
k[SDLK_LGUI] = Keyboard::KEY_LGUI;
k[SDLK_RCTRL] = Keyboard::KEY_RCTRL;
k[SDLK_RSHIFT] = Keyboard::KEY_RSHIFT;
k[SDLK_RALT] = Keyboard::KEY_RALT;
k[SDLK_RGUI] = Keyboard::KEY_RGUI;
k[SDLK_MODE] = Keyboard::KEY_MODE;
k[SDLK_AUDIONEXT] = Keyboard::KEY_AUDIONEXT;
k[SDLK_AUDIOPREV] = Keyboard::KEY_AUDIOPREV;
k[SDLK_AUDIOSTOP] = Keyboard::KEY_AUDIOSTOP;
k[SDLK_AUDIOPLAY] = Keyboard::KEY_AUDIOPLAY;
k[SDLK_AUDIOMUTE] = Keyboard::KEY_AUDIOMUTE;
k[SDLK_MEDIASELECT] = Keyboard::KEY_MEDIASELECT;
k[SDLK_BRIGHTNESSDOWN] = Keyboard::KEY_BRIGHTNESSDOWN;
k[SDLK_BRIGHTNESSUP] = Keyboard::KEY_BRIGHTNESSUP;
k[SDLK_DISPLAYSWITCH] = Keyboard::KEY_DISPLAYSWITCH;
k[SDLK_KBDILLUMTOGGLE] = Keyboard::KEY_KBDILLUMTOGGLE;
k[SDLK_KBDILLUMDOWN] = Keyboard::KEY_KBDILLUMDOWN;
k[SDLK_KBDILLUMUP] = Keyboard::KEY_KBDILLUMUP;
k[SDLK_EJECT] = Keyboard::KEY_EJECT;
k[SDLK_SLEEP] = Keyboard::KEY_SLEEP;
return k;
}
EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry Event::keyEntries[] =
{
{ love::keyboard::Keyboard::KEY_BACKSPACE, SDLK_BACKSPACE},
{ love::keyboard::Keyboard::KEY_TAB, SDLK_TAB},
{ love::keyboard::Keyboard::KEY_CLEAR, SDLK_CLEAR},
{ love::keyboard::Keyboard::KEY_RETURN, SDLK_RETURN},
{ love::keyboard::Keyboard::KEY_PAUSE, SDLK_PAUSE},
{ love::keyboard::Keyboard::KEY_ESCAPE, SDLK_ESCAPE },
{ love::keyboard::Keyboard::KEY_SPACE, SDLK_SPACE },
{ love::keyboard::Keyboard::KEY_EXCLAIM, SDLK_EXCLAIM },
{ love::keyboard::Keyboard::KEY_QUOTEDBL, SDLK_QUOTEDBL },
{ love::keyboard::Keyboard::KEY_HASH, SDLK_HASH },
{ love::keyboard::Keyboard::KEY_DOLLAR, SDLK_DOLLAR },
{ love::keyboard::Keyboard::KEY_AMPERSAND, SDLK_AMPERSAND },
{ love::keyboard::Keyboard::KEY_QUOTE, SDLK_QUOTE },
{ love::keyboard::Keyboard::KEY_LEFTPAREN, SDLK_LEFTPAREN },
{ love::keyboard::Keyboard::KEY_RIGHTPAREN, SDLK_RIGHTPAREN },
{ love::keyboard::Keyboard::KEY_ASTERISK, SDLK_ASTERISK },
{ love::keyboard::Keyboard::KEY_PLUS, SDLK_PLUS },
{ love::keyboard::Keyboard::KEY_COMMA, SDLK_COMMA },
{ love::keyboard::Keyboard::KEY_MINUS, SDLK_MINUS },
{ love::keyboard::Keyboard::KEY_PERIOD, SDLK_PERIOD },
{ love::keyboard::Keyboard::KEY_SLASH, SDLK_SLASH },
{ love::keyboard::Keyboard::KEY_0, SDLK_0 },
{ love::keyboard::Keyboard::KEY_1, SDLK_1 },
{ love::keyboard::Keyboard::KEY_2, SDLK_2 },
{ love::keyboard::Keyboard::KEY_3, SDLK_3 },
{ love::keyboard::Keyboard::KEY_4, SDLK_4 },
{ love::keyboard::Keyboard::KEY_5, SDLK_5 },
{ love::keyboard::Keyboard::KEY_6, SDLK_6 },
{ love::keyboard::Keyboard::KEY_7, SDLK_7 },
{ love::keyboard::Keyboard::KEY_8, SDLK_8 },
{ love::keyboard::Keyboard::KEY_9, SDLK_9 },
{ love::keyboard::Keyboard::KEY_COLON, SDLK_COLON },
{ love::keyboard::Keyboard::KEY_SEMICOLON, SDLK_SEMICOLON },
{ love::keyboard::Keyboard::KEY_LESS, SDLK_LESS },
{ love::keyboard::Keyboard::KEY_EQUALS, SDLK_EQUALS },
{ love::keyboard::Keyboard::KEY_GREATER, SDLK_GREATER },
{ love::keyboard::Keyboard::KEY_QUESTION, SDLK_QUESTION },
{ love::keyboard::Keyboard::KEY_AT, SDLK_AT },
{ love::keyboard::Keyboard::KEY_LEFTBRACKET, SDLK_LEFTBRACKET },
{ love::keyboard::Keyboard::KEY_BACKSLASH, SDLK_BACKSLASH },
{ love::keyboard::Keyboard::KEY_RIGHTBRACKET, SDLK_RIGHTBRACKET },
{ love::keyboard::Keyboard::KEY_CARET, SDLK_CARET },
{ love::keyboard::Keyboard::KEY_UNDERSCORE, SDLK_UNDERSCORE },
{ love::keyboard::Keyboard::KEY_BACKQUOTE, SDLK_BACKQUOTE },
{ love::keyboard::Keyboard::KEY_A, SDLK_a },
{ love::keyboard::Keyboard::KEY_B, SDLK_b },
{ love::keyboard::Keyboard::KEY_C, SDLK_c },
{ love::keyboard::Keyboard::KEY_D, SDLK_d },
{ love::keyboard::Keyboard::KEY_E, SDLK_e },
{ love::keyboard::Keyboard::KEY_F, SDLK_f },
{ love::keyboard::Keyboard::KEY_G, SDLK_g },
{ love::keyboard::Keyboard::KEY_H, SDLK_h },
{ love::keyboard::Keyboard::KEY_I, SDLK_i },
{ love::keyboard::Keyboard::KEY_J, SDLK_j },
{ love::keyboard::Keyboard::KEY_K, SDLK_k },
{ love::keyboard::Keyboard::KEY_L, SDLK_l },
{ love::keyboard::Keyboard::KEY_M, SDLK_m },
{ love::keyboard::Keyboard::KEY_N, SDLK_n },
{ love::keyboard::Keyboard::KEY_O, SDLK_o },
{ love::keyboard::Keyboard::KEY_P, SDLK_p },
{ love::keyboard::Keyboard::KEY_Q, SDLK_q },
{ love::keyboard::Keyboard::KEY_R, SDLK_r },
{ love::keyboard::Keyboard::KEY_S, SDLK_s },
{ love::keyboard::Keyboard::KEY_T, SDLK_t },
{ love::keyboard::Keyboard::KEY_U, SDLK_u },
{ love::keyboard::Keyboard::KEY_V, SDLK_v },
{ love::keyboard::Keyboard::KEY_W, SDLK_w },
{ love::keyboard::Keyboard::KEY_X, SDLK_x },
{ love::keyboard::Keyboard::KEY_Y, SDLK_y },
{ love::keyboard::Keyboard::KEY_Z, SDLK_z },
{ love::keyboard::Keyboard::KEY_DELETE, SDLK_DELETE },
{ love::keyboard::Keyboard::KEY_KP0, SDLK_KP0 },
{ love::keyboard::Keyboard::KEY_KP1, SDLK_KP1 },
{ love::keyboard::Keyboard::KEY_KP2, SDLK_KP2 },
{ love::keyboard::Keyboard::KEY_KP3, SDLK_KP3 },
{ love::keyboard::Keyboard::KEY_KP4, SDLK_KP4 },
{ love::keyboard::Keyboard::KEY_KP5, SDLK_KP5 },
{ love::keyboard::Keyboard::KEY_KP6, SDLK_KP6 },
{ love::keyboard::Keyboard::KEY_KP7, SDLK_KP7 },
{ love::keyboard::Keyboard::KEY_KP8, SDLK_KP8 },
{ love::keyboard::Keyboard::KEY_KP9, SDLK_KP9 },
{ love::keyboard::Keyboard::KEY_KP_PERIOD, SDLK_KP_PERIOD },
{ love::keyboard::Keyboard::KEY_KP_DIVIDE, SDLK_KP_DIVIDE },
{ love::keyboard::Keyboard::KEY_KP_MULTIPLY, SDLK_KP_MULTIPLY},
{ love::keyboard::Keyboard::KEY_KP_MINUS, SDLK_KP_MINUS },
{ love::keyboard::Keyboard::KEY_KP_PLUS, SDLK_KP_PLUS },
{ love::keyboard::Keyboard::KEY_KP_ENTER, SDLK_KP_ENTER },
{ love::keyboard::Keyboard::KEY_KP_EQUALS, SDLK_KP_EQUALS },
{ love::keyboard::Keyboard::KEY_UP, SDLK_UP },
{ love::keyboard::Keyboard::KEY_DOWN, SDLK_DOWN },
{ love::keyboard::Keyboard::KEY_RIGHT, SDLK_RIGHT },
{ love::keyboard::Keyboard::KEY_LEFT, SDLK_LEFT },
{ love::keyboard::Keyboard::KEY_INSERT, SDLK_INSERT },
{ love::keyboard::Keyboard::KEY_HOME, SDLK_HOME },
{ love::keyboard::Keyboard::KEY_END, SDLK_END },
{ love::keyboard::Keyboard::KEY_PAGEUP, SDLK_PAGEUP },
{ love::keyboard::Keyboard::KEY_PAGEDOWN, SDLK_PAGEDOWN },
{ love::keyboard::Keyboard::KEY_F1, SDLK_F1 },
{ love::keyboard::Keyboard::KEY_F2, SDLK_F2 },
{ love::keyboard::Keyboard::KEY_F3, SDLK_F3 },
{ love::keyboard::Keyboard::KEY_F4, SDLK_F4 },
{ love::keyboard::Keyboard::KEY_F5, SDLK_F5 },
{ love::keyboard::Keyboard::KEY_F6, SDLK_F6 },
{ love::keyboard::Keyboard::KEY_F7, SDLK_F7 },
{ love::keyboard::Keyboard::KEY_F8, SDLK_F8 },
{ love::keyboard::Keyboard::KEY_F9, SDLK_F9 },
{ love::keyboard::Keyboard::KEY_F10, SDLK_F10 },
{ love::keyboard::Keyboard::KEY_F11, SDLK_F11 },
{ love::keyboard::Keyboard::KEY_F12, SDLK_F12 },
{ love::keyboard::Keyboard::KEY_F13, SDLK_F13 },
{ love::keyboard::Keyboard::KEY_F14, SDLK_F14 },
{ love::keyboard::Keyboard::KEY_F15, SDLK_F15 },
{ love::keyboard::Keyboard::KEY_NUMLOCK, SDLK_NUMLOCK },
{ love::keyboard::Keyboard::KEY_CAPSLOCK, SDLK_CAPSLOCK },
{ love::keyboard::Keyboard::KEY_SCROLLOCK, SDLK_SCROLLOCK },
{ love::keyboard::Keyboard::KEY_RSHIFT, SDLK_RSHIFT },
{ love::keyboard::Keyboard::KEY_LSHIFT, SDLK_LSHIFT },
{ love::keyboard::Keyboard::KEY_RCTRL, SDLK_RCTRL },
{ love::keyboard::Keyboard::KEY_LCTRL, SDLK_LCTRL },
{ love::keyboard::Keyboard::KEY_RALT, SDLK_RALT },
{ love::keyboard::Keyboard::KEY_LALT, SDLK_LALT },
{ love::keyboard::Keyboard::KEY_RMETA, SDLK_RMETA },
{ love::keyboard::Keyboard::KEY_LMETA, SDLK_LMETA },
{ love::keyboard::Keyboard::KEY_LSUPER, SDLK_LSUPER },
{ love::keyboard::Keyboard::KEY_RSUPER, SDLK_RSUPER },
{ love::keyboard::Keyboard::KEY_MODE, SDLK_MODE },
{ love::keyboard::Keyboard::KEY_COMPOSE, SDLK_COMPOSE },
{ love::keyboard::Keyboard::KEY_HELP, SDLK_HELP },
{ love::keyboard::Keyboard::KEY_PRINT, SDLK_PRINT },
{ love::keyboard::Keyboard::KEY_SYSREQ, SDLK_SYSREQ },
{ love::keyboard::Keyboard::KEY_BREAK, SDLK_BREAK },
{ love::keyboard::Keyboard::KEY_MENU, SDLK_MENU },
{ love::keyboard::Keyboard::KEY_POWER, SDLK_POWER },
{ love::keyboard::Keyboard::KEY_EURO, SDLK_EURO },
{ love::keyboard::Keyboard::KEY_UNDO, SDLK_UNDO },
{ love::keyboard::Keyboard::KEY_UNKNOWN, SDLK_UNKNOWN },
};
EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM> Event::keys(Event::keyEntries, sizeof(Event::keyEntries));
std::map<SDL_Keycode, love::keyboard::Keyboard::Key> Event::keys = Event::createKeyMap();
EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry Event::buttonEntries[] =
{
{ love::mouse::Mouse::BUTTON_LEFT, SDL_BUTTON_LEFT},
{ love::mouse::Mouse::BUTTON_MIDDLE, SDL_BUTTON_MIDDLE},
{ love::mouse::Mouse::BUTTON_RIGHT, SDL_BUTTON_RIGHT},
{ love::mouse::Mouse::BUTTON_WHEELUP, SDL_BUTTON_WHEELUP},
{ love::mouse::Mouse::BUTTON_WHEELDOWN, SDL_BUTTON_WHEELDOWN},
{ love::mouse::Mouse::BUTTON_X1, SDL_BUTTON_X1},
{ love::mouse::Mouse::BUTTON_X2, SDL_BUTTON_X2},
};
EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM> Event::buttons(Event::buttonEntries, sizeof(Event::buttonEntries));
EnumMap<love::joystick::Joystick::Hat, Uint8, love::joystick::Joystick::HAT_MAX_ENUM>::Entry Event::hatEntries[] =
{
{love::joystick::Joystick::HAT_CENTERED, SDL_HAT_CENTERED},
{love::joystick::Joystick::HAT_UP, SDL_HAT_UP},
{love::joystick::Joystick::HAT_RIGHT, SDL_HAT_RIGHT},
{love::joystick::Joystick::HAT_DOWN, SDL_HAT_DOWN},
{love::joystick::Joystick::HAT_LEFT, SDL_HAT_LEFT},
{love::joystick::Joystick::HAT_RIGHTUP, SDL_HAT_RIGHTUP},
{love::joystick::Joystick::HAT_RIGHTDOWN, SDL_HAT_RIGHTDOWN},
{love::joystick::Joystick::HAT_LEFTUP, SDL_HAT_LEFTUP},
{love::joystick::Joystick::HAT_LEFTDOWN, SDL_HAT_LEFTDOWN},
};
EnumMap<love::joystick::Joystick::Hat, Uint8, love::joystick::Joystick::HAT_MAX_ENUM> Event::hats(Event::hatEntries, sizeof(Event::hatEntries));
} // sdl
} // event
} // love
+10 -6
View File
@@ -29,6 +29,9 @@
// SDL
#include <SDL.h>
// STL
#include <map>
namespace love
{
namespace event
@@ -44,6 +47,7 @@ public:
const char *getName() const;
Event();
virtual ~Event();
/**
* Pumps the event queue. This function gathers all the pending input information
@@ -66,15 +70,15 @@ public:
private:
Message *convert(SDL_Event &e);
const char *convertUnicode(Uint16 codepoint) const;
Message *convert(const SDL_Event &e) const;
Message *convertJoystickEvent(const SDL_Event &e) const;
Message *convertWindowEvent(const SDL_Event &e) const;
static std::map<SDL_Keycode, love::keyboard::Keyboard::Key> createKeyMap();
static std::map<SDL_Keycode, love::keyboard::Keyboard::Key> keys;
static EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
static EnumMap<love::keyboard::Keyboard::Key, SDLKey, love::keyboard::Keyboard::KEY_MAX_ENUM> keys;
static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM>::Entry buttonEntries[];
static EnumMap<love::mouse::Mouse::Button, Uint8, love::mouse::Mouse::BUTTON_MAX_ENUM> buttons;
static EnumMap<love::joystick::Joystick::Hat, Uint8, love::joystick::Joystick::HAT_MAX_ENUM>::Entry hatEntries[];
static EnumMap<love::joystick::Joystick::Hat, Uint8, love::joystick::Joystick::HAT_MAX_ENUM> hats;
}; // System
+2 -2
View File
@@ -127,9 +127,9 @@ extern "C" int luaopen_love_event(lua_State *L)
{
instance = new Event();
}
catch(Exception &e)
catch (love::Exception &e)
{
return luaL_error(L, e.what());
return luaL_error(L, "%s", e.what());
}
}
else
+5
View File
@@ -108,6 +108,11 @@ public:
virtual ~Graphics();
/**
* Sets the current graphics display viewport dimensions.
**/
virtual void setViewportSize(int width, int height) = 0;
/**
* Sets the current graphics display viewport and initializes the renderer.
* @param width The viewport width.
+26 -13
View File
@@ -52,7 +52,7 @@ Graphics::Graphics()
, created(false)
, savedState()
{
currentWindow = love::window::sdl::Window::getSingleton();
currentWindow = love::window::sdl::Window::createSingleton();
if (currentWindow->isCreated())
setMode(currentWindow->getWidth(), currentWindow->getHeight());
@@ -113,6 +113,27 @@ void Graphics::restoreState(const DisplayState &s)
setColorMask(s.colorMask[0], s.colorMask[1], s.colorMask[2], s.colorMask[3]);
}
void Graphics::setViewportSize(int width, int height)
{
this->width = width;
this->height = height;
if (!isCreated())
return;
// Set the viewport to top-left corner
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
// Reset the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set up orthographic view (no depth)
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
bool Graphics::setMode(int width, int height)
{
this->width = width;
@@ -121,6 +142,10 @@ bool Graphics::setMode(int width, int height)
// Okay, setup OpenGL.
gl.initContext();
created = true;
setViewportSize(width, height);
// Make sure antialiasing works when set elsewhere
if (GLEE_VERSION_1_3 || GLEE_ARB_multisample)
glEnable(GL_MULTISAMPLE);
@@ -147,16 +172,6 @@ bool Graphics::setMode(int width, int height)
glEnable(GL_TEXTURE_2D);
gl.setTextureUnit(0);
// Set the viewport to top-left corner
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
// Reset the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set up orthographic view (no depth)
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
// Reset modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
@@ -179,8 +194,6 @@ bool Graphics::setMode(int width, int height)
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &matrixLimit);
matrixLimit -= 5;
created = true;
return true;
}
+1
View File
@@ -112,6 +112,7 @@ public:
void restoreState(const DisplayState &s);
virtual void setViewportSize(int width, int height);
virtual bool setMode(int width, int height);
virtual void unSetMode();
+85 -2
View File
@@ -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
+133 -5
View File
@@ -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
+99
View File
@@ -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
+225 -141
View File
@@ -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
+59 -22
View File
@@ -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
+450
View File
@@ -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
+81
View File
@@ -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
+132 -90
View File
@@ -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
+17 -11
View File
@@ -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
+103 -54
View File
@@ -39,12 +39,10 @@ bool Keyboard::getConstant(Keyboard::Key in, const char *&out)
StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] =
{
{"return", Keyboard::KEY_RETURN},
{"escape", Keyboard::KEY_ESCAPE},
{"backspace", Keyboard::KEY_BACKSPACE},
{"tab", Keyboard::KEY_TAB},
{"clear", Keyboard::KEY_CLEAR},
{"return", Keyboard::KEY_RETURN},
{"pause", Keyboard::KEY_PAUSE},
{"escape", Keyboard::KEY_ESCAPE},
{" ", Keyboard::KEY_SPACE},
{"!", Keyboard::KEY_EXCLAIM},
{"\"", Keyboard::KEY_QUOTEDBL},
@@ -110,35 +108,8 @@ StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] =
{"x", Keyboard::KEY_X},
{"y", Keyboard::KEY_Y},
{"z", Keyboard::KEY_Z},
{"delete", Keyboard::KEY_DELETE},
{"kp0", Keyboard::KEY_KP0},
{"kp1", Keyboard::KEY_KP1},
{"kp2", Keyboard::KEY_KP2},
{"kp3", Keyboard::KEY_KP3},
{"kp4", Keyboard::KEY_KP4},
{"kp5", Keyboard::KEY_KP5},
{"kp6", Keyboard::KEY_KP6},
{"kp7", Keyboard::KEY_KP7},
{"kp8", Keyboard::KEY_KP8},
{"kp9", Keyboard::KEY_KP9},
{"kp.", Keyboard::KEY_KP_PERIOD},
{"kp/", Keyboard::KEY_KP_DIVIDE},
{"kp*", Keyboard::KEY_KP_MULTIPLY},
{"kp-", Keyboard::KEY_KP_MINUS},
{"kp+", Keyboard::KEY_KP_PLUS},
{"kpenter", Keyboard::KEY_KP_ENTER},
{"kp=", Keyboard::KEY_KP_EQUALS},
{"up", Keyboard::KEY_UP},
{"down", Keyboard::KEY_DOWN},
{"right", Keyboard::KEY_RIGHT},
{"left", Keyboard::KEY_LEFT},
{"insert", Keyboard::KEY_INSERT},
{"home", Keyboard::KEY_HOME},
{"end", Keyboard::KEY_END},
{"pageup", Keyboard::KEY_PAGEUP},
{"pagedown", Keyboard::KEY_PAGEDOWN},
{"capslock", Keyboard::KEY_CAPSLOCK},
{"f1", Keyboard::KEY_F1},
{"f2", Keyboard::KEY_F2},
@@ -152,34 +123,112 @@ StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] =
{"f10", Keyboard::KEY_F10},
{"f11", Keyboard::KEY_F11},
{"f12", Keyboard::KEY_F12},
{"printscreen", Keyboard::KEY_PRINTSCREEN},
{"scrolllock", Keyboard::KEY_SCROLLLOCK},
{"pause", Keyboard::KEY_PAUSE},
{"insert", Keyboard::KEY_INSERT},
{"home", Keyboard::KEY_HOME},
{"pageup", Keyboard::KEY_PAGEUP},
{"delete", Keyboard::KEY_DELETE},
{"end", Keyboard::KEY_END},
{"pagedown", Keyboard::KEY_PAGEDOWN},
{"right", Keyboard::KEY_RIGHT},
{"left", Keyboard::KEY_LEFT},
{"down", Keyboard::KEY_DOWN},
{"up", Keyboard::KEY_UP},
{"numlock", Keyboard::KEY_NUMLOCKCLEAR},
{"kp/", Keyboard::KEY_KP_DIVIDE},
{"kp*", Keyboard::KEY_KP_MULTIPLY},
{"kp-", Keyboard::KEY_KP_MINUS},
{"kp+", Keyboard::KEY_KP_PLUS},
{"kpenter", Keyboard::KEY_KP_ENTER},
{"kp0", Keyboard::KEY_KP_0},
{"kp1", Keyboard::KEY_KP_1},
{"kp2", Keyboard::KEY_KP_2},
{"kp3", Keyboard::KEY_KP_3},
{"kp4", Keyboard::KEY_KP_4},
{"kp5", Keyboard::KEY_KP_5},
{"kp6", Keyboard::KEY_KP_6},
{"kp7", Keyboard::KEY_KP_7},
{"kp8", Keyboard::KEY_KP_8},
{"kp9", Keyboard::KEY_KP_9},
{"kp.", Keyboard::KEY_KP_PERIOD},
{"kp,", Keyboard::KEY_KP_COMMA},
{"kp=", Keyboard::KEY_KP_EQUALS},
{"application", Keyboard::KEY_APPLICATION},
{"power", Keyboard::KEY_POWER},
{"f13", Keyboard::KEY_F13},
{"f14", Keyboard::KEY_F14},
{"f15", Keyboard::KEY_F15},
{"numlock", Keyboard::KEY_NUMLOCK},
{"capslock", Keyboard::KEY_CAPSLOCK},
{"scrollock", Keyboard::KEY_SCROLLOCK},
{"rshift", Keyboard::KEY_RSHIFT},
{"lshift", Keyboard::KEY_LSHIFT},
{"rctrl", Keyboard::KEY_RCTRL},
{"lctrl", Keyboard::KEY_LCTRL},
{"ralt", Keyboard::KEY_RALT},
{"lalt", Keyboard::KEY_LALT},
{"rmeta", Keyboard::KEY_RMETA},
{"lmeta", Keyboard::KEY_LMETA},
{"lsuper", Keyboard::KEY_LSUPER},
{"rsuper", Keyboard::KEY_RSUPER},
{"mode", Keyboard::KEY_MODE},
{"compose", Keyboard::KEY_COMPOSE},
{"f16", Keyboard::KEY_F16},
{"f17", Keyboard::KEY_F17},
{"f18", Keyboard::KEY_F18},
{"f19", Keyboard::KEY_F19},
{"f20", Keyboard::KEY_F20},
{"f21", Keyboard::KEY_F21},
{"f22", Keyboard::KEY_F22},
{"f23", Keyboard::KEY_F23},
{"f24", Keyboard::KEY_F24},
{"execute", Keyboard::KEY_EXECUTE},
{"help", Keyboard::KEY_HELP},
{"print", Keyboard::KEY_PRINT},
{"sysreq", Keyboard::KEY_SYSREQ},
{"break", Keyboard::KEY_BREAK},
{"menu", Keyboard::KEY_MENU},
{"power", Keyboard::KEY_POWER},
{"euro", Keyboard::KEY_EURO},
{"select", Keyboard::KEY_SELECT},
{"stop", Keyboard::KEY_STOP},
{"again", Keyboard::KEY_AGAIN},
{"undo", Keyboard::KEY_UNDO},
{"cut", Keyboard::KEY_CUT},
{"copy", Keyboard::KEY_COPY},
{"paste", Keyboard::KEY_PASTE},
{"find", Keyboard::KEY_FIND},
{"mute", Keyboard::KEY_MUTE},
{"volumeup", Keyboard::KEY_VOLUMEUP},
{"volumedown", Keyboard::KEY_VOLUMEDOWN},
{"alterase", Keyboard::KEY_ALTERASE},
{"sysreq", Keyboard::KEY_SYSREQ},
{"cancel", Keyboard::KEY_CANCEL},
{"clear", Keyboard::KEY_CLEAR},
{"prior", Keyboard::KEY_PRIOR},
{"return2", Keyboard::KEY_RETURN2},
{"separator", Keyboard::KEY_SEPARATOR},
{"out", Keyboard::KEY_OUT},
{"oper", Keyboard::KEY_OPER},
{"clearagain", Keyboard::KEY_CLEARAGAIN},
{"thsousandsseparator", Keyboard::KEY_THOUSANDSSEPARATOR},
{"decimalseparator", Keyboard::KEY_DECIMALSEPARATOR},
{"currencyunit", Keyboard::KEY_CURRENCYUNIT},
{"currencysubunit", Keyboard::KEY_CURRENCYSUBUNIT},
{"lctrl", Keyboard::KEY_LCTRL},
{"lshift", Keyboard::KEY_LSHIFT},
{"lalt", Keyboard::KEY_LALT},
{"lgui", Keyboard::KEY_LGUI},
{"rctrl", Keyboard::KEY_RCTRL},
{"rshift", Keyboard::KEY_RSHIFT},
{"ralt", Keyboard::KEY_RALT},
{"rgui", Keyboard::KEY_RGUI},
{"mode", Keyboard::KEY_MODE},
{"audionext", Keyboard::KEY_AUDIONEXT},
{"audioprev", Keyboard::KEY_AUDIOPREV},
{"audiostop", Keyboard::KEY_AUDIOSTOP},
{"audioplay", Keyboard::KEY_AUDIOPLAY},
{"audiomute", Keyboard::KEY_AUDIOMUTE},
{"mediaselect", Keyboard::KEY_MEDIASELECT},
{"brightnessdown", Keyboard::KEY_BRIGHTNESSDOWN},
{"brightnessup", Keyboard::KEY_BRIGHTNESSUP},
{"displayswitch", Keyboard::KEY_DISPLAYSWITCH},
{"kbdillumtoggle", Keyboard::KEY_KBDILLUMTOGGLE},
{"kbdillumdown", Keyboard::KEY_KBDILLUMDOWN},
{"kbdillumup", Keyboard::KEY_KBDILLUMUP},
{"eject", Keyboard::KEY_EJECT},
{"sleep", Keyboard::KEY_SLEEP},
};
StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM> Keyboard::keys(Keyboard::keyEntries, sizeof(Keyboard::keyEntries));
+106 -75
View File
@@ -37,16 +37,16 @@ public:
enum Key
{
KEY_UNKNOWN,
KEY_RETURN,
KEY_ESCAPE,
KEY_BACKSPACE,
KEY_TAB,
KEY_CLEAR,
KEY_RETURN,
KEY_PAUSE,
KEY_ESCAPE,
KEY_SPACE,
KEY_EXCLAIM,
KEY_QUOTEDBL,
KEY_HASH,
KEY_PERCENT,
KEY_DOLLAR,
KEY_AMPERSAND,
KEY_QUOTE,
@@ -108,35 +108,8 @@ public:
KEY_X,
KEY_Y,
KEY_Z,
KEY_DELETE,
KEY_KP0,
KEY_KP1,
KEY_KP2,
KEY_KP3,
KEY_KP4,
KEY_KP5,
KEY_KP6,
KEY_KP7,
KEY_KP8,
KEY_KP9,
KEY_KP_PERIOD,
KEY_KP_DIVIDE,
KEY_KP_MULTIPLY,
KEY_KP_MINUS,
KEY_KP_PLUS,
KEY_KP_ENTER,
KEY_KP_EQUALS,
KEY_UP,
KEY_DOWN,
KEY_RIGHT,
KEY_LEFT,
KEY_INSERT,
KEY_HOME,
KEY_END,
KEY_PAGEUP,
KEY_PAGEDOWN,
KEY_CAPSLOCK,
KEY_F1,
KEY_F2,
@@ -150,39 +123,116 @@ public:
KEY_F10,
KEY_F11,
KEY_F12,
KEY_PRINTSCREEN,
KEY_SCROLLLOCK,
KEY_PAUSE,
KEY_INSERT,
KEY_HOME,
KEY_PAGEUP,
KEY_DELETE,
KEY_END,
KEY_PAGEDOWN,
KEY_RIGHT,
KEY_LEFT,
KEY_DOWN,
KEY_UP,
KEY_NUMLOCKCLEAR,
KEY_KP_DIVIDE,
KEY_KP_MULTIPLY,
KEY_KP_MINUS,
KEY_KP_PLUS,
KEY_KP_ENTER,
KEY_KP_1,
KEY_KP_2,
KEY_KP_3,
KEY_KP_4,
KEY_KP_5,
KEY_KP_6,
KEY_KP_7,
KEY_KP_8,
KEY_KP_9,
KEY_KP_0,
KEY_KP_PERIOD,
KEY_KP_COMMA,
KEY_KP_EQUALS,
KEY_APPLICATION,
KEY_POWER,
KEY_F13,
KEY_F14,
KEY_F15,
KEY_NUMLOCK,
KEY_CAPSLOCK,
KEY_SCROLLOCK,
KEY_RSHIFT,
KEY_LSHIFT,
KEY_RCTRL,
KEY_LCTRL,
KEY_RALT,
KEY_LALT,
KEY_RMETA,
KEY_LMETA,
KEY_LSUPER,
KEY_RSUPER,
KEY_MODE,
KEY_COMPOSE,
KEY_F16,
KEY_F17,
KEY_F18,
KEY_F19,
KEY_F20,
KEY_F21,
KEY_F22,
KEY_F23,
KEY_F24,
KEY_EXECUTE,
KEY_HELP,
KEY_PRINT,
KEY_SYSREQ,
KEY_BREAK,
KEY_MENU,
KEY_POWER,
KEY_EURO,
KEY_SELECT,
KEY_STOP,
KEY_AGAIN,
KEY_UNDO,
KEY_CUT,
KEY_COPY,
KEY_PASTE,
KEY_FIND,
KEY_MUTE,
KEY_VOLUMEUP,
KEY_VOLUMEDOWN,
KEY_ALTERASE,
KEY_SYSREQ,
KEY_CANCEL,
KEY_CLEAR,
KEY_PRIOR,
KEY_RETURN2,
KEY_SEPARATOR,
KEY_OUT,
KEY_OPER,
KEY_CLEARAGAIN,
KEY_THOUSANDSSEPARATOR,
KEY_DECIMALSEPARATOR,
KEY_CURRENCYUNIT,
KEY_CURRENCYSUBUNIT,
KEY_LCTRL,
KEY_LSHIFT,
KEY_LALT,
KEY_LGUI,
KEY_RCTRL,
KEY_RSHIFT,
KEY_RALT,
KEY_RGUI,
KEY_MODE,
KEY_AUDIONEXT,
KEY_AUDIOPREV,
KEY_AUDIOSTOP,
KEY_AUDIOPLAY,
KEY_AUDIOMUTE,
KEY_MEDIASELECT,
KEY_BRIGHTNESSDOWN,
KEY_BRIGHTNESSUP,
KEY_DISPLAYSWITCH,
KEY_KBDILLUMTOGGLE,
KEY_KBDILLUMDOWN,
KEY_KBDILLUMUP,
KEY_EJECT,
KEY_SLEEP,
KEY_MAX_ENUM = 512
};
static const int DEFAULT = -1;
virtual ~Keyboard() {}
/**
@@ -192,25 +242,6 @@ public:
**/
virtual bool isDown(Key *keylist) const = 0;
/**
* Enables key repeating.
* @param delay The amount of delay before repeating the key (in milliseconds)
* @param interval Specifies the amount of time between repeats (in milliseconds)
**/
virtual void setKeyRepeat(int delay, int interval) const = 0;
/**
* Gets the specified delay for the key repeat.
* @return int
**/
virtual int getKeyRepeatDelay() const = 0;
/**
* Gets the specified interval for the key repeat.
* @return int
**/
virtual int getKeyRepeatInterval() const = 0;
static bool getConstant(const char *in, Key &out);
static bool getConstant(Key in, const char *&out);
+201 -168
View File
@@ -36,187 +36,220 @@ const char *Keyboard::getName() const
bool Keyboard::isDown(Key *keylist) const
{
SDLKey k;
Uint8 *keystate = SDL_GetKeyState(0);
const Uint8 *keystate = SDL_GetKeyboardState(0);
std::map<Key, SDL_Keycode>::const_iterator it;
for (Key key = *keylist; key != KEY_MAX_ENUM; key = *(++keylist))
{
if (keys.find(key, k) && keystate[(unsigned)k] == 1)
it = keys.find(key);
if (it != keys.end() && keystate[SDL_GetScancodeFromKey(it->second)])
return true;
}
return false;
}
void Keyboard::setKeyRepeat(int delay, int interval) const
std::map<Keyboard::Key, SDL_Keycode> Keyboard::createKeyMap()
{
delay = (delay == DEFAULT) ? SDL_DEFAULT_REPEAT_DELAY : delay;
interval = (interval == DEFAULT) ? SDL_DEFAULT_REPEAT_INTERVAL : interval;
std::map<Keyboard::Key, SDL_Keycode> k;
SDL_EnableKeyRepeat(delay, interval);
k[Keyboard::KEY_UNKNOWN] = SDLK_UNKNOWN;
k[Keyboard::KEY_RETURN] = SDLK_RETURN;
k[Keyboard::KEY_ESCAPE] = SDLK_ESCAPE;
k[Keyboard::KEY_BACKSPACE] = SDLK_BACKSPACE;
k[Keyboard::KEY_TAB] = SDLK_TAB;
k[Keyboard::KEY_SPACE] = SDLK_SPACE;
k[Keyboard::KEY_EXCLAIM] = SDLK_EXCLAIM;
k[Keyboard::KEY_QUOTEDBL] = SDLK_QUOTEDBL;
k[Keyboard::KEY_HASH] = SDLK_HASH;
k[Keyboard::KEY_DOLLAR] = SDLK_DOLLAR;
k[Keyboard::KEY_AMPERSAND] = SDLK_AMPERSAND;
k[Keyboard::KEY_QUOTE] = SDLK_QUOTE;
k[Keyboard::KEY_LEFTPAREN] = SDLK_LEFTPAREN;
k[Keyboard::KEY_RIGHTPAREN] = SDLK_RIGHTPAREN;
k[Keyboard::KEY_ASTERISK] = SDLK_ASTERISK;
k[Keyboard::KEY_PLUS] = SDLK_PLUS;
k[Keyboard::KEY_COMMA] = SDLK_COMMA;
k[Keyboard::KEY_MINUS] = SDLK_MINUS;
k[Keyboard::KEY_PERIOD] = SDLK_PERIOD;
k[Keyboard::KEY_SLASH] = SDLK_SLASH;
k[Keyboard::KEY_0] = SDLK_0;
k[Keyboard::KEY_1] = SDLK_1;
k[Keyboard::KEY_2] = SDLK_2;
k[Keyboard::KEY_3] = SDLK_3;
k[Keyboard::KEY_4] = SDLK_4;
k[Keyboard::KEY_5] = SDLK_5;
k[Keyboard::KEY_6] = SDLK_6;
k[Keyboard::KEY_7] = SDLK_7;
k[Keyboard::KEY_8] = SDLK_8;
k[Keyboard::KEY_9] = SDLK_9;
k[Keyboard::KEY_COLON] = SDLK_COLON;
k[Keyboard::KEY_SEMICOLON] = SDLK_SEMICOLON;
k[Keyboard::KEY_LESS] = SDLK_LESS;
k[Keyboard::KEY_EQUALS] = SDLK_EQUALS;
k[Keyboard::KEY_GREATER] = SDLK_GREATER;
k[Keyboard::KEY_QUESTION] = SDLK_QUESTION;
k[Keyboard::KEY_AT] = SDLK_AT;
k[Keyboard::KEY_LEFTBRACKET] = SDLK_LEFTBRACKET;
k[Keyboard::KEY_BACKSLASH] = SDLK_BACKSLASH;
k[Keyboard::KEY_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
k[Keyboard::KEY_CARET] = SDLK_CARET;
k[Keyboard::KEY_UNDERSCORE] = SDLK_UNDERSCORE;
k[Keyboard::KEY_BACKQUOTE] = SDLK_BACKQUOTE;
k[Keyboard::KEY_A] = SDLK_a;
k[Keyboard::KEY_B] = SDLK_b;
k[Keyboard::KEY_C] = SDLK_c;
k[Keyboard::KEY_D] = SDLK_d;
k[Keyboard::KEY_E] = SDLK_e;
k[Keyboard::KEY_F] = SDLK_f;
k[Keyboard::KEY_G] = SDLK_g;
k[Keyboard::KEY_H] = SDLK_h;
k[Keyboard::KEY_I] = SDLK_i;
k[Keyboard::KEY_J] = SDLK_j;
k[Keyboard::KEY_K] = SDLK_k;
k[Keyboard::KEY_L] = SDLK_l;
k[Keyboard::KEY_M] = SDLK_m;
k[Keyboard::KEY_N] = SDLK_n;
k[Keyboard::KEY_O] = SDLK_o;
k[Keyboard::KEY_P] = SDLK_p;
k[Keyboard::KEY_Q] = SDLK_q;
k[Keyboard::KEY_R] = SDLK_r;
k[Keyboard::KEY_S] = SDLK_s;
k[Keyboard::KEY_T] = SDLK_t;
k[Keyboard::KEY_U] = SDLK_u;
k[Keyboard::KEY_V] = SDLK_v;
k[Keyboard::KEY_W] = SDLK_w;
k[Keyboard::KEY_X] = SDLK_x;
k[Keyboard::KEY_Y] = SDLK_y;
k[Keyboard::KEY_Z] = SDLK_z;
k[Keyboard::KEY_CAPSLOCK] = SDLK_CAPSLOCK;
k[Keyboard::KEY_F1] = SDLK_F1;
k[Keyboard::KEY_F2] = SDLK_F2;
k[Keyboard::KEY_F3] = SDLK_F3;
k[Keyboard::KEY_F4] = SDLK_F4;
k[Keyboard::KEY_F5] = SDLK_F5;
k[Keyboard::KEY_F6] = SDLK_F6;
k[Keyboard::KEY_F7] = SDLK_F7;
k[Keyboard::KEY_F8] = SDLK_F8;
k[Keyboard::KEY_F9] = SDLK_F9;
k[Keyboard::KEY_F10] = SDLK_F10;
k[Keyboard::KEY_F11] = SDLK_F11;
k[Keyboard::KEY_F12] = SDLK_F12;
k[Keyboard::KEY_PRINTSCREEN] = SDLK_PRINTSCREEN;
k[Keyboard::KEY_SCROLLLOCK] = SDLK_SCROLLLOCK;
k[Keyboard::KEY_PAUSE] = SDLK_PAUSE;
k[Keyboard::KEY_INSERT] = SDLK_INSERT;
k[Keyboard::KEY_HOME] = SDLK_HOME;
k[Keyboard::KEY_PAGEUP] = SDLK_PAGEUP;
k[Keyboard::KEY_DELETE] = SDLK_DELETE;
k[Keyboard::KEY_END] = SDLK_END;
k[Keyboard::KEY_PAGEDOWN] = SDLK_PAGEDOWN;
k[Keyboard::KEY_RIGHT] = SDLK_RIGHT;
k[Keyboard::KEY_LEFT] = SDLK_LEFT;
k[Keyboard::KEY_DOWN] = SDLK_DOWN;
k[Keyboard::KEY_UP] = SDLK_UP;
k[Keyboard::KEY_NUMLOCKCLEAR] = SDLK_NUMLOCKCLEAR;
k[Keyboard::KEY_KP_DIVIDE] = SDLK_KP_DIVIDE;
k[Keyboard::KEY_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
k[Keyboard::KEY_KP_MINUS] = SDLK_KP_MINUS;
k[Keyboard::KEY_KP_PLUS] = SDLK_KP_PLUS;
k[Keyboard::KEY_KP_ENTER] = SDLK_KP_ENTER;
k[Keyboard::KEY_KP_0] = SDLK_KP_0;
k[Keyboard::KEY_KP_1] = SDLK_KP_1;
k[Keyboard::KEY_KP_2] = SDLK_KP_2;
k[Keyboard::KEY_KP_3] = SDLK_KP_3;
k[Keyboard::KEY_KP_4] = SDLK_KP_4;
k[Keyboard::KEY_KP_5] = SDLK_KP_5;
k[Keyboard::KEY_KP_6] = SDLK_KP_6;
k[Keyboard::KEY_KP_7] = SDLK_KP_7;
k[Keyboard::KEY_KP_8] = SDLK_KP_8;
k[Keyboard::KEY_KP_9] = SDLK_KP_9;
k[Keyboard::KEY_KP_PERIOD] = SDLK_KP_PERIOD;
k[Keyboard::KEY_KP_COMMA] = SDLK_KP_COMMA;
k[Keyboard::KEY_KP_EQUALS] = SDLK_KP_EQUALS;
k[Keyboard::KEY_APPLICATION] = SDLK_APPLICATION;
k[Keyboard::KEY_POWER] = SDLK_POWER;
k[Keyboard::KEY_F13] = SDLK_F13;
k[Keyboard::KEY_F14] = SDLK_F14;
k[Keyboard::KEY_F15] = SDLK_F15;
k[Keyboard::KEY_F16] = SDLK_F16;
k[Keyboard::KEY_F17] = SDLK_F17;
k[Keyboard::KEY_F18] = SDLK_F18;
k[Keyboard::KEY_F19] = SDLK_F19;
k[Keyboard::KEY_F20] = SDLK_F20;
k[Keyboard::KEY_F21] = SDLK_F21;
k[Keyboard::KEY_F22] = SDLK_F22;
k[Keyboard::KEY_F23] = SDLK_F23;
k[Keyboard::KEY_F24] = SDLK_F24;
k[Keyboard::KEY_EXECUTE] = SDLK_EXECUTE;
k[Keyboard::KEY_HELP] = SDLK_HELP;
k[Keyboard::KEY_MENU] = SDLK_MENU;
k[Keyboard::KEY_SELECT] = SDLK_SELECT;
k[Keyboard::KEY_STOP] = SDLK_STOP;
k[Keyboard::KEY_AGAIN] = SDLK_AGAIN;
k[Keyboard::KEY_UNDO] = SDLK_UNDO;
k[Keyboard::KEY_CUT] = SDLK_CUT;
k[Keyboard::KEY_COPY] = SDLK_COPY;
k[Keyboard::KEY_PASTE] = SDLK_PASTE;
k[Keyboard::KEY_FIND] = SDLK_FIND;
k[Keyboard::KEY_MUTE] = SDLK_MUTE;
k[Keyboard::KEY_VOLUMEUP] = SDLK_VOLUMEUP;
k[Keyboard::KEY_VOLUMEDOWN] = SDLK_VOLUMEDOWN;
k[Keyboard::KEY_ALTERASE] = SDLK_ALTERASE;
k[Keyboard::KEY_SYSREQ] = SDLK_SYSREQ;
k[Keyboard::KEY_CANCEL] = SDLK_CANCEL;
k[Keyboard::KEY_CLEAR] = SDLK_CLEAR;
k[Keyboard::KEY_PRIOR] = SDLK_PRIOR;
k[Keyboard::KEY_RETURN2] = SDLK_RETURN2;
k[Keyboard::KEY_SEPARATOR] = SDLK_SEPARATOR;
k[Keyboard::KEY_OUT] = SDLK_OUT;
k[Keyboard::KEY_OPER] = SDLK_OPER;
k[Keyboard::KEY_CLEARAGAIN] = SDLK_CLEARAGAIN;
k[Keyboard::KEY_THOUSANDSSEPARATOR] = SDLK_THOUSANDSSEPARATOR;
k[Keyboard::KEY_DECIMALSEPARATOR] = SDLK_DECIMALSEPARATOR;
k[Keyboard::KEY_CURRENCYUNIT] = SDLK_CURRENCYUNIT;
k[Keyboard::KEY_CURRENCYSUBUNIT] = SDLK_CURRENCYSUBUNIT;
k[Keyboard::KEY_LCTRL] = SDLK_LCTRL;
k[Keyboard::KEY_LSHIFT] = SDLK_LSHIFT;
k[Keyboard::KEY_LALT] = SDLK_LALT;
k[Keyboard::KEY_LGUI] = SDLK_LGUI;
k[Keyboard::KEY_RCTRL] = SDLK_RCTRL;
k[Keyboard::KEY_RSHIFT] = SDLK_RSHIFT;
k[Keyboard::KEY_RALT] = SDLK_RALT;
k[Keyboard::KEY_RGUI] = SDLK_RGUI;
k[Keyboard::KEY_MODE] = SDLK_MODE;
k[Keyboard::KEY_AUDIONEXT] = SDLK_AUDIONEXT;
k[Keyboard::KEY_AUDIOPREV] = SDLK_AUDIOPREV;
k[Keyboard::KEY_AUDIOSTOP] = SDLK_AUDIOSTOP;
k[Keyboard::KEY_AUDIOPLAY] = SDLK_AUDIOPLAY;
k[Keyboard::KEY_AUDIOMUTE] = SDLK_AUDIOMUTE;
k[Keyboard::KEY_MEDIASELECT] = SDLK_MEDIASELECT;
k[Keyboard::KEY_BRIGHTNESSDOWN] = SDLK_BRIGHTNESSDOWN;
k[Keyboard::KEY_BRIGHTNESSUP] = SDLK_BRIGHTNESSUP;
k[Keyboard::KEY_DISPLAYSWITCH] = SDLK_DISPLAYSWITCH;
k[Keyboard::KEY_KBDILLUMTOGGLE] = SDLK_KBDILLUMTOGGLE;
k[Keyboard::KEY_KBDILLUMDOWN] = SDLK_KBDILLUMDOWN;
k[Keyboard::KEY_KBDILLUMUP] = SDLK_KBDILLUMUP;
k[Keyboard::KEY_EJECT] = SDLK_EJECT;
k[Keyboard::KEY_SLEEP] = SDLK_SLEEP;
return k;
}
int Keyboard::getKeyRepeatDelay() const
{
int delay, interval;
SDL_GetKeyRepeat(&delay, &interval);
return delay;
}
int Keyboard::getKeyRepeatInterval() const
{
int delay, interval;
SDL_GetKeyRepeat(&delay, &interval);
return interval;
}
EnumMap<Keyboard::Key, SDLKey, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] =
{
{ Keyboard::KEY_BACKSPACE, SDLK_BACKSPACE},
{ Keyboard::KEY_TAB, SDLK_TAB},
{ Keyboard::KEY_CLEAR, SDLK_CLEAR},
{ Keyboard::KEY_RETURN, SDLK_RETURN},
{ Keyboard::KEY_PAUSE, SDLK_PAUSE},
{ Keyboard::KEY_ESCAPE, SDLK_ESCAPE },
{ Keyboard::KEY_SPACE, SDLK_SPACE },
{ Keyboard::KEY_EXCLAIM, SDLK_EXCLAIM },
{ Keyboard::KEY_QUOTEDBL, SDLK_QUOTEDBL },
{ Keyboard::KEY_HASH, SDLK_HASH },
{ Keyboard::KEY_DOLLAR, SDLK_DOLLAR },
{ Keyboard::KEY_AMPERSAND, SDLK_AMPERSAND },
{ Keyboard::KEY_QUOTE, SDLK_QUOTE },
{ Keyboard::KEY_LEFTPAREN, SDLK_LEFTPAREN },
{ Keyboard::KEY_RIGHTPAREN, SDLK_RIGHTPAREN },
{ Keyboard::KEY_ASTERISK, SDLK_ASTERISK },
{ Keyboard::KEY_PLUS, SDLK_PLUS },
{ Keyboard::KEY_COMMA, SDLK_COMMA },
{ Keyboard::KEY_MINUS, SDLK_MINUS },
{ Keyboard::KEY_PERIOD, SDLK_PERIOD },
{ Keyboard::KEY_SLASH, SDLK_SLASH },
{ Keyboard::KEY_0, SDLK_0 },
{ Keyboard::KEY_1, SDLK_1 },
{ Keyboard::KEY_2, SDLK_2 },
{ Keyboard::KEY_3, SDLK_3 },
{ Keyboard::KEY_4, SDLK_4 },
{ Keyboard::KEY_5, SDLK_5 },
{ Keyboard::KEY_6, SDLK_6 },
{ Keyboard::KEY_7, SDLK_7 },
{ Keyboard::KEY_8, SDLK_8 },
{ Keyboard::KEY_9, SDLK_9 },
{ Keyboard::KEY_COLON, SDLK_COLON },
{ Keyboard::KEY_SEMICOLON, SDLK_SEMICOLON },
{ Keyboard::KEY_LESS, SDLK_LESS },
{ Keyboard::KEY_EQUALS, SDLK_EQUALS },
{ Keyboard::KEY_GREATER, SDLK_GREATER },
{ Keyboard::KEY_QUESTION, SDLK_QUESTION },
{ Keyboard::KEY_AT, SDLK_AT },
{ Keyboard::KEY_LEFTBRACKET, SDLK_LEFTBRACKET },
{ Keyboard::KEY_BACKSLASH, SDLK_BACKSLASH },
{ Keyboard::KEY_RIGHTBRACKET, SDLK_RIGHTBRACKET },
{ Keyboard::KEY_CARET, SDLK_CARET },
{ Keyboard::KEY_UNDERSCORE, SDLK_UNDERSCORE },
{ Keyboard::KEY_BACKQUOTE, SDLK_BACKQUOTE },
{ Keyboard::KEY_A, SDLK_a },
{ Keyboard::KEY_B, SDLK_b },
{ Keyboard::KEY_C, SDLK_c },
{ Keyboard::KEY_D, SDLK_d },
{ Keyboard::KEY_E, SDLK_e },
{ Keyboard::KEY_F, SDLK_f },
{ Keyboard::KEY_G, SDLK_g },
{ Keyboard::KEY_H, SDLK_h },
{ Keyboard::KEY_I, SDLK_i },
{ Keyboard::KEY_J, SDLK_j },
{ Keyboard::KEY_K, SDLK_k },
{ Keyboard::KEY_L, SDLK_l },
{ Keyboard::KEY_M, SDLK_m },
{ Keyboard::KEY_N, SDLK_n },
{ Keyboard::KEY_O, SDLK_o },
{ Keyboard::KEY_P, SDLK_p },
{ Keyboard::KEY_Q, SDLK_q },
{ Keyboard::KEY_R, SDLK_r },
{ Keyboard::KEY_S, SDLK_s },
{ Keyboard::KEY_T, SDLK_t },
{ Keyboard::KEY_U, SDLK_u },
{ Keyboard::KEY_V, SDLK_v },
{ Keyboard::KEY_W, SDLK_w },
{ Keyboard::KEY_X, SDLK_x },
{ Keyboard::KEY_Y, SDLK_y },
{ Keyboard::KEY_Z, SDLK_z },
{ Keyboard::KEY_DELETE, SDLK_DELETE },
{ Keyboard::KEY_KP0, SDLK_KP0 },
{ Keyboard::KEY_KP1, SDLK_KP1 },
{ Keyboard::KEY_KP2, SDLK_KP2 },
{ Keyboard::KEY_KP3, SDLK_KP3 },
{ Keyboard::KEY_KP4, SDLK_KP4 },
{ Keyboard::KEY_KP5, SDLK_KP5 },
{ Keyboard::KEY_KP6, SDLK_KP6 },
{ Keyboard::KEY_KP7, SDLK_KP7 },
{ Keyboard::KEY_KP8, SDLK_KP8 },
{ Keyboard::KEY_KP9, SDLK_KP9 },
{ Keyboard::KEY_KP_PERIOD, SDLK_KP_PERIOD },
{ Keyboard::KEY_KP_DIVIDE, SDLK_KP_DIVIDE },
{ Keyboard::KEY_KP_MULTIPLY, SDLK_KP_MULTIPLY},
{ Keyboard::KEY_KP_MINUS, SDLK_KP_MINUS },
{ Keyboard::KEY_KP_PLUS, SDLK_KP_PLUS },
{ Keyboard::KEY_KP_ENTER, SDLK_KP_ENTER },
{ Keyboard::KEY_KP_EQUALS, SDLK_KP_EQUALS },
{ Keyboard::KEY_UP, SDLK_UP },
{ Keyboard::KEY_DOWN, SDLK_DOWN },
{ Keyboard::KEY_RIGHT, SDLK_RIGHT },
{ Keyboard::KEY_LEFT, SDLK_LEFT },
{ Keyboard::KEY_INSERT, SDLK_INSERT },
{ Keyboard::KEY_HOME, SDLK_HOME },
{ Keyboard::KEY_END, SDLK_END },
{ Keyboard::KEY_PAGEUP, SDLK_PAGEUP },
{ Keyboard::KEY_PAGEDOWN, SDLK_PAGEDOWN },
{ Keyboard::KEY_F1, SDLK_F1 },
{ Keyboard::KEY_F2, SDLK_F2 },
{ Keyboard::KEY_F3, SDLK_F3 },
{ Keyboard::KEY_F4, SDLK_F4 },
{ Keyboard::KEY_F5, SDLK_F5 },
{ Keyboard::KEY_F6, SDLK_F6 },
{ Keyboard::KEY_F7, SDLK_F7 },
{ Keyboard::KEY_F8, SDLK_F8 },
{ Keyboard::KEY_F9, SDLK_F9 },
{ Keyboard::KEY_F10, SDLK_F10 },
{ Keyboard::KEY_F11, SDLK_F11 },
{ Keyboard::KEY_F12, SDLK_F12 },
{ Keyboard::KEY_F13, SDLK_F13 },
{ Keyboard::KEY_F14, SDLK_F14 },
{ Keyboard::KEY_F15, SDLK_F15 },
{ Keyboard::KEY_NUMLOCK, SDLK_NUMLOCK },
{ Keyboard::KEY_CAPSLOCK, SDLK_CAPSLOCK },
{ Keyboard::KEY_SCROLLOCK, SDLK_SCROLLOCK },
{ Keyboard::KEY_RSHIFT, SDLK_RSHIFT },
{ Keyboard::KEY_LSHIFT, SDLK_LSHIFT },
{ Keyboard::KEY_RCTRL, SDLK_RCTRL },
{ Keyboard::KEY_LCTRL, SDLK_LCTRL },
{ Keyboard::KEY_RALT, SDLK_RALT },
{ Keyboard::KEY_LALT, SDLK_LALT },
{ Keyboard::KEY_RMETA, SDLK_RMETA },
{ Keyboard::KEY_LMETA, SDLK_LMETA },
{ Keyboard::KEY_LSUPER, SDLK_LSUPER },
{ Keyboard::KEY_RSUPER, SDLK_RSUPER },
{ Keyboard::KEY_MODE, SDLK_MODE },
{ Keyboard::KEY_COMPOSE, SDLK_COMPOSE },
{ Keyboard::KEY_HELP, SDLK_HELP },
{ Keyboard::KEY_PRINT, SDLK_PRINT },
{ Keyboard::KEY_SYSREQ, SDLK_SYSREQ },
{ Keyboard::KEY_BREAK, SDLK_BREAK },
{ Keyboard::KEY_MENU, SDLK_MENU },
{ Keyboard::KEY_POWER, SDLK_POWER },
{ Keyboard::KEY_EURO, SDLK_EURO },
{ Keyboard::KEY_UNDO, SDLK_UNDO },
};
EnumMap<Keyboard::Key, SDLKey, Keyboard::KEY_MAX_ENUM> Keyboard::keys(Keyboard::keyEntries, sizeof(Keyboard::keyEntries));
std::map<Keyboard::Key, SDL_Keycode> Keyboard::keys = Keyboard::createKeyMap();
} // sdl
} // keyboard
+5 -5
View File
@@ -28,6 +28,9 @@
// SDL
#include <SDL.h>
// STL
#include <map>
namespace love
{
namespace keyboard
@@ -42,14 +45,11 @@ public:
// Implements Module.
const char *getName() const;
bool isDown(Key *keylist) const;
void setKeyRepeat(int delay, int interval) const;
int getKeyRepeatDelay() const;
int getKeyRepeatInterval() const;
private:
static EnumMap<Key, SDLKey, Keyboard::KEY_MAX_ENUM>::Entry keyEntries[];
static EnumMap<Key, SDLKey, Keyboard::KEY_MAX_ENUM> keys;
static std::map<Key, SDL_Keycode> createKeyMap();
static std::map<Key, SDL_Keycode> keys;
}; // Keyboard
-24
View File
@@ -50,34 +50,10 @@ int w_isDown(lua_State *L)
return 1;
}
int w_setKeyRepeat(lua_State *L)
{
if (lua_gettop(L) == 0)
{
// Disables key repeat.
instance->setKeyRepeat(0, 0);
return 0;
}
int delay = lua_isnumber(L, 1) ? (int)(lua_tonumber(L, 1) * 1000 + 0.5) : Keyboard::DEFAULT;
int interval = lua_isnumber(L, 2) ? (int)(lua_tonumber(L, 2) * 1000 + 0.5) : Keyboard::DEFAULT;
instance->setKeyRepeat(delay, interval);
return 0;
}
int w_getKeyRepeat(lua_State *L)
{
lua_pushnumber(L, (lua_Number) instance->getKeyRepeatDelay() * 0.001);
lua_pushnumber(L, (lua_Number) instance->getKeyRepeatInterval() * 0.001);
return 2;
}
// List of functions to wrap.
static const luaL_Reg functions[] =
{
{ "isDown", w_isDown },
{ "setKeyRepeat", w_setKeyRepeat },
{ "getKeyRepeat", w_getKeyRepeat },
{ 0, 0 }
};
-2
View File
@@ -30,8 +30,6 @@ namespace keyboard
{
int w_isDown(lua_State *L);
int w_setKeyRepeat(lua_State *L);
int w_getKeyRepeat(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_keyboard(lua_State *L);
} // keyboard
+2
View File
@@ -103,6 +103,7 @@ extern "C"
extern int luaopen_love_mouse(lua_State*);
extern int luaopen_love_physics(lua_State*);
extern int luaopen_love_sound(lua_State*);
extern int luaopen_love_system(lua_State*);
extern int luaopen_love_timer(lua_State*);
extern int luaopen_love_thread(lua_State*);
extern int luaopen_love_window(lua_State*);
@@ -122,6 +123,7 @@ static const luaL_Reg modules[] = {
{ "love.mouse", luaopen_love_mouse },
{ "love.physics", luaopen_love_physics },
{ "love.sound", luaopen_love_sound },
{ "love.system", luaopen_love_system },
{ "love.timer", luaopen_love_timer },
{ "love.thread", luaopen_love_thread },
{ "love.window", luaopen_love_window },
+79
View File
@@ -0,0 +1,79 @@
/**
* 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 "Cursor.h"
namespace love
{
namespace mouse
{
Cursor::~Cursor()
{
}
bool Cursor::getConstant(const char *in, SystemCursor &out)
{
return systemCursors.find(in, out);
}
bool Cursor::getConstant(SystemCursor in, const char *&out)
{
return systemCursors.find(in, out);
}
bool Cursor::getConstant(const char *in, CursorType &out)
{
return types.find(in, out);
}
bool Cursor::getConstant(CursorType in, const char *&out)
{
return types.find(in, out);
}
StringMap<Cursor::SystemCursor, Cursor::CURSOR_MAX_ENUM>::Entry Cursor::systemCursorEntries[] =
{
{"arrow", Cursor::CURSOR_ARROW},
{"ibeam", Cursor::CURSOR_IBEAM},
{"wait", Cursor::CURSOR_WAIT},
{"crosshair", Cursor::CURSOR_CROSSHAIR},
{"waitarrow", Cursor::CURSOR_WAITARROW},
{"sizenwse", Cursor::CURSOR_SIZENWSE},
{"sizenesw", Cursor::CURSOR_SIZENESW},
{"sizewe", Cursor::CURSOR_SIZEWE},
{"sizens", Cursor::CURSOR_SIZENS},
{"sizeall", Cursor::CURSOR_SIZEALL},
{"no", Cursor::CURSOR_NO},
{"hand", Cursor::CURSOR_HAND},
};
StringMap<Cursor::SystemCursor, Cursor::CURSOR_MAX_ENUM> Cursor::systemCursors(Cursor::systemCursorEntries, sizeof(Cursor::systemCursorEntries));
StringMap<Cursor::CursorType, Cursor::CURSORTYPE_MAX_ENUM>::Entry Cursor::typeEntries[] =
{
{"system", Cursor::CURSORTYPE_SYSTEM},
{"image", Cursor::CURSORTYPE_IMAGE},
};
StringMap<Cursor::CursorType, Cursor::CURSORTYPE_MAX_ENUM> Cursor::types(Cursor::typeEntries, sizeof(Cursor::typeEntries));
} // mouse
} // love
+100
View File
@@ -0,0 +1,100 @@
/**
* 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_MOUSE_CURSOR_H
#define LOVE_MOUSE_CURSOR_H
// LOVE
#include "image/ImageData.h"
#include "common/Object.h"
#include "common/StringMap.h"
namespace love
{
namespace mouse
{
class Cursor : public Object
{
public:
// Types of system cursors.
enum SystemCursor
{
CURSOR_ARROW,
CURSOR_IBEAM,
CURSOR_WAIT,
CURSOR_CROSSHAIR,
CURSOR_WAITARROW,
CURSOR_SIZENWSE,
CURSOR_SIZENESW,
CURSOR_SIZEWE,
CURSOR_SIZENS,
CURSOR_SIZEALL,
CURSOR_NO,
CURSOR_HAND,
CURSOR_MAX_ENUM
};
enum CursorType
{
CURSORTYPE_SYSTEM,
CURSORTYPE_IMAGE,
CURSORTYPE_MAX_ENUM
};
virtual ~Cursor();
/**
* Returns a pointer to the implementation-dependent handle of this Cursor.
**/
virtual void *getHandle() const = 0;
/**
* Returns whether this Cursor is system-defined or a custom image.
**/
virtual CursorType getType() const = 0;
/**
* Returns the type type of system cursor used, if this Cursor is using a
* system-defined image.
**/
virtual SystemCursor getSystemType() const = 0;
static bool getConstant(const char *in, SystemCursor &out);
static bool getConstant(SystemCursor in, const char *&out);
static bool getConstant(const char *in, CursorType &out);
static bool getConstant(CursorType in, const char *&out);
private:
static StringMap<SystemCursor, CURSOR_MAX_ENUM>::Entry systemCursorEntries[];
static StringMap<SystemCursor, CURSOR_MAX_ENUM> systemCursors;
static StringMap<CursorType, CURSORTYPE_MAX_ENUM>::Entry typeEntries[];
static StringMap<CursorType, CURSORTYPE_MAX_ENUM> types;
};
} // mouse
} // love
#endif // LOVE_MOUSE_CURSOR_H
+10
View File
@@ -22,8 +22,10 @@
#define LOVE_MOUSE_MOUSE_H
// LOVE
#include "Cursor.h"
#include "common/Module.h"
#include "common/StringMap.h"
#include "image/ImageData.h"
namespace love
{
@@ -49,6 +51,14 @@ public:
virtual ~Mouse() {};
virtual Cursor *newCursor(love::image::ImageData *data, int hotx, int hoty) = 0;
virtual Cursor *newCursor(Cursor::SystemCursor cursortype) = 0;
virtual void setCursor(Cursor *cursor) = 0;
virtual void setCursor() = 0;
virtual Cursor *getCursor() const = 0;
virtual int getX() const = 0;
virtual int getY() const = 0;
virtual void getPosition(int &x, int &y) const = 0;
+122
View File
@@ -0,0 +1,122 @@
/**
* 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.
**/
// LOVE
#include "Cursor.h"
#include "common/config.h"
namespace love
{
namespace mouse
{
namespace sdl
{
Cursor::Cursor(image::ImageData *data, int hotx, int hoty)
: cursor(0)
, type(CURSORTYPE_IMAGE)
, systemType(CURSOR_MAX_ENUM)
{
Uint32 rmask, gmask, bmask, amask;
#ifdef LOVE_BIG_ENDIAN
rmask = 0xFF000000;
gmask = 0x00FF0000;
bmask = 0x0000FF00;
amask = 0x000000FF;
#else
rmask = 0x000000FF;
gmask = 0x0000FF00;
bmask = 0x00FF0000;
amask = 0xFF000000;
#endif
int w = data->getWidth();
int h = data->getHeight();
int pitch = w * 4;
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(data->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
if (!surface)
throw love::Exception("Cannot create cursor: out of memory!");
cursor = SDL_CreateColorCursor(surface, hotx, hoty);
SDL_FreeSurface(surface);
if (!cursor)
throw love::Exception("Cannot create cursor: %s", SDL_GetError());
}
Cursor::Cursor(mouse::Cursor::SystemCursor cursortype)
: cursor(0)
, type(CURSORTYPE_SYSTEM)
, systemType(cursortype)
{
SDL_SystemCursor sdlcursortype;
if (systemCursors.find(cursortype, sdlcursortype))
cursor = SDL_CreateSystemCursor(sdlcursortype);
else
throw love::Exception("Cannot create system cursor: invalid type.");
if (!cursor)
throw love::Exception("Cannot create system cursor: %s", SDL_GetError());
}
Cursor::~Cursor()
{
if (cursor)
SDL_FreeCursor(cursor);
}
void *Cursor::getHandle() const
{
return cursor;
}
Cursor::CursorType Cursor::getType() const
{
return type;
}
Cursor::SystemCursor Cursor::getSystemType() const
{
return systemType;
}
EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM>::Entry Cursor::systemCursorEntries[] =
{
{Cursor::CURSOR_ARROW, SDL_SYSTEM_CURSOR_ARROW},
{Cursor::CURSOR_IBEAM, SDL_SYSTEM_CURSOR_IBEAM},
{Cursor::CURSOR_WAIT, SDL_SYSTEM_CURSOR_WAIT},
{Cursor::CURSOR_CROSSHAIR, SDL_SYSTEM_CURSOR_CROSSHAIR},
{Cursor::CURSOR_WAITARROW, SDL_SYSTEM_CURSOR_WAITARROW},
{Cursor::CURSOR_SIZENWSE, SDL_SYSTEM_CURSOR_SIZENWSE},
{Cursor::CURSOR_SIZENESW, SDL_SYSTEM_CURSOR_SIZENESW},
{Cursor::CURSOR_SIZEWE, SDL_SYSTEM_CURSOR_SIZEWE},
{Cursor::CURSOR_SIZENS, SDL_SYSTEM_CURSOR_SIZENS},
{Cursor::CURSOR_SIZEALL, SDL_SYSTEM_CURSOR_SIZEALL},
{Cursor::CURSOR_NO, SDL_SYSTEM_CURSOR_NO},
{Cursor::CURSOR_HAND, SDL_SYSTEM_CURSOR_HAND},
};
EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM> Cursor::systemCursors(Cursor::systemCursorEntries, sizeof(Cursor::systemCursorEntries));
} // sdl
} // mouse
} // love
+64
View File
@@ -0,0 +1,64 @@
/**
* 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_MOUSE_SDL_CURSOR_H
#define LOVE_MOUSE_SDL_CURSOR_H
// LOVE
#include "mouse/Cursor.h"
#include "common/EnumMap.h"
// SDL
#include <SDL_mouse.h>
namespace love
{
namespace mouse
{
namespace sdl
{
class Cursor : public love::mouse::Cursor
{
public:
Cursor(image::ImageData *imageData, int hotx, int hoty);
Cursor(SystemCursor cursortype);
~Cursor();
void *getHandle() const;
CursorType getType() const;
SystemCursor getSystemType() const;
private:
SDL_Cursor *cursor;
CursorType type;
SystemCursor systemType;
static EnumMap<SystemCursor, SDL_SystemCursor, CURSOR_MAX_ENUM>::Entry systemCursorEntries[];
static EnumMap<SystemCursor, SDL_SystemCursor, CURSOR_MAX_ENUM> systemCursors;
};
} // sdl
} // mouse
} // love
#endif // LOVE_MOUSE_SDL_CURSOR_H
+63 -5
View File
@@ -18,10 +18,12 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
// LOVE
#include "Mouse.h"
#include "window/sdl/Window.h"
// SDL
#include <SDL.h>
#include <SDL_mouse.h>
namespace love
{
@@ -35,6 +37,50 @@ const char *Mouse::getName() const
return "love.mouse.sdl";
}
Mouse::Mouse()
: curCursor(0)
{
}
Mouse::~Mouse()
{
if (curCursor)
setCursor();
}
love::mouse::Cursor *Mouse::newCursor(love::image::ImageData *data, int hotx, int hoty)
{
return new Cursor(data, hotx, hoty);
}
love::mouse::Cursor *Mouse::newCursor(love::mouse::Cursor::SystemCursor cursortype)
{
return new Cursor(cursortype);
}
void Mouse::setCursor(love::mouse::Cursor *cursor)
{
Object::AutoRelease cursorrelease(curCursor);
curCursor = cursor;
curCursor->retain();
SDL_SetCursor((SDL_Cursor *) cursor->getHandle());
}
void Mouse::setCursor()
{
Object::AutoRelease cursorrelease(curCursor);
curCursor = NULL;
SDL_SetCursor(SDL_GetDefaultCursor());
}
love::mouse::Cursor *Mouse::getCursor() const
{
return curCursor;
}
int Mouse::getX() const
{
int x;
@@ -56,7 +102,13 @@ void Mouse::getPosition(int &x, int &y) const
void Mouse::setPosition(int x, int y)
{
SDL_WarpMouse(x, y);
love::window::Window *window = love::window::sdl::Window::getSingleton();
SDL_Window *handle = NULL;
if (window)
handle = (SDL_Window *) window->getHandle();
SDL_WarpMouseInWindow(handle, x, y);
}
void Mouse::setX(int x)
@@ -91,17 +143,23 @@ bool Mouse::isDown(Button *buttonlist) const
bool Mouse::isVisible() const
{
return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) ? true : false;
return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE;
}
void Mouse::setGrab(bool grab)
{
SDL_WM_GrabInput(grab ? SDL_GRAB_ON : SDL_GRAB_OFF);
love::window::Window *window = love::window::sdl::Window::getSingleton();
if (window)
window->setMouseGrab(grab);
}
bool Mouse::isGrabbed() const
{
return (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON ? true : false);
love::window::Window *window = love::window::sdl::Window::getSingleton();
if (window)
return window->isMouseGrabbed();
else
return false;
}
} // sdl
+17
View File
@@ -23,6 +23,7 @@
// LOVE
#include "mouse/Mouse.h"
#include "Cursor.h"
namespace love
{
@@ -38,6 +39,17 @@ public:
// Implements Module.
const char *getName() const;
Mouse();
~Mouse();
love::mouse::Cursor *newCursor(love::image::ImageData *data, int hotx, int hoty);
love::mouse::Cursor *newCursor(love::mouse::Cursor::SystemCursor cursortype);
void setCursor(love::mouse::Cursor *cursor);
void setCursor();
love::mouse::Cursor *getCursor() const;
int getX() const;
int getY() const;
void getPosition(int &x, int &y) const;
@@ -49,6 +61,11 @@ public:
bool isVisible() const;
void setGrab(bool grab);
bool isGrabbed() const;
private:
love::mouse::Cursor *curCursor;
}; // Mouse
} // sdl
+66
View File
@@ -0,0 +1,66 @@
/**
* 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.
**/
// LOVE
#include "wrap_Cursor.h"
#include "Cursor.h"
namespace love
{
namespace mouse
{
int w_getType(lua_State *L)
{
mouse::Cursor *cursor = luax_checktype<mouse::Cursor>(L, 1, "Cursor", MOUSE_CURSOR_T);
Cursor::CursorType ctype = cursor->getType();
const char *ctypestr;
if (!mouse::Cursor::getConstant(ctype, ctypestr))
return luaL_error(L, "Unknown cursor type.");
lua_pushstring(L, ctypestr);
Cursor::SystemCursor systype = cursor->getSystemType();
const char *systypestr;
if (mouse::Cursor::getConstant(systype, systypestr))
{
lua_pushstring(L, systypestr);
return 2;
}
return 1;
};
static const luaL_Reg functions[] =
{
{ "getType", w_getType },
{ 0, 0 },
};
extern "C" int luaopen_cursor(lua_State *L)
{
return luax_register_type(L, "Cursor", functions);
}
} // mouse
} // love
+39
View File
@@ -0,0 +1,39 @@
/**
* 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_MOUSE_WRAP_CURSOR_H
#define LOVE_MOUSE_WRAP_CURSOR_H
// LOVE
#include "common/runtime.h"
namespace love
{
namespace mouse
{
int w_getType(lua_State *L);
extern "C" int luaopen_cursor(lua_State *L);
} // mouse
} // love
#endif // LOVE_MOUSE_WRAP_CURSOR_H
+86 -3
View File
@@ -18,12 +18,13 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
// LOVE
#include "wrap_Mouse.h"
#include "wrap_Cursor.h"
#include "common/config.h"
#include "sdl/Mouse.h"
#include "wrap_Mouse.h"
namespace love
{
namespace mouse
@@ -31,6 +32,78 @@ namespace mouse
static Mouse *instance = 0;
int w_newCursor(lua_State *L)
{
Cursor *cursor = 0;
if (lua_isstring(L, 1))
{
// System cursor type.
const char *str = luaL_checkstring(L, 1);
Cursor::SystemCursor systemCursor;
if (!Cursor::getConstant(str, systemCursor))
return luaL_error(L, "Invalid cursor type %s", str);
try
{
cursor = instance->newCursor(systemCursor);
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
}
else
{
// Custom image.
love::image::ImageData *data = luax_checktype<love::image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
int hotx = luaL_optint(L, 2, 0);
int hoty = luaL_optint(L, 3, 0);
try
{
cursor = instance->newCursor(data, hotx, hoty);
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
}
luax_newtype(L, "Cursor", MOUSE_CURSOR_T, (void *) cursor);
return 1;
}
int w_setCursor(lua_State *L)
{
// Revert to the default system cursor if no argument is given.
if (lua_isnoneornil(L, 1))
{
instance->setCursor();
return 0;
}
Cursor *cursor = luax_checktype<Cursor>(L, 1, "Cursor", MOUSE_CURSOR_T);
instance->setCursor(cursor);
return 0;
}
int w_getCursor(lua_State *L)
{
Cursor *cursor = instance->getCursor();
if (cursor)
{
cursor->retain();
luax_newtype(L, "Cursor", MOUSE_CURSOR_T, (void *) cursor);
}
else
lua_pushnil(L);
return 1;
}
int w_getX(lua_State *L)
{
lua_pushnumber(L, instance->getX());
@@ -122,6 +195,9 @@ int w_isGrabbed(lua_State *L)
// List of functions to wrap.
static const luaL_Reg functions[] =
{
{ "newCursor", w_newCursor },
{ "setCursor", w_setCursor },
{ "getCursor", w_getCursor },
{ "getX", w_getX },
{ "getY", w_getY },
{ "setX", w_setX },
@@ -136,6 +212,13 @@ static const luaL_Reg functions[] =
{ 0, 0 }
};
// Types for this module.
static const lua_CFunction types[] =
{
luaopen_cursor,
0,
};
extern "C" int luaopen_love_mouse(lua_State *L)
{
if (instance == 0)
@@ -157,7 +240,7 @@ extern "C" int luaopen_love_mouse(lua_State *L)
w.name = "mouse";
w.flags = MODULE_T;
w.functions = functions;
w.types = 0;
w.types = types;
return luax_register_module(L, w);
}
+5 -1
View File
@@ -22,13 +22,17 @@
#define LOVE_MOUSE_WRAP_MOUSE_H
// LOVE
#include "Mouse.h"
#include "common/runtime.h"
#include "common/config.h"
namespace love
{
namespace mouse
{
int w_newCursor(lua_State *L);
int w_setCursor(lua_State *L);
int w_getCursor(lua_State *L);
int w_getX(lua_State *L);
int w_getY(lua_State *L);
int w_getPosition(lua_State *L);
+63
View File
@@ -0,0 +1,63 @@
/**
* 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 "System.h"
namespace love
{
namespace system
{
std::string System::getOS() const
{
#ifdef LOVE_MACOSX
return "OS X";
#elif LOVE_WINDOWS
return "Windows";
#elif LOVE_LINUX
return "Linux";
#else
return "Unknown";
#endif
}
bool System::getConstant(const char *in, System::PowerState &out)
{
return powerStates.find(in, out);
}
bool System::getConstant(System::PowerState in, const char *&out)
{
return powerStates.find(in, out);
}
StringMap<System::PowerState, System::POWER_MAX_ENUM>::Entry System::powerEntries[] =
{
{"unknown", System::POWER_UNKNOWN},
{"battery", System::POWER_BATTERY},
{"nobattery", System::POWER_NO_BATTERY},
{"charging", System::POWER_CHARGING},
{"charged", System::POWER_CHARGED},
};
StringMap<System::PowerState, System::POWER_MAX_ENUM> System::powerStates(System::powerEntries, sizeof(System::powerEntries));
} // system
} // love
+101
View File
@@ -0,0 +1,101 @@
/**
* 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_SYSTEM_H
#define LOVE_SYSTEM_H
// LOVE
#include "common/config.h"
#include "common/Module.h"
#include "common/StringMap.h"
// stdlib
#include <string>
namespace love
{
namespace system
{
class System : public Module
{
public:
enum PowerState
{
POWER_UNKNOWN,
POWER_BATTERY,
POWER_NO_BATTERY,
POWER_CHARGING,
POWER_CHARGED,
POWER_MAX_ENUM
};
virtual ~System() {}
/**
* Gets the current operating system.
**/
std::string getOS() const;
/**
* Gets the number of reported CPU cores on the current system.
* Does not account for technologies such as Hyperthreading: a 4-core
* Hyperthreading-enabled Intel CPU will report 8, instead of 4.
**/
virtual int getProcessorCount() const = 0;
/**
* Replaces the contents of the system's text clipboard with a string.
* @param text The clipboard text to set.
**/
virtual void setClipboardText(const std::string &text) const = 0;
/**
* Gets the contents of the system's text clipboard.
**/
virtual std::string getClipboardText() const = 0;
/**
* Gets information about the system's power supply.
*
* @param[out] seconds Time in seconds of battery life left.
* -1 if a value can't be determined.
* @param[out] percent The percentage of battery life left (0-100.)
* -1 if a value can't be determined.
*
* @return The current state of the battery.
**/
virtual PowerState getPowerInfo(int &seconds, int &percent) const = 0;
static bool getConstant(const char *in, PowerState &out);
static bool getConstant(PowerState in, const char *&out);
private:
static StringMap<PowerState, POWER_MAX_ENUM>::Entry powerEntries[];
static StringMap<PowerState, POWER_MAX_ENUM> powerStates;
}; // System
} // system
} // love
#endif // LOVE_SYSTEM_H
+91
View File
@@ -0,0 +1,91 @@
/**
* 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.
**/
// LOVE
#include "System.h"
// SDL
#include <SDL_clipboard.h>
#include <SDL_cpuinfo.h>
namespace love
{
namespace system
{
namespace sdl
{
System::System()
{
}
const char *System::getName() const
{
return "love.system.sdl";
}
int System::getProcessorCount() const
{
return SDL_GetCPUCount();
}
void System::setClipboardText(const std::string &text) const
{
SDL_SetClipboardText(text.c_str());
}
std::string System::getClipboardText() const
{
std::string text("");
char *ctext = SDL_GetClipboardText();
if (ctext)
{
text = std::string(ctext);
SDL_free(ctext);
}
return text;
}
love::system::System::PowerState System::getPowerInfo(int &seconds, int &percent) const
{
SDL_PowerState sdlstate = SDL_GetPowerInfo(&seconds, &percent);
PowerState state = POWER_UNKNOWN;
powerStates.find(sdlstate, state);
return state;
}
EnumMap<System::PowerState, SDL_PowerState, System::POWER_MAX_ENUM>::Entry System::powerEntries[] =
{
{System::POWER_UNKNOWN, SDL_POWERSTATE_UNKNOWN},
{System::POWER_BATTERY, SDL_POWERSTATE_ON_BATTERY},
{System::POWER_NO_BATTERY, SDL_POWERSTATE_NO_BATTERY},
{System::POWER_CHARGING, SDL_POWERSTATE_CHARGING},
{System::POWER_CHARGED, SDL_POWERSTATE_CHARGED},
};
EnumMap<System::PowerState, SDL_PowerState, System::POWER_MAX_ENUM> System::powerStates(System::powerEntries, sizeof(System::powerEntries));
} // sdl
} // system
} // love
+66
View File
@@ -0,0 +1,66 @@
/**
* 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_SYSTEM_SDL_SYSTEM_H
#define LOVE_SYSTEM_SDL_SYSTEM_H
// LOVE
#include "system/System.h"
#include "common/EnumMap.h"
// SDL
#include <SDL_power.h>
namespace love
{
namespace system
{
namespace sdl
{
class System : public love::system::System
{
public:
System();
virtual ~System() {}
// Implements Module.
const char *getName() const;
int getProcessorCount() const;
void setClipboardText(const std::string &text) const;
std::string getClipboardText() const;
PowerState getPowerInfo(int &seconds, int &percent) const;
private:
static EnumMap<PowerState, SDL_PowerState, POWER_MAX_ENUM>::Entry powerEntries[];
static EnumMap<PowerState, SDL_PowerState, POWER_MAX_ENUM> powerStates;
}; // System
} // sdl
} // system
} // love
#endif // LOVE_SYSTEM_SDL_SYSTEM_H
+112
View File
@@ -0,0 +1,112 @@
/**
* 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.
**/
// LOVE
#include "wrap_System.h"
#include "sdl/System.h"
namespace love
{
namespace system
{
static System *instance = 0;
int w_getOS(lua_State *L)
{
luax_pushstring(L, instance->getOS());
return 1;
}
int w_getProcessorCount(lua_State *L)
{
lua_pushinteger(L, instance->getProcessorCount());
return 1;
}
int w_setClipboardText(lua_State *L)
{
const char *text = luaL_checkstring(L, 1);
instance->setClipboardText(text);
return 0;
}
int w_getClipboardText(lua_State *L)
{
luax_pushstring(L, instance->getClipboardText());
return 1;
}
int w_getPowerInfo(lua_State *L)
{
int seconds = -1, percent = -1;
const char *str;
System::PowerState state = instance->getPowerInfo(seconds, percent);
if (!System::getConstant(state, str))
str = "unknown";
lua_pushstring(L, str);
if (percent >= 0)
lua_pushinteger(L, percent);
else
lua_pushnil(L);
if (seconds >= 0)
lua_pushinteger(L, seconds);
else
lua_pushnil(L);
return 3;
}
static const luaL_Reg functions[] =
{
{ "getOS", w_getOS },
{ "getProcessorCount", w_getProcessorCount },
{ "setClipboardText", w_setClipboardText },
{ "getClipboardText", w_getClipboardText },
{ "getPowerInfo", w_getPowerInfo },
{ 0, 0 }
};
extern "C" int luaopen_love_system(lua_State *L)
{
if (instance == 0)
{
instance = new love::system::sdl::System();
}
else
instance->retain();
WrappedModule w;
w.module = instance;
w.name = "system";
w.flags = MODULE_T;
w.functions = functions;
w.types = 0;
return luax_register_module(L, w);
}
} // system
} // love
+43
View File
@@ -0,0 +1,43 @@
/**
* 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_WRAP_SYSTEM_H
#define LOVE_WRAP_SYSTEM_H
// LOVE
#include "System.h"
#include "common/runtime.h"
namespace love
{
namespace system
{
int w_getOS(lua_State *L);
int w_getProcessorCount(lua_State *L);
int w_setClipboardText(lua_State *L);
int w_getClipboardText(lua_State *L);
int w_getPowerInfo(lua_State *L);
extern "C" LOVE_EXPORT int luaopen_love_system(lua_State *L);
} // system
} // love
#endif // LOVE_WRAP_SYSTEM_H
+6 -4
View File
@@ -24,10 +24,6 @@ namespace love
{
namespace thread
{
const char *ThreadModule::getName() const
{
return "love.thread.sdl";
}
LuaThread *ThreadModule::newThread(const std::string &name, love::Data *data)
{
@@ -44,5 +40,11 @@ Channel *ThreadModule::getChannel(const std::string &name)
{
return Channel::getChannel(name);
}
const char *ThreadModule::getName() const
{
return "love.thread.sdl";
}
} // thread
} // love
+17 -11
View File
@@ -25,12 +25,14 @@
#include <string>
// LOVE
#include <common/Data.h>
#include <common/Module.h>
#include <thread/Thread.h>
#include <thread/Channel.h>
#include <thread/LuaThread.h>
#include <thread/threads.h>
#include "common/Data.h"
#include "common/Module.h"
#include "common/StringMap.h"
#include "Thread.h"
#include "Channel.h"
#include "LuaThread.h"
#include "threads.h"
namespace love
{
@@ -39,13 +41,17 @@ namespace thread
class ThreadModule : public love::Module
{
public:
virtual ~ThreadModule() {}
LuaThread *newThread(const std::string &name, love::Data *data);
Channel *newChannel();
Channel *getChannel(const std::string &name);
const char *getName() const;
virtual ~ThreadModule() {}
virtual LuaThread *newThread(const std::string &name, love::Data *data);
virtual Channel *newChannel();
virtual Channel *getChannel(const std::string &name);
// Implements Module.
virtual const char *getName() const;
}; // ThreadModule
} // thread
} // love
+1 -1
View File
@@ -51,7 +51,7 @@ bool Thread::start()
return false;
if (thread) // Clean old handle up
SDL_WaitThread(thread, 0);
thread = SDL_CreateThread(thread_runner, this);
thread = SDL_CreateThread(thread_runner, NULL, this);
running = (thread != 0);
return running;
}
+2 -2
View File
@@ -39,12 +39,12 @@ Mutex::~Mutex()
void Mutex::lock()
{
SDL_mutexP(mutex);
SDL_LockMutex(mutex);
}
void Mutex::unlock()
{
SDL_mutexV(mutex);
SDL_UnlockMutex(mutex);
}
Conditional::Conditional()
+10 -5
View File
@@ -18,16 +18,20 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
// LOVE
#include "wrap_ThreadModule.h"
#include "wrap_LuaThread.h"
#include "wrap_Channel.h"
#include <filesystem/File.h>
#include <filesystem/FileData.h>
#include "ThreadModule.h"
#include "filesystem/File.h"
#include "filesystem/FileData.h"
namespace love
{
namespace thread
{
static ThreadModule *instance = 0;
int w_newThread(lua_State *L)
@@ -89,7 +93,7 @@ extern "C" int luaopen_love_thread(lua_State *L)
{
try
{
instance = new ThreadModule();
instance = new love::thread::ThreadModule();
}
catch (Exception & e)
{
@@ -108,5 +112,6 @@ extern "C" int luaopen_love_thread(lua_State *L)
return luax_register_module(L, w);
}
}
}
} // thread
} // love
+2 -1
View File
@@ -22,7 +22,8 @@
#define LOVE_THREAD_WRAP_THREADMODULE_H
// LOVE
#include "ThreadModule.h"
#include "common/config.h"
#include "common/runtime.h"
namespace love
{
+22
View File
@@ -40,13 +40,35 @@ void Window::swapBuffers()
WindowFlags::WindowFlags()
: fullscreen(false)
, fstype(Window::FULLSCREEN_TYPE_NORMAL)
, vsync(true)
, fsaa(0)
, resizable(false)
, minwidth(100)
, minheight(100)
, borderless(false)
, centered(true)
, display(0)
{
}
bool Window::getConstant(const char *in, Window::FullscreenType &out)
{
return fullscreenTypes.find(in, out);
}
bool Window::getConstant(Window::FullscreenType in, const char *&out)
{
return fullscreenTypes.find(in, out);
}
StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM>::Entry Window::fullscreenTypeEntries[] =
{
{"normal", Window::FULLSCREEN_TYPE_NORMAL},
{"desktop", Window::FULLSCREEN_TYPE_DESKTOP},
};
StringMap<Window::FullscreenType, Window::FULLSCREEN_TYPE_MAX_ENUM> Window::fullscreenTypes(Window::fullscreenTypeEntries, sizeof(Window::fullscreenTypeEntries));
} // window
} // love
+61 -18
View File
@@ -21,32 +21,35 @@
#ifndef LOVE_WINDOW_WINDOW_H
#define LOVE_WINDOW_WINDOW_H
// STL
#include <string>
// LOVE
#include "common/Module.h"
#include "common/StringMap.h"
#include "image/ImageData.h"
// C++
#include <string>
#include <vector>
namespace love
{
namespace window
{
struct WindowFlags
{
WindowFlags();
bool fullscreen; // = false
bool vsync; // = true
int fsaa; // = 0
bool resizable; // = false
bool borderless; // = false
bool centered; // = true
}; // WindowFlags
// Forward-declared so it can be used in the class methods. We can't define the
// whole thing here because it uses the Window::Type enum.
struct WindowFlags;
class Window : public Module
{
public:
enum FullscreenType
{
FULLSCREEN_TYPE_NORMAL,
FULLSCREEN_TYPE_DESKTOP,
FULLSCREEN_TYPE_MAX_ENUM
};
struct WindowSize
{
int width;
@@ -56,18 +59,27 @@ public:
virtual ~Window();
virtual bool setWindow(int width = 800, int height = 600, WindowFlags *flags = 0) = 0;
virtual void getWindow(int &width, int &height, WindowFlags &flags) const = 0;
virtual void getWindow(int &width, int &height, WindowFlags &flags) = 0;
virtual bool checkWindowSize(int width, int height, bool fullscreen) const = 0;
virtual WindowSize *getFullscreenSizes(int &n) const = 0;
virtual bool setFullscreen(bool fullscreen, FullscreenType fstype) = 0;
virtual bool setFullscreen(bool fullscreen) = 0;
virtual bool onWindowResize(int width, int height) = 0;
virtual int getDisplayCount() const = 0;
virtual bool checkWindowSize(int width, int height, bool fullscreen, int displayindex) const = 0;
virtual std::vector<WindowSize> getFullscreenSizes(int displayindex) const = 0;
virtual int getWidth() const = 0;
virtual int getHeight() const = 0;
virtual void getDesktopDimensions(int displayindex, int &width, int &height) const = 0;
virtual bool isCreated() const = 0;
virtual void setWindowTitle(const std::string &title) = 0;
virtual std::string getWindowTitle() const = 0;
virtual const std::string &getWindowTitle() const = 0;
virtual bool setIcon(love::image::ImageData *imgd) = 0;
virtual love::image::ImageData *getIcon() = 0;
@@ -83,13 +95,44 @@ public:
virtual void setMouseVisible(bool visible) = 0;
virtual bool getMouseVisible() const = 0;
virtual void setMouseGrab(bool grab) = 0;
virtual bool isMouseGrabbed() const = 0;
virtual const void *getHandle() const = 0;
//virtual static Window *createSingleton() = 0;
//virtual static Window *getSingleton() = 0;
// No virtual statics, of course, but you are supposed to implement this static.
// No virtual statics, of course, but you are supposed to implement these statics.
static bool getConstant(const char *in, FullscreenType &out);
static bool getConstant(FullscreenType in, const char *&out);
protected:
static Window *singleton;
private:
static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM>::Entry fullscreenTypeEntries[];
static StringMap<FullscreenType, FULLSCREEN_TYPE_MAX_ENUM> fullscreenTypes;
}; // Window
struct WindowFlags
{
WindowFlags();
bool fullscreen; // = false
Window::FullscreenType fstype; // = FULLSCREEN_TYPE_NORMAL
bool vsync; // = true
int fsaa; // = 0
bool resizable; // = false
int minwidth; // = 100
int minheight; // = 100
bool borderless; // = false
bool centered; // = true
int display; // = 0
}; // WindowFlags
} // window
} // love
+392 -155
View File
@@ -23,11 +23,10 @@
#include "graphics/Graphics.h"
#include "Window.h"
// SDL
#include <SDL.h>
// STL
// C++
#include <iostream>
#include <vector>
#include <algorithm>
namespace love
{
@@ -39,15 +38,30 @@ namespace sdl
Window::Window()
: windowTitle("")
, created(false)
, mouseGrabbed(false)
, window(0)
, context(0)
{
#ifdef LOVE_MACOSX
// SDL 2 minimizes the window at weird times on OSX if this isn't disabled.
// TODO: do Linux and/or Windows need this as well (multi-monitor)?
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
#endif
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
throw love::Exception(SDL_GetError());
throw love::Exception("%s", SDL_GetError());
}
Window::~Window()
{
if (currentMode.icon)
currentMode.icon->release();
if (curMode.icon)
curMode.icon->release();
if (window)
SDL_DestroyWindow(window);
if (context)
SDL_GL_DeleteContext(context);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
@@ -66,109 +80,181 @@ bool Window::setWindow(int width, int height, WindowFlags *flags)
if (gfx)
gfx->unSetMode();
bool fullscreen = false;
bool vsync = true;
int fsaa = 0;
bool resizable = false;
bool borderless = false;
bool centered = true;
WindowFlags f;
if (flags)
f = *flags;
f.minwidth = std::max(f.minwidth, 0);
f.minheight = std::max(f.minheight, 0);
f.display = std::min(std::max(f.display, 0), getDisplayCount());
// Use the desktop resolution if a width or height of 0 is specified.
if (width == 0 || height == 0)
{
fullscreen = flags->fullscreen;
vsync = flags->vsync;
fsaa = flags->fsaa;
resizable = flags->resizable;
borderless = flags->borderless;
centered = flags->centered;
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(f.display, &mode);
width = mode.w;
height = mode.h;
}
bool mouseVisible = getMouseVisible();
int keyrepeatDelay, keyrepeatInterval;
SDL_GetKeyRepeat(&keyrepeatDelay, &keyrepeatInterval);
Uint32 sdlflags = SDL_WINDOW_OPENGL;
// We need to restart the subsystem for two reasons:
// 1) Special case for fullscreen -> windowed. Windows XP did not
// work well with "normal" display mode change in this case.
// The application window does leave fullscreen, but the desktop
// resolution does not revert to the correct one. Restarting the
// SDL video subsystem does the trick, though.
// 2) Restart the event system (for whatever reason the event system
// started and stopped with SDL_INIT_VIDEO, see:
// http://sdl.beuc.net/sdl.wiki/Introduction_to_Events)
// because the mouse position will not be able to exceed
// the previous' video mode window size (i.e. alway
// love.mouse.getX() < 800 when switching from 800x600 to a
// higher resolution)
SDL_QuitSubSystem(SDL_INIT_VIDEO);
if (centered) // Window should be centered.
SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED=center"));
else
SDL_putenv(const_cast<char *>("SDL_VIDEO_CENTERED="));
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
if (f.fullscreen)
{
std::cout << "Could not init SDL_VIDEO: " << SDL_GetError() << std::endl;
switch (f.fstype)
{
case FULLSCREEN_TYPE_NORMAL:
default:
sdlflags |= SDL_WINDOW_FULLSCREEN;
break;
case FULLSCREEN_TYPE_DESKTOP:
sdlflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
break;
}
}
if (f.resizable)
sdlflags |= SDL_WINDOW_RESIZABLE;
if (f.borderless)
sdlflags |= SDL_WINDOW_BORDERLESS;
// Destroy and recreate the window if the dimensions or flags have changed.
if (window)
{
int curdisplay = SDL_GetWindowDisplayIndex(window);
Uint32 wflags = SDL_GetWindowFlags(window);
wflags &= (SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE | SDL_WINDOW_BORDERLESS);
if (sdlflags != wflags || width != curMode.width || height != curMode.height
|| f.display != curdisplay || f.fsaa != curMode.flags.fsaa)
{
SDL_DestroyWindow(window);
window = 0;
// The old window may have generated pending events which are no
// longer relevant. Destroy them all!
SDL_FlushEvent(SDL_WINDOWEVENT);
}
}
int centeredpos = SDL_WINDOWPOS_CENTERED_DISPLAY(f.display);
int uncenteredpos = SDL_WINDOWPOS_UNDEFINED_DISPLAY(f.display);
if (!window)
{
// In Windows and Linux, some GL attributes are set on window creation.
setWindowGLAttributes(f.fsaa);
const char *title = windowTitle.c_str();
int pos = f.centered ? centeredpos : uncenteredpos;
window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags);
if (!window && f.fsaa > 0)
{
// FSAA might have caused the failure, disable it and try again.
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
window = SDL_CreateWindow(title, pos, pos, width, height, sdlflags);
f.fsaa = 0;
}
// Make sure the window keeps any previously set icon.
if (window && curMode.icon)
setIcon(curMode.icon);
}
if (!window)
{
std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
return false;
}
// Set caption.
setWindowTitle(windowTitle);
setMouseVisible(mouseVisible);
setIcon(currentMode.icon);
SDL_EnableKeyRepeat(keyrepeatDelay, keyrepeatInterval);
// Enforce minimum window dimensions.
SDL_SetWindowMinimumSize(window, f.minwidth, f.minheight);
// Set GL attributes
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vsync ? 1 : 0));
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
if (f.centered && !f.fullscreen)
SDL_SetWindowPosition(window, centeredpos, centeredpos);
// FSAA
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
SDL_RaiseWindow(window);
Uint32 sdlflags = SDL_OPENGL;
// Flags
if (fullscreen)
sdlflags |= SDL_FULLSCREEN;
if (resizable)
sdlflags |= SDL_RESIZABLE;
if (borderless)
sdlflags |= SDL_NOFRAME;
// Have SDL set the video mode.
SDL_Surface *surface;
if ((surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0)
{
bool failed = true;
if (fsaa > 0)
{
// FSAA might have caused the failure, disable it and try again
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
failed = (surface = SDL_SetVideoMode(width, height, 32, sdlflags)) == 0;
}
if (failed)
{
std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
return false;
}
}
if (!setContext(f.fsaa, f.vsync))
return false;
created = true;
const SDL_VideoInfo *videoinfo = SDL_GetVideoInfo();
width = videoinfo->current_w;
height = videoinfo->current_h;
updateWindowFlags(f);
if (gfx)
gfx->setMode(curMode.width, curMode.height);
// Make sure the mouse keeps its previous grab setting.
setMouseGrab(mouseGrabbed);
return true;
}
bool Window::onWindowResize(int width, int height)
{
if (!window)
return false;
curMode.width = width;
curMode.height = height;
return true;
}
bool Window::setContext(int fsaa, bool vsync)
{
// We need to recreate the context if FSAA changes,
// or if the existing context has been invalidated.
if (context && (fsaa != curMode.flags.fsaa || SDL_GL_MakeCurrent(window, context) < 0))
{
SDL_GL_DeleteContext(context);
context = 0;
}
// Create a new OpenGL context.
if (!context)
{
setWindowGLAttributes(fsaa);
context = SDL_GL_CreateContext(window);
if (!context && fsaa > 0)
{
// FSAA might have caused the failure, disable it and try again.
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
context = SDL_GL_CreateContext(window);
}
}
if (!context)
{
std::cerr << "Could not set video mode: " << SDL_GetError() << std::endl;
return false;
}
// Set vertical synchronization.
if (vsync)
{
// Prefer EXT_swap_control_tear (late swaps happen immediately),
// otherwise fall back to regular vsync.
if (SDL_GL_SetSwapInterval(-1) < 0 || SDL_GL_GetSwapInterval() != -1)
SDL_GL_SetSwapInterval(1);
}
else
SDL_GL_SetSwapInterval(0);
// Verify FSAA setting.
int buffers;
int samples;
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
@@ -179,65 +265,173 @@ bool Window::setWindow(int width, int height, WindowFlags *flags)
fsaa = (buffers > 0) ? samples : 0;
}
// Get the actual vsync status
int real_vsync;
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &real_vsync);
// Set the new display mode as the current display mode.
currentMode.width = width;
currentMode.height = height;
currentMode.flags.fsaa = fsaa;
currentMode.flags.fullscreen = fullscreen;
currentMode.flags.vsync = (real_vsync != 0);
currentMode.flags.resizable = ((surface->flags & SDL_RESIZABLE) != 0);
currentMode.flags.borderless = ((surface->flags & SDL_NOFRAME) != 0);
currentMode.flags.centered = centered;
if (gfx)
gfx->setMode(width, height);
curMode.flags.fsaa = fsaa;
curMode.flags.vsync = SDL_GL_GetSwapInterval() != 0;
return true;
}
void Window::getWindow(int &width, int &height, WindowFlags &flags) const
void Window::setWindowGLAttributes(int fsaa) const
{
width = currentMode.width;
height = currentMode.height;
flags = currentMode.flags;
// Set GL window attributes.
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
// FSAA.
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (fsaa > 0) ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, (fsaa > 0) ? fsaa : 0);
}
bool Window::checkWindowSize(int width, int height, bool fullscreen) const
void Window::updateWindowFlags(const WindowFlags &newflags)
{
Uint32 sdlflags = fullscreen ? (SDL_OPENGL | SDL_FULLSCREEN) : SDL_OPENGL;
Uint32 wflags = SDL_GetWindowFlags(window);
// Check if mode is supported
int bpp = SDL_VideoModeOK(width, height, 32, sdlflags);
// Set the new display mode as the current display mode.
SDL_GetWindowSize(window, &curMode.width, &curMode.height);
return (bpp >= 16);
if ((wflags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
{
curMode.flags.fullscreen = true;
curMode.flags.fstype = FULLSCREEN_TYPE_DESKTOP;
}
else if ((wflags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)
{
curMode.flags.fullscreen = true;
curMode.flags.fstype = FULLSCREEN_TYPE_NORMAL;
}
else
{
curMode.flags.fullscreen = false;
curMode.flags.fstype = newflags.fstype;
}
// The min width/height is set to 0 internally in SDL when in fullscreen.
if (curMode.flags.fullscreen)
{
curMode.flags.minwidth = newflags.minwidth;
curMode.flags.minheight = newflags.minheight;
}
else
SDL_GetWindowMinimumSize(window, &curMode.flags.minwidth, &curMode.flags.minheight);
curMode.flags.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0;
curMode.flags.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0;
curMode.flags.centered = newflags.centered;
curMode.flags.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
}
void Window::getWindow(int &width, int &height, WindowFlags &flags)
{
// Window position may be different from creation - update display index.
if (window)
curMode.flags.display = std::max(SDL_GetWindowDisplayIndex(window), 0);
width = curMode.width;
height = curMode.height;
flags = curMode.flags;
}
bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
{
if (!window)
return false;
WindowFlags newflags = curMode.flags;
newflags.fullscreen = fullscreen;
newflags.fstype = fstype;
Uint32 sdlflags = 0;
if (fullscreen)
{
if (fstype == FULLSCREEN_TYPE_DESKTOP)
sdlflags = SDL_WINDOW_FULLSCREEN_DESKTOP;
else
{
sdlflags = SDL_WINDOW_FULLSCREEN;
SDL_DisplayMode mode = {};
mode.w = curMode.width;
mode.h = curMode.height;
SDL_GetClosestDisplayMode(SDL_GetWindowDisplayIndex(window), &mode, &mode);
SDL_SetWindowDisplayMode(window, &mode);
}
}
if (SDL_SetWindowFullscreen(window, sdlflags) == 0)
{
SDL_GL_MakeCurrent(window, context);
updateWindowFlags(newflags);
return true;
}
return false;
}
bool Window::setFullscreen(bool fullscreen)
{
return setFullscreen(fullscreen, curMode.flags.fstype);
}
int Window::getDisplayCount() const
{
return SDL_GetNumVideoDisplays();
}
bool Window::checkWindowSize(int width, int height, bool fullscreen, int displayindex) const
{
if (fullscreen)
{
SDL_DisplayMode mode = {}, closest = {};
mode.w = width;
mode.h = height;
SDL_GetClosestDisplayMode(displayindex, &mode, &closest);
return (mode.w == closest.w && mode.h == closest.h);
}
else
{
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(displayindex, &mode);
return (width <= mode.w && height <= mode.h);
}
}
typedef Window::WindowSize WindowSize;
WindowSize *Window::getFullscreenSizes(int &n) const
std::vector<WindowSize> Window::getFullscreenSizes(int displayindex) const
{
SDL_Rect **modes = SDL_ListModes(0, SDL_OPENGL | SDL_FULLSCREEN);
std::vector<WindowSize> sizes;
if (modes == (SDL_Rect **)0 || modes == (SDL_Rect **)-1)
SDL_DisplayMode mode = {};
std::vector<WindowSize>::const_iterator it;
for (int i = 0; i < SDL_GetNumDisplayModes(displayindex); i++)
{
n = 0;
return NULL;
}
SDL_GetDisplayMode(displayindex, i, &mode);
n = 0;
for (int i = 0; modes[i]; i++)
n++;
// SDL2's display mode list has multiple entries for modes of the same
// size with different bits per pixel, so we need to filter those out.
bool alreadyhassize = false;
for (it = sizes.begin(); it != sizes.end(); ++it)
{
if (it->width == mode.w && it->height == mode.h)
{
alreadyhassize = true;
break;
}
}
WindowSize *sizes = new WindowSize[n];
for (int i = 0; i < n; i++)
{
WindowSize w = {modes[i]->w, modes[i]->h};
sizes[i] = w;
if (!alreadyhassize)
{
WindowSize w = {mode.w, mode.h};
sizes.push_back(w);
}
}
return sizes;
@@ -245,12 +439,28 @@ WindowSize *Window::getFullscreenSizes(int &n) const
int Window::getWidth() const
{
return currentMode.width;
return curMode.width;
}
int Window::getHeight() const
{
return currentMode.height;
return curMode.height;
}
void Window::getDesktopDimensions(int displayindex, int &width, int &height) const
{
if (displayindex >= 0 && displayindex < getDisplayCount())
{
SDL_DisplayMode mode = {};
SDL_GetDesktopDisplayMode(displayindex, &mode);
width = mode.w;
height = mode.h;
}
else
{
width = 0;
height = 0;
}
}
bool Window::isCreated() const
@@ -261,14 +471,13 @@ bool Window::isCreated() const
void Window::setWindowTitle(const std::string &title)
{
windowTitle = title;
SDL_WM_SetCaption(windowTitle.c_str(), 0);
if (window)
SDL_SetWindowTitle(window, title.c_str());
}
std::string Window::getWindowTitle() const
const std::string &Window::getWindowTitle() const
{
// not a reference
// because we want this untouched
// const std::string& might be an option
return windowTitle;
}
@@ -277,6 +486,14 @@ bool Window::setIcon(love::image::ImageData *imgd)
if (!imgd)
return false;
imgd->retain();
if (curMode.icon)
curMode.icon->release();
curMode.icon = imgd;
if (!window)
return false;
Uint32 rmask, gmask, bmask, amask;
#ifdef LOVE_BIG_ENDIAN
rmask = 0xFF000000;
@@ -294,51 +511,46 @@ bool Window::setIcon(love::image::ImageData *imgd)
int h = imgd->getHeight();
int pitch = imgd->getWidth() * 4;
SDL_Surface *icon = 0;
SDL_Surface *sdlicon = 0;
{
// We don't want another thread modifying the ImageData mid-copy.
love::thread::Lock lock(imgd->getMutex());
icon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
sdlicon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
}
if (!icon)
if (!sdlicon)
return false;
SDL_WM_SetIcon(icon, NULL);
SDL_FreeSurface(icon);
imgd->retain();
if (currentMode.icon)
currentMode.icon->release();
currentMode.icon = imgd;
SDL_SetWindowIcon(window, sdlicon);
SDL_FreeSurface(sdlicon);
return true;
}
love::image::ImageData *Window::getIcon()
{
return currentMode.icon;
return curMode.icon;
}
void Window::swapBuffers()
{
SDL_GL_SwapBuffers();
SDL_GL_SwapWindow(window);
}
bool Window::hasFocus() const
{
return (SDL_GetAppState() & SDL_APPINPUTFOCUS) != 0;
return (window && SDL_GetKeyboardFocus() == window);
}
bool Window::hasMouseFocus() const
{
return (SDL_GetAppState() & SDL_APPMOUSEFOCUS) != 0;
return (window && SDL_GetMouseFocus() == window);
}
bool Window::isVisible() const
{
return (SDL_GetAppState() & SDL_APPACTIVE) != 0;
return window && (SDL_GetWindowFlags(window) & SDL_WINDOW_SHOWN) != 0;
}
void Window::setMouseVisible(bool visible)
@@ -348,10 +560,30 @@ void Window::setMouseVisible(bool visible)
bool Window::getMouseVisible() const
{
return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) ? true : false;
return (SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE);
}
love::window::Window *Window::getSingleton()
void Window::setMouseGrab(bool grab)
{
mouseGrabbed = grab;
if (window)
SDL_SetWindowGrab(window, (SDL_bool) grab);
}
bool Window::isMouseGrabbed() const
{
if (window)
return (bool) SDL_GetWindowGrab(window);
else
return mouseGrabbed;
}
const void *Window::getHandle() const
{
return window;
}
love::window::Window *Window::createSingleton()
{
if (!singleton)
singleton = new Window();
@@ -361,6 +593,11 @@ love::window::Window *Window::getSingleton()
return singleton;
}
love::window::Window *Window::getSingleton()
{
return singleton;
}
const char *Window::getName() const
{
return "love.window.sdl";
+34 -5
View File
@@ -24,6 +24,9 @@
// LOVE
#include "window/Window.h"
// SDL
#include <SDL.h>
namespace love
{
namespace window
@@ -39,18 +42,27 @@ public:
~Window();
bool setWindow(int width = 800, int height = 600, WindowFlags *flags = 0);
void getWindow(int &width, int &height, WindowFlags &flags) const;
void getWindow(int &width, int &height, WindowFlags &flags);
bool checkWindowSize(int width, int height, bool fullscreen) const;
WindowSize *getFullscreenSizes(int &n) const;
bool setFullscreen(bool fullscreen, FullscreenType fstype);
bool setFullscreen(bool fullscreen);
bool onWindowResize(int width, int height);
int getDisplayCount() const;
bool checkWindowSize(int width, int height, bool fullscreen, int displayindex) const;
std::vector<WindowSize> getFullscreenSizes(int displayindex) const;
int getWidth() const;
int getHeight() const;
void getDesktopDimensions(int displayindex, int &width, int &height) const;
bool isCreated() const;
void setWindowTitle(const std::string &title);
std::string getWindowTitle() const;
const std::string &getWindowTitle() const;
bool setIcon(love::image::ImageData *imgd);
love::image::ImageData *getIcon();
@@ -65,12 +77,24 @@ public:
void setMouseVisible(bool visible);
bool getMouseVisible() const;
void setMouseGrab(bool grab);
bool isMouseGrabbed() const;
const void *getHandle() const;
static love::window::Window *createSingleton();
static love::window::Window *getSingleton();
const char *getName() const;
private:
bool setContext(int fsaa, bool vsync);
void setWindowGLAttributes(int fsaa) const;
// Update the window flags based on the window's actual state.
void updateWindowFlags(const WindowFlags &newflags);
std::string windowTitle;
struct _currentMode
@@ -82,10 +106,15 @@ private:
WindowFlags flags;
love::image::ImageData *icon;
} currentMode;
} curMode;
bool created;
bool mouseGrabbed;
SDL_Window *window;
SDL_GLContext context;
}; // Window
} // sdl
+104 -28
View File
@@ -28,23 +28,37 @@ namespace window
static Window *instance = 0;
int w_getDisplayCount(lua_State *L)
{
lua_pushinteger(L, instance->getDisplayCount());
return 1;
}
int w_checkMode(lua_State *L)
{
int w = luaL_checkint(L, 1);
int h = luaL_checkint(L, 2);
bool fs = false;
int displayindex = 0;
if (lua_istable(L, 3))
{
lua_getfield(L, 3, "fullscreen");
fs = luax_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 3, "display");
displayindex = luaL_optint(L, -1, 1) - 1;
lua_pop(L, 2);
}
else
{
fs = luax_toboolean(L, 3);
displayindex = luaL_optint(L, 4, 1) - 1;
}
luax_pushboolean(L, instance->checkWindowSize(w, h, fs));
luax_pushboolean(L, instance->checkWindowSize(w, h, fs, displayindex));
return 1;
}
@@ -63,12 +77,33 @@ int w_setMode(lua_State *L)
WindowFlags flags;
lua_getfield(L, 3, "fullscreentype");
if (!lua_isnoneornil(L, -1))
{
const char *typestr = luaL_checkstring(L, -1);
if (!Window::getConstant(typestr, flags.fstype))
return luaL_error(L, "Invalid fullscreen type: %s", typestr);
}
else
{
// Default to "normal" fullscreen.
flags.fstype = Window::FULLSCREEN_TYPE_NORMAL;
}
lua_pop(L, 1);
flags.fullscreen = luax_boolflag(L, 3, "fullscreen", false);
flags.vsync = luax_boolflag(L, 3, "vsync", true);
flags.fsaa = luax_intflag(L, 3, "fsaa", 0);
flags.resizable = luax_boolflag(L, 3, "resizable", false);
flags.minwidth = luax_intflag(L, 3, "minwidth", 100);
flags.minheight = luax_intflag(L, 3, "minheight", 100);
flags.borderless = luax_boolflag(L, 3, "borderless", false);
flags.centered = luax_boolflag(L, 3, "centered", true);
flags.display = luax_intflag(L, 3, "display", 1);
// Display index is 1-based in Lua and 0-based internally.
flags.display--;
try
{
@@ -92,38 +127,52 @@ int w_getMode(lua_State *L)
lua_newtable(L);
const char *fstypestr = "normal";
Window::getConstant(flags.fstype, fstypestr);
lua_pushstring(L, fstypestr);
lua_setfield(L, -2, "fullscreentype");
luax_pushboolean(L, flags.fullscreen);
lua_setfield(L, -2, "fullscreen");
luax_pushboolean(L, flags.vsync);
lua_setfield(L, -2, "vsync");
lua_pushnumber(L, flags.fsaa);
lua_pushinteger(L, flags.fsaa);
lua_setfield(L, -2, "fsaa");
luax_pushboolean(L, flags.resizable);
lua_setfield(L, -2, "resizable");
lua_pushinteger(L, flags.minwidth);
lua_setfield(L, -2, "minwidth");
lua_pushinteger(L, flags.minheight);
lua_setfield(L, -2, "minheight");
luax_pushboolean(L, flags.borderless);
lua_setfield(L, -2, "borderless");
luax_pushboolean(L, flags.centered);
lua_setfield(L, -2, "centered");
// Display index is 0-based internally and 1-based in Lua.
lua_pushinteger(L, flags.display + 1);
lua_setfield(L, -2, "display");
return 3;
}
int w_getModes(lua_State *L)
{
int n;
Window::WindowSize *modes = instance->getFullscreenSizes(n);
int displayindex = luaL_optint(L, 1, 1);
if (modes == 0)
return 0;
std::vector<Window::WindowSize> modes = instance->getFullscreenSizes(displayindex - 1);
lua_createtable(L, n, 0);
lua_createtable(L, modes.size(), 0);
for (int i = 0; i < n ; i++)
for (size_t i = 0; i < modes.size(); i++)
{
lua_pushinteger(L, i+1);
lua_createtable(L, 0, 2);
@@ -141,29 +190,43 @@ int w_getModes(lua_State *L)
lua_settable(L, -3);
}
delete[] modes;
return 1;
}
int w_toggleFullscreen(lua_State *L)
int w_setFullscreen(lua_State *L)
{
int width, height;
WindowFlags flags;
instance->getWindow(width, height, flags);
flags.fullscreen = !flags.fullscreen;
bool fullscreen = luax_toboolean(L, 1);
Window::FullscreenType fstype = Window::FULLSCREEN_TYPE_MAX_ENUM;
try
{
luax_pushboolean(L, instance->setWindow(width, height, &flags));
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
const char *typestr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2);
if (typestr && !Window::getConstant(typestr, fstype))
return luaL_error(L, "Invalid fullscreen type: %s", typestr);
bool success = false;
if (fstype == Window::FULLSCREEN_TYPE_MAX_ENUM)
success = instance->setFullscreen(fullscreen);
else
success = instance->setFullscreen(fullscreen, fstype);
luax_pushboolean(L, success);
return 1;
}
int w_isFullscreen(lua_State *L)
{
int w, h;
WindowFlags flags;
instance->getWindow(w, h, flags);
const char *typestr;
if (!Window::getConstant(flags.fstype, typestr))
luaL_error(L, "Unknown fullscreen type.");
luax_pushboolean(L, flags.fullscreen);
lua_pushstring(L, typestr);
return 2;
}
int w_isCreated(lua_State *L)
{
luax_pushboolean(L, instance->isCreated());
@@ -189,11 +252,21 @@ int w_getDimensions(lua_State *L)
return 2;
}
int w_getDesktopDimensions(lua_State *L)
{
int width = 0, height = 0;
int displayindex = luaL_optint(L, 1, 1) - 1;
instance->getDesktopDimensions(displayindex, width, height);
lua_pushinteger(L, width);
lua_pushinteger(L, height);
return 2;
}
int w_setIcon(lua_State *L)
{
image::ImageData *i = luax_checktype<image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
instance->setIcon(i);
return 0;
luax_pushboolean(L, instance->setIcon(i));
return 1;
}
int w_getIcon(lua_State *L)
@@ -242,15 +315,18 @@ int w_isVisible(lua_State *L)
static const luaL_Reg functions[] =
{
{ "getDisplayCount", w_getDisplayCount },
{ "checkMode", w_checkMode },
{ "setMode", w_setMode },
{ "getMode", w_getMode },
{ "getModes", w_getModes },
{ "toggleFullscreen", w_toggleFullscreen },
{ "setFullscreen", w_setFullscreen },
{ "isFullscreen", w_isFullscreen },
{ "isCreated", w_isCreated },
{ "getWidth", w_getWidth },
{ "getHeight", w_getHeight },
{ "getDimensions", w_getDimensions },
{ "getDesktopDimensions", w_getDesktopDimensions },
{ "setIcon", w_setIcon },
{ "getIcon", w_getIcon },
{ "setTitle", w_setTitle },
@@ -265,7 +341,7 @@ extern "C" int luaopen_love_window(lua_State *L)
{
try
{
instance = sdl::Window::getSingleton();
instance = sdl::Window::createSingleton();
}
catch (love::Exception &e)
{
+4 -1
View File
@@ -29,15 +29,18 @@ namespace love
namespace window
{
int w_getDisplayCount(lua_State *L);
int w_checkMode(lua_State *L);
int w_setMode(lua_State *L);
int w_getMode(lua_State *L);
int w_getModes(lua_State *L);
int w_toggleFullscreen(lua_State *L);
int w_setFullscreen(lua_State *L);
int w_isFullscreen(lua_State *L);
int w_isCreated(lua_State *L);
int w_getWidth(lua_State *L);
int w_getHeight(lua_State *L);
int w_getDimensions(lua_State *L);
int w_getDesktopDimensions(lua_State *L);
int w_setIcon(lua_State *L);
int w_getIcon(lua_State *L);
int w_setTitle(lua_State *L);
+34 -7
View File
@@ -158,6 +158,12 @@ function love.createhandlers()
keyreleased = function (b)
if love.keyreleased then return love.keyreleased(b) end
end,
textinput = function (t)
if love.textinput then return love.textinput(t) end
end,
textedit = function (t,s,l)
if love.textedit then return love.textedit(t,s,l) end
end,
mousepressed = function (x,y,b)
if love.mousepressed then return love.mousepressed(x,y,b) end
end,
@@ -173,9 +179,24 @@ function love.createhandlers()
joystickaxis = function (j,a,v)
if love.joystickaxis then return love.joystickaxis(j,a,v) end
end,
joystickhat = function(j,h,v)
joystickhat = function (j,h,v)
if love.joystickhat then return love.joystickhat(j,h,v) end
end,
gamepadpressed = function (j,b)
if love.gamepadpressed then return love.gamepadpressed(j,b) end
end,
gamepadreleased = function (j,b)
if love.gamepadreleased then return love.gamepadreleased(j,b) end
end,
gamepadaxis = function (j,a,v)
if love.gamepadaxis then return love.gamepadaxis(j,a,v) end
end,
joystickadded = function (j)
if love.joystickadded then return love.joystickadded(j) end
end,
joystickremoved = function(j)
if love.joystickremoved then return love.joystickremoved(j) end
end,
focus = function (f)
if love.focus then return love.focus(f) end
end,
@@ -192,11 +213,7 @@ function love.createhandlers()
if love.threaderror then return love.threaderror(t, err) end
end,
resize = function(w, h)
local ow, oh, flags = love.window.getMode()
if flags.resizable then
love.window.setMode(w, h, flags)
if love.resize then return love.resize(w, h) end
end
if love.resize then return love.resize(w, h) end
end,
}, {
__index = function(self, name)
@@ -266,7 +283,11 @@ function love.init()
window = {
width = 800,
height = 600,
minwidth = 100,
minheight = 100,
fullscreen = false,
fullscreentype = "normal",
display = 1,
vsync = true,
fsaa = 0,
borderless = false,
@@ -285,6 +306,7 @@ function love.init()
math = true,
physics = true,
sound = true,
system = true,
font = true,
thread = true,
window = true,
@@ -322,6 +344,7 @@ function love.init()
"joystick",
"mouse",
"sound",
"system",
"audio",
"image",
"font",
@@ -347,15 +370,19 @@ function love.init()
-- Setup window here.
local has_window = false
if c.window and c.modules.window then
if love.window.checkMode(c.window.width, c.window.height, c.window.fullscreen) or (c.window.width == 0 and c.window.height == 0) then
if love.window.checkMode(c.window.width, c.window.height, c.window.fullscreen, c.window.display) or (c.window.width == 0 and c.window.height == 0) then
assert(love.window.setMode(c.window.width, c.window.height,
{
fullscreen = c.window.fullscreen,
fullscreentype = c.window.fullscreentype,
vsync = c.window.vsync,
fsaa = c.window.fsaa,
resizable = c.window.resizable,
minwidth = c.window.minwidth,
minheight = c.window.minheight,
borderless = c.window.borderless,
centered = c.window.centered,
display = c.window.display,
}), "Could not set window mode")
else
error("Could not set window mode")
+71 -13
View File
@@ -270,6 +270,19 @@ const unsigned char boot_lua[] =
0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x28, 0x62, 0x29,
0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x74, 0x65, 0x78, 0x74, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x74, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x69, 0x6e, 0x70,
0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76,
0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x28, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x28, 0x74, 0x2c, 0x73, 0x2c, 0x6c, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69,
0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65,
0x2e, 0x74, 0x65, 0x78, 0x74, 0x65, 0x64, 0x69, 0x74, 0x28, 0x74, 0x2c, 0x73, 0x2c, 0x6c, 0x29, 0x20, 0x65,
0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72,
@@ -306,12 +319,47 @@ const unsigned char boot_lua[] =
0x6a, 0x2c, 0x61, 0x2c, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x68, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6a, 0x2c, 0x68, 0x2c, 0x76, 0x29, 0x0a,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x68, 0x2c, 0x76, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63,
0x6b, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c,
0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x68, 0x61, 0x74, 0x28, 0x6a, 0x2c,
0x68, 0x2c, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x3d,
0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64,
0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x70, 0x72, 0x65, 0x73,
0x73, 0x65, 0x64, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20,
0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64,
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x72, 0x65, 0x6c,
0x65, 0x61, 0x73, 0x65, 0x64, 0x28, 0x6a, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x61, 0x78, 0x69, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x2c, 0x61, 0x2c, 0x76, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64,
0x61, 0x78, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c,
0x6f, 0x76, 0x65, 0x2e, 0x67, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x64, 0x61, 0x78, 0x69, 0x73, 0x28, 0x6a, 0x2c,
0x61, 0x2c, 0x76, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x3d, 0x20,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6a, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63,
0x6b, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x61, 0x64, 0x64, 0x65,
0x64, 0x28, 0x6a, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20,
0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6a, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63,
0x6b, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x72, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x6a, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x28, 0x66, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x74,
@@ -344,17 +392,9 @@ const unsigned char boot_lua[] =
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x77, 0x2c, 0x20, 0x6f, 0x68, 0x2c, 0x20, 0x66,
0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
0x2e, 0x67, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61,
0x62, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65,
0x74, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x2c, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x29, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x65,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e,
0x72, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x72,
0x65, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x77, 0x2c, 0x20, 0x68, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
0x09, 0x7d, 0x2c, 0x20, 0x7b, 0x0a,
0x09, 0x09, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
@@ -471,8 +511,14 @@ const unsigned char boot_lua[] =
0x09, 0x09, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
0x09, 0x09, 0x09, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x38, 0x30, 0x30, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x36, 0x30, 0x30, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x31, 0x30, 0x30, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x30, 0x30,
0x2c, 0x0a,
0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x61,
0x6c, 0x73, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x20,
0x3d, 0x20, 0x22, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x3d, 0x20, 0x31, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x66, 0x73, 0x61, 0x61, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x61,
@@ -497,6 +543,7 @@ const unsigned char boot_lua[] =
0x09, 0x09, 0x09, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
@@ -553,6 +600,7 @@ const unsigned char boot_lua[] =
0x09, 0x09, 0x22, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x2c, 0x0a,
0x09, 0x09, 0x22, 0x66, 0x6f, 0x6e, 0x74, 0x22, 0x2c, 0x0a,
@@ -590,7 +638,8 @@ const unsigned char boot_lua[] =
0x68, 0x65, 0x63, 0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e,
0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x68, 0x65,
0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x66, 0x75, 0x6c,
0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x28, 0x63, 0x2e, 0x77, 0x69, 0x6e,
0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x2c, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e,
0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x28, 0x63, 0x2e, 0x77, 0x69, 0x6e,
0x64, 0x6f, 0x77, 0x2e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x61, 0x6e, 0x64,
0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d,
0x3d, 0x20, 0x30, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
@@ -602,17 +651,26 @@ const unsigned char boot_lua[] =
0x09, 0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x63,
0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e,
0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65,
0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63,
0x72, 0x65, 0x65, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64,
0x6f, 0x77, 0x2e, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x66, 0x73, 0x61, 0x61, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f,
0x77, 0x2e, 0x66, 0x73, 0x61, 0x61, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x2e,
0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77,
0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6d, 0x69, 0x6e, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x63, 0x2e,
0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6d, 0x69, 0x6e, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x63,
0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73,
0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77,
0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x09, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x3d, 0x20, 0x63, 0x2e, 0x77, 0x69,
0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x2c, 0x0a,
0x09, 0x09, 0x09, 0x7d, 0x29, 0x2c, 0x20, 0x22, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
0x73, 0x65, 0x74, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x29, 0x0a,
0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a,