Browse Source

updated to latest love-android (changeset 7b5f223900b)

fysx 11 years ago
parent
commit
542c029666

+ 5 - 7
jni/love/src/common/Object.cpp

@@ -21,33 +21,31 @@
 // LOVE
 #include "Object.h"
 
-#include <stdio.h>
-
 namespace love
 {
 
 Object::Object()
-	: count(1)
 {
+	count.value = 1;
 }
 
 Object::~Object()
 {
 }
 
-int Object::getReferenceCount() const
+int Object::getReferenceCount()
 {
-	return count;
+	return SDL_AtomicGet(&count);
 }
 
 void Object::retain()
 {
-	++count;
+	SDL_AtomicIncRef(&count);
 }
 
 void Object::release()
 {
-	if (--count <= 0)
+	if (SDL_AtomicDecRef(&count))
 		delete this;
 }
 

+ 9 - 2
jni/love/src/common/Object.h

@@ -21,6 +21,13 @@
 #ifndef LOVE_OBJECT_H
 #define LOVE_OBJECT_H
 
+/**
+ * NOTE: the fact that an SDL header is included in such a widely used header
+ * file is only temporary - in the LOVE 0.10+ codebase we use atomics from
+ * C++11's standard library.
+ **/
+#include <SDL_atomic.h>
+
 namespace love
 {
 
@@ -50,7 +57,7 @@ public:
 	 * Gets the reference count of this Object.
 	 * @returns The reference count.
 	 **/
-	int getReferenceCount() const;
+	int getReferenceCount();
 
 	/**
 	 * Retains the Object, i.e. increases the
@@ -155,7 +162,7 @@ public:
 private:
 
 	// The reference count.
-	int count;
+	SDL_atomic_t count;
 
 }; // Object
 

+ 1 - 0
jni/love/src/common/config.h

@@ -116,6 +116,7 @@
 #	define LOVE_ENABLE_KEYBOARD_SDL
 #	define LOVE_ENABLE_LOVE
 #	define LOVE_ENABLE_LUASOCKET
+#	define LOVE_ENABLE_LUAUTF8
 #	define LOVE_ENABLE_MATH
 #	define LOVE_ENABLE_MOUSE
 #	define LOVE_ENABLE_MOUSE_SDL

+ 1 - 1
jni/love/src/common/runtime.h

@@ -23,7 +23,6 @@
 
 // LOVE
 #include "types.h"
-#include "Object.h"
 
 // Lua
 extern "C" {
@@ -40,6 +39,7 @@ namespace love
 {
 
 // Forward declarations.
+class Object;
 class Module;
 class Reference;
 

+ 45 - 0
jni/love/src/libraries/luautf8/lprefix.h

@@ -0,0 +1,45 @@
+/*
+** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
+** Definitions for Lua code that must come before any other header file
+** See Copyright Notice in lutf8lib.c
+*/
+
+#ifndef lprefix_h
+#define lprefix_h
+
+
+/*
+** Allows POSIX/XSI stuff
+*/
+#if !defined(LUA_USE_C89)	/* { */
+
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE           600
+#elif _XOPEN_SOURCE == 0
+#undef _XOPEN_SOURCE  /* use -D_XOPEN_SOURCE=0 to undefine it */
+#endif
+
+/*
+** Allows manipulation of large files in gcc and some other compilers
+*/
+#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
+#define _LARGEFILE_SOURCE       1
+#define _FILE_OFFSET_BITS       64
+#endif
+
+#endif				/* } */
+
+
+/*
+** Windows stuff
+*/
+#if defined(_WIN32) 	/* { */
+
+#if !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS  /* avoid warnings about ISO C functions */
+#endif
+
+#endif			/* } */
+
+#endif
+

+ 290 - 0
jni/love/src/libraries/luautf8/lutf8lib.c

@@ -0,0 +1,290 @@
+/*
+** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $
+** Standard library for UTF-8 manipulation
+** Modified by the LOVE Development Team to work with Lua 5.1's API
+*/
+
+/******************************************************************************
+ * Copyright (C) 1994-2015 Lua.org, PUC-Rio, 2015 LOVE Development Team.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ ******************************************************************************/
+
+#define lutf8lib_c
+
+#include "lprefix.h"
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lutf8lib.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+#define MAXUNICODE	0x10FFFF
+
+#define iscont(p)	((*(p) & 0xC0) == 0x80)
+
+
+/* from strlib */
+/* translate a relative string position: negative means back from end */
+static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
+  if (pos >= 0) return pos;
+  else if (0u - (size_t)pos > len) return 0;
+  else return (lua_Integer)len + pos + 1;
+}
+
+
+/*
+** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
+*/
+static const char *utf8_decode (const char *o, int *val) {
+  static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
+  const unsigned char *s = (const unsigned char *)o;
+  unsigned int c = s[0];
+  unsigned int res = 0;  /* final result */
+  if (c < 0x80)  /* ascii? */
+    res = c;
+  else {
+    int count = 0;  /* to count number of continuation bytes */
+    while (c & 0x40) {  /* still have continuation bytes? */
+      int cc = s[++count];  /* read next byte */
+      if ((cc & 0xC0) != 0x80)  /* not a continuation byte? */
+        return NULL;  /* invalid byte sequence */
+      res = (res << 6) | (cc & 0x3F);  /* add lower 6 bits from cont. byte */
+      c <<= 1;  /* to test next bit */
+    }
+    res |= ((c & 0x7F) << (count * 5));  /* add first byte */
+    if (count > 3 || res > MAXUNICODE || res <= limits[count])
+      return NULL;  /* invalid byte sequence */
+    s += count;  /* skip continuation bytes read */
+  }
+  if (val) *val = res;
+  return (const char *)s + 1;  /* +1 to include first byte */
+}
+
+
+/*
+** utf8len(s [, i [, j]]) --> number of characters that start in the
+** range [i,j], or nil + current position if 's' is not well formed in
+** that interval
+*/
+static int utflen (lua_State *L) {
+  int n = 0;
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+  lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
+  luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
+                   "initial position out of string");
+  luaL_argcheck(L, --posj < (lua_Integer)len, 3,
+                   "final position out of string");
+  while (posi <= posj) {
+    const char *s1 = utf8_decode(s + posi, NULL);
+    if (s1 == NULL) {  /* conversion error? */
+      lua_pushnil(L);  /* return nil ... */
+      lua_pushinteger(L, posi + 1);  /* ... and current position */
+      return 2;
+    }
+    posi = s1 - s;
+    n++;
+  }
+  lua_pushinteger(L, n);
+  return 1;
+}
+
+
+/*
+** codepoint(s, [i, [j]])  -> returns codepoints for all characters
+** that start in the range [i,j]
+*/
+static int codepoint (lua_State *L) {
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+  lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
+  int n;
+  const char *se;
+  luaL_argcheck(L, posi >= 1, 2, "out of range");
+  luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
+  if (posi > pose) return 0;  /* empty interval; return no values */
+  n = (int)(pose -  posi + 1);
+  if (posi + n <= pose)  /* (lua_Integer -> int) overflow? */
+    return luaL_error(L, "string slice too long");
+  luaL_checkstack(L, n, "string slice too long");
+  n = 0;
+  se = s + pose;
+  for (s += posi - 1; s < se;) {
+    int code;
+    s = utf8_decode(s, &code);
+    if (s == NULL)
+      return luaL_error(L, "invalid UTF-8 code");
+    lua_pushinteger(L, code);
+    n++;
+  }
+  return n;
+}
+
+
+static void pushutfchar (lua_State *L, int arg) {
+  lua_Integer code = luaL_checkinteger(L, arg);
+  luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
+  lua_pushfstring(L, "%U", (long)code);
+}
+
+
+/*
+** utfchar(n1, n2, ...)  -> char(n1)..char(n2)...
+*/
+static int utfchar (lua_State *L) {
+  int n = lua_gettop(L);  /* number of arguments */
+  if (n == 1)  /* optimize common case of single char */
+    pushutfchar(L, 1);
+  else {
+    int i;
+    luaL_Buffer b;
+    luaL_buffinit(L, &b);
+    for (i = 1; i <= n; i++) {
+      pushutfchar(L, i);
+      luaL_addvalue(&b);
+    }
+    luaL_pushresult(&b);
+  }
+  return 1;
+}
+
+
+/*
+** offset(s, n, [i])  -> index where n-th character counting from
+**   position 'i' starts; 0 means character at 'i'.
+*/
+static int byteoffset (lua_State *L) {
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer n  = luaL_checkinteger(L, 2);
+  lua_Integer posi = (n >= 0) ? 1 : len + 1;
+  posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
+  luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
+                   "position out of range");
+  if (n == 0) {
+    /* find beginning of current byte sequence */
+    while (posi > 0 && iscont(s + posi)) posi--;
+  }
+  else {
+    if (iscont(s + posi))
+      luaL_error(L, "initial position is a continuation byte");
+    if (n < 0) {
+       while (n < 0 && posi > 0) {  /* move back */
+         do {  /* find beginning of previous character */
+           posi--;
+         } while (posi > 0 && iscont(s + posi));
+         n++;
+       }
+     }
+     else {
+       n--;  /* do not move for 1st character */
+       while (n > 0 && posi < (lua_Integer)len) {
+         do {  /* find beginning of next character */
+           posi++;
+         } while (iscont(s + posi));  /* (cannot pass final '\0') */
+         n--;
+       }
+     }
+  }
+  if (n == 0)  /* did it find given character? */
+    lua_pushinteger(L, posi + 1);
+  else  /* no such character */
+    lua_pushnil(L);
+  return 1;  
+}
+
+
+static int iter_aux (lua_State *L) {
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer n = lua_tointeger(L, 2) - 1;
+  if (n < 0)  /* first iteration? */
+    n = 0;  /* start from here */
+  else if (n < (lua_Integer)len) {
+    n++;  /* skip current byte */
+    while (iscont(s + n)) n++;  /* and its continuations */
+  }
+  if (n >= (lua_Integer)len)
+    return 0;  /* no more codepoints */
+  else {
+    int code;
+    const char *next = utf8_decode(s + n, &code);
+    if (next == NULL || iscont(next))
+      return luaL_error(L, "invalid UTF-8 code");
+    lua_pushinteger(L, n + 1);
+    lua_pushinteger(L, code);
+    return 2;
+  }
+}
+
+
+static int iter_codes (lua_State *L) {
+  luaL_checkstring(L, 1);
+  lua_pushcfunction(L, iter_aux);
+  lua_pushvalue(L, 1);
+  lua_pushinteger(L, 0);
+  return 3;
+}
+
+
+/* pattern to match a single UTF-8 character */
+#if LUA_VERSION_NUM >= 502
+#define UTF8PATT	"[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
+#else
+/* lua 5.1 doesn't support literal null bytes in patterns */
+#define UTF8PATT	"[%z\x01-\x7F\xC2-\xF4][\x80-\xBF]*"
+#endif
+
+
+static struct luaL_Reg funcs[] = {
+  {"offset", byteoffset},
+  {"codepoint", codepoint},
+  {"char", utfchar},
+  {"len", utflen},
+  {"codes", iter_codes},
+  /* placeholders */
+  {"charpattern", NULL},
+  {NULL, NULL}
+};
+
+
+/* modified version of luaopen_utf8, designed to work with lua 5.1-5.3 */
+int luaopen_luautf8 (lua_State *L) {
+  luaL_Reg *l;
+  lua_createtable(L, 0, (int) (sizeof(funcs) / sizeof(luaL_Reg)) - 1);
+  for (l = funcs; l->name != NULL; l++) {
+    if (l->func != NULL) {
+      lua_pushcfunction(L, l->func);
+      lua_setfield(L, -2, l->name);
+    }
+  }
+  lua_pushliteral(L, UTF8PATT);
+  lua_setfield(L, -2, "charpattern");
+  return 1;
+}
+

+ 17 - 0
jni/love/src/libraries/luautf8/lutf8lib.h

@@ -0,0 +1,17 @@
+
+#ifndef LUAUTF8_LUTF8LIB_H
+#define LUAUTF8_LUTF8LIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lua.h"
+
+LUALIB_API int luaopen_luautf8(lua_State *L);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOVE_LUAUTF8_LUTF8LIB_H */

+ 8 - 0
jni/love/src/love.cpp

@@ -18,6 +18,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
+#include "common/version.h"
 #include "modules/love/love.h"
 #include <SDL.h>
 
@@ -194,6 +195,13 @@ int main(int argc, char **argv)
 	argv = hack_argv;
 #endif // LOVE_LEGENDARY_APP_ARGV_HACK
 
+	if (strcmp(love::VERSION, love_version()) != 0)
+	{
+		printf("Version mismatch detected!\nLOVE binary is version %s\n"
+				"LOVE library is version %s\n", love::VERSION, love_version());
+		return 1;
+	}
+
 	// Oh, you just want the version? Okay!
 	if (argc > 1 && strcmp(argv[1], "--version") == 0)
 	{

+ 33 - 2
jni/love/src/modules/audio/openal/Source.cpp

@@ -33,6 +33,17 @@ namespace audio
 namespace openal
 {
 
+class InvalidFormatException : public love::Exception
+{
+public:
+
+	InvalidFormatException(int channels, int bitdepth)
+		: Exception("%d-channel Sources with %d bits per sample are not supported.", channels, bitdepth)
+	{
+	}
+
+};
+
 StaticDataBuffer::StaticDataBuffer(ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
 {
 	alGenBuffers(1, &buffer);
@@ -68,6 +79,9 @@ Source::Source(Pool *pool, love::sound::SoundData *soundData)
 	, toLoop(0)
 {
 	ALenum fmt = getFormat(soundData->getChannels(), soundData->getBitDepth());
+	if (fmt == 0)
+		throw InvalidFormatException(soundData->getChannels(), soundData->getBitDepth());
+
 	staticBuffer.set(new StaticDataBuffer(fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate()));
 
 	// The buffer has a +2 retain count right now, but we want it to have +1.
@@ -103,6 +117,9 @@ Source::Source(Pool *pool, love::sound::Decoder *decoder)
 	, decoder(decoder)
 	, toLoop(0)
 {
+	if (getFormat(decoder->getChannels(), decoder->getBitDepth()) == 0)
+		throw InvalidFormatException(decoder->getChannels(), decoder->getBitDepth());
+
 	alGenBuffers(MAX_BUFFERS, streamBuffers);
 
 	float z[3] = {0, 0, 0};
@@ -651,8 +668,22 @@ ALenum Source::getFormat(int channels, int bitDepth) const
 		return AL_FORMAT_STEREO8;
 	else if (channels == 2 && bitDepth == 16)
 		return AL_FORMAT_STEREO16;
-	else
-		return 0;
+
+#ifdef AL_EXT_MCFORMATS
+	if (alIsExtensionPresent("AL_EXT_MCFORMATS"))
+	{
+		if (channels == 6 && bitDepth == 8)
+			return AL_FORMAT_51CHN8;
+		else if (channels == 6 && bitDepth == 16)
+			return AL_FORMAT_51CHN16;
+		else if (channels == 8 && bitDepth == 8)
+			return AL_FORMAT_71CHN8;
+		else if (channels == 8 && bitDepth == 16)
+			return AL_FORMAT_71CHN16;
+	}
+#endif
+
+	return 0;
 }
 
 int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d)

+ 6 - 4
jni/love/src/modules/audio/wrap_Audio.cpp

@@ -58,10 +58,12 @@ int w_newSource(lua_State *L)
 
 	Source *t = 0;
 
-	if (luax_istype(L, 1, SOUND_SOUND_DATA_T))
-		t = instance()->newSource(luax_totype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T));
-	else if (luax_istype(L, 1, SOUND_DECODER_T))
-		t = instance()->newSource(luax_totype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T));
+	luax_catchexcept(L, [&]() {
+		if (luax_istype(L, 1, SOUND_SOUND_DATA_T))
+			t = instance()->newSource(luax_totype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T));
+		else if (luax_istype(L, 1, SOUND_DECODER_T))
+			t = instance()->newSource(luax_totype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T));
+	});
 
 	if (t)
 	{

+ 28 - 10
jni/love/src/modules/event/sdl/Event.cpp

@@ -42,14 +42,14 @@ namespace sdl
 
 // SDL reports mouse coordinates in the window coordinate system in OS X, but
 // we want them in pixel coordinates (may be different with high-DPI enabled.)
-static void windowToPixelCoords(int *x, int *y)
+static void windowToPixelCoords(double *x, double *y)
 {
 #ifndef LOVE_ANDROID
 	window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
 	if (window && x)
-		*x = (int) window->toPixels(*x);
+		*x = window->toPixels(*x);
 	if (window && y)
-		*y = (int) window->toPixels(*y);
+		*y = window->toPixels(*y);
 #endif
 }
 
@@ -201,15 +201,30 @@ Message *Event::convert(const SDL_Event &e) const
 		vargs.push_back(new Variant((double) e.edit.length));
 		msg = new Message("textedit", vargs);
 		break;
+	case SDL_MOUSEMOTION:
+		{
+			double x = (double) e.motion.x;
+			double y = (double) e.motion.y;
+			double xrel = (double) e.motion.xrel;
+			double yrel = (double) e.motion.yrel;
+			windowToPixelCoords(&x, &y);
+			windowToPixelCoords(&xrel, &yrel);
+			vargs.push_back(new Variant(x));
+			vargs.push_back(new Variant(y));
+			vargs.push_back(new Variant(xrel));
+			vargs.push_back(new Variant(yrel));
+			msg = new Message("mousemoved", vargs);
+		}
+		break;
 	case SDL_MOUSEBUTTONDOWN:
 	case SDL_MOUSEBUTTONUP:
 		if (buttons.find(e.button.button, button) && mouse::Mouse::getConstant(button, txt))
 		{
-			int x = e.button.x;
-			int y = e.button.y;
+			double x = (double) e.button.x;
+			double y = (double) e.button.y;
 			windowToPixelCoords(&x, &y);
-			vargs.push_back(new Variant((double) x));
-			vargs.push_back(new Variant((double) y));
+			vargs.push_back(new Variant(x));
+			vargs.push_back(new Variant(y));
 			vargs.push_back(new Variant(txt, strlen(txt)));
 			vargs.push_back(new Variant(e.button.which == SDL_TOUCH_MOUSEID));
 			msg = new Message((e.type == SDL_MOUSEBUTTONDOWN) ?
@@ -225,11 +240,14 @@ Message *Event::convert(const SDL_Event &e) const
 				break;
 
 			int mx, my;
+			double dmx, dmy;
 			SDL_GetMouseState(&mx, &my);
-			windowToPixelCoords(&mx, &my);
+			dmx = (double) mx;
+			dmy = (double) my;
+			windowToPixelCoords(&dmx, &dmy);
 
-			vargs.push_back(new Variant((double) mx));
-			vargs.push_back(new Variant((double) my));
+			vargs.push_back(new Variant(dmx));
+			vargs.push_back(new Variant(dmy));
 			vargs.push_back(new Variant(txt, strlen(txt)));
 			vargs.push_back(new Variant(false));
 			msg = new Message("mousepressed", vargs);

+ 2 - 0
jni/love/src/modules/graphics/opengl/Graphics.cpp

@@ -51,6 +51,8 @@ Graphics::Graphics()
 	, active(true)
 	, activeStencil(false)
 {
+	gl = OpenGL();
+
 	states.reserve(10);
 	states.push_back(DisplayState());
 

+ 6 - 2
jni/love/src/modules/love/love.cpp

@@ -47,6 +47,9 @@
 #ifdef LOVE_ENABLE_ENET
 #	include "libraries/enet/lua-enet.h"
 #endif
+#ifdef LOVE_ENABLE_LUAUTF8
+#	include "libraries/luautf8/lutf8lib.h"
+#endif
 
 // Scripts
 #include "scripts/boot.lua.h"
@@ -249,9 +252,7 @@ int luaopen_love(lua_State * L)
 
 	// Preload module loaders.
 	for (int i = 0; modules[i].name != 0; i++)
-	{
 		love::luax_preload(L, modules[i].func, modules[i].name);
-	}
 
 #ifdef LOVE_ENABLE_LUASOCKET
 	love::luasocket::__open(L);
@@ -259,6 +260,9 @@ int luaopen_love(lua_State * L)
 #ifdef LOVE_ENABLE_ENET
 	love::luax_preload(L, luaopen_enet, "enet");
 #endif
+#ifdef LOVE_ENABLE_LUAUTF8
+	love::luax_preload(L, luaopen_luautf8, "utf8");
+#endif
 
 	return 1;
 }

+ 1 - 1
jni/love/src/modules/math/wrap_Math.cpp

@@ -247,7 +247,7 @@ int w_isConvex(lua_State *L)
 		}
 	}
 
-	lua_pushboolean(L, Math::instance.isConvex(vertices));
+	luax_pushboolean(L, Math::instance.isConvex(vertices));
 	return 1;
 }
 

+ 2 - 0
jni/love/src/modules/mouse/Mouse.h

@@ -75,6 +75,8 @@ public:
 	virtual bool isVisible() const = 0;
 	virtual void setGrabbed(bool grab) = 0;
 	virtual bool isGrabbed() const = 0;
+	virtual bool setRelative(bool relative) = 0;
+	virtual bool isRelative() const = 0;
 
 	static bool getConstant(const char *in, Button &out);
 	static bool getConstant(Button in, const char  *&out);

+ 10 - 0
jni/love/src/modules/mouse/sdl/Mouse.cpp

@@ -220,6 +220,16 @@ bool Mouse::isGrabbed() const
 		return false;
 }
 
+bool Mouse::setRelative(bool relative)
+{
+	return SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0;
+}
+
+bool Mouse::isRelative() const
+{
+	return SDL_GetRelativeMouseMode() != SDL_FALSE;
+}
+
 } // sdl
 } // mouse
 } // love

+ 2 - 0
jni/love/src/modules/mouse/sdl/Mouse.h

@@ -66,6 +66,8 @@ public:
 	bool isVisible() const;
 	void setGrabbed(bool grab);
 	bool isGrabbed() const;
+	bool setRelative(bool relative);
+	bool isRelative() const;
 
 private:
 

+ 15 - 0
jni/love/src/modules/mouse/wrap_Mouse.cpp

@@ -185,6 +185,19 @@ int w_isGrabbed(lua_State *L)
 	return 1;
 }
 
+int w_setRelative(lua_State *L)
+{
+	bool relative = luax_toboolean(L, 1);
+	luax_pushboolean(L, instance()->setRelative(relative));
+	return 1;
+}
+
+int w_isRelative(lua_State *L)
+{
+	luax_pushboolean(L, instance()->isRelative());
+	return 1;
+}
+
 // List of functions to wrap.
 static const luaL_Reg functions[] =
 {
@@ -204,6 +217,8 @@ static const luaL_Reg functions[] =
 	{ "getPosition", w_getPosition },
 	{ "setGrabbed", w_setGrabbed },
 	{ "isGrabbed", w_isGrabbed },
+	{ "setRelative", w_setRelative },
+	{ "isRelative", w_isRelative },
 	{ 0, 0 }
 };
 

+ 2 - 0
jni/love/src/modules/mouse/wrap_Mouse.h

@@ -46,6 +46,8 @@ int w_setVisible(lua_State *L);
 int w_isVisible(lua_State *L);
 int w_setGrabbed(lua_State *L);
 int w_isGrabbed(lua_State *L);
+int w_setRelative(lua_State *L);
+int w_isRelative(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_mouse(lua_State *L);
 
 } // mouse

+ 9 - 3
jni/love/src/modules/window/sdl/Window.cpp

@@ -55,11 +55,17 @@ Window::Window()
 
 Window::~Window()
 {
-	if (window)
-		SDL_DestroyWindow(window);
-
 	if (context)
+	{
+		graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
+		if (gfx != nullptr)
+			gfx->unSetMode();
+
 		SDL_GL_DeleteContext(context);
+	}
+
+	if (window)
+		SDL_DestroyWindow(window);
 
 	SDL_QuitSubSystem(SDL_INIT_VIDEO);
 }

+ 12 - 9
jni/love/src/scripts/boot.lua

@@ -169,6 +169,9 @@ function love.createhandlers()
 		mousepressed = function (x,y,b,t)
 			if love.mousepressed then return love.mousepressed(x,y,b,t) end
 		end,
+		mousemoved = function (x,y,xrel,yrel)
+			if love.mousemoved then return love.mousemoved(x,y,xrel,yrel) end
+		end,
 		mousereleased = function (x,y,b,t)
 			if love.mousereleased then return love.mousereleased(x,y,b,t) end
 		end,
@@ -357,6 +360,13 @@ function love.init()
 		accelerometerjoystick = true, -- Only relevant for Android / iOS.
 	}
 
+	-- Console hack, part 1.
+	local openedconsole = false
+	if love.arg.options.console.set and love._openConsole then
+		love._openConsole()
+		openedconsole = true
+	end
+
 	-- If config file exists, load it and allow it to update config table.
 	if not love.conf and love.filesystem and love.filesystem.isFile("conf.lua") then
 		require("conf")
@@ -371,12 +381,8 @@ function love.init()
 		-- the error message can be displayed in the window.
 	end
 
-	if love.arg.options.console.set then
-		c.console = true
-	end
-
-	-- Console hack
-	if c.console and love._openConsole then
+	-- Console hack, part 2.
+	if c.console and love._openConsole and not openedconsole then
 		love._openConsole()
 	end
 
@@ -521,9 +527,6 @@ function love.run()
 			for n,a,b,c,d,e in love.event.poll() do
 				if n == "quit" then
 					if not love.quit or not love.quit() then
-						if love.audio then
-							love.audio.stop()
-						end
 						return
 					end
 				end

+ 25 - 12
jni/love/src/scripts/boot.lua.h

@@ -292,6 +292,14 @@ const unsigned char boot_lua[] =
 	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x28, 
 	0x78, 0x2c, 0x79, 0x2c, 0x62, 0x2c, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
+	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 
+	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x78, 0x72, 0x65, 0x6c, 0x2c, 0x79, 0x72, 
+	0x65, 0x6c, 0x29, 0x0a,
+	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 
+	0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 
+	0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x28, 0x78, 0x2c, 0x79, 0x2c, 
+	0x78, 0x72, 0x65, 0x6c, 0x2c, 0x79, 0x72, 0x65, 0x6c, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+	0x09, 0x09, 0x65, 0x6e, 0x64, 0x2c, 0x0a,
 	0x09, 0x09, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x20, 
 	0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x78, 0x2c, 0x79, 0x2c, 0x62, 0x2c, 0x74, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x65, 
@@ -645,6 +653,19 @@ const unsigned char boot_lua[] =
 	0x6e, 0x6c, 0x79, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 
 	0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x2f, 0x20, 0x69, 0x4f, 0x53, 0x2e, 0x0a,
 	0x09, 0x7d, 0x0a,
+	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x2c, 0x20, 
+	0x70, 0x61, 0x72, 0x74, 0x20, 0x31, 0x2e, 0x0a,
+	0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 
+	0x6c, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x0a,
+	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 
+	0x6e, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x64, 
+	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 
+	0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 
+	0x65, 0x28, 0x29, 0x0a,
+	0x09, 0x09, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 
+	0x74, 0x72, 0x75, 0x65, 0x0a,
+	0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x2d, 0x2d, 0x20, 0x49, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 
 	0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2c, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x69, 0x74, 0x20, 0x61, 
 	0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64, 
@@ -679,15 +700,12 @@ const unsigned char boot_lua[] =
 	0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 
 	0x79, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x72, 0x67, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 
-	0x6e, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 
-	0x6e, 0x0a,
-	0x09, 0x09, 0x63, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a,
-	0x09, 0x65, 0x6e, 0x64, 0x0a,
-	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x0a,
+	0x09, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x63, 0x6b, 0x2c, 0x20, 
+	0x70, 0x61, 0x72, 0x74, 0x20, 0x32, 0x2e, 0x0a,
 	0x09, 0x69, 0x66, 0x20, 0x63, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 
 	0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x20, 
-	0x74, 0x68, 0x65, 0x6e, 0x0a,
+	0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x73, 
+	0x6f, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 
 	0x65, 0x28, 0x29, 0x0a,
 	0x09, 0x65, 0x6e, 0x64, 0x0a,
@@ -951,11 +969,6 @@ const unsigned char boot_lua[] =
 	0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71, 
 	0x75, 0x69, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x71, 0x75, 
 	0x69, 0x74, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 
-	0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 
-	0x73, 0x74, 0x6f, 0x70, 0x28, 0x29, 0x0a,
-	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,