Browse Source

Text:add and Text:addf now return index numbers which can be used as arguments to Text:getWidth and text:getHeight to determine the (pre-transformed) width and height of specific text within the Text object.

Alex Szpakowski 9 years ago
parent
commit
e9c75c342e

+ 1 - 1
changes.txt

@@ -63,7 +63,7 @@ Released: N/A
   * Added love.math.compress and love.math.decompress.
   * Added love.math.compress and love.math.decompress.
   * Added Channel:performAtomic.
   * Added Channel:performAtomic.
 
 
-  * Changed love.mousepressed], love.mousereleased, and love.mouse.isDown to use button numbers instead of named button constants.
+  * Changed love.mousepressed, love.mousereleased, and love.mouse.isDown to use button numbers instead of named button constants.
   * Changed love.keypressed to be love.keypressed(key, scancode, isrepeat).
   * Changed love.keypressed to be love.keypressed(key, scancode, isrepeat).
   * Changed love.keyreleased to be love.keyreleased(key, scancode).
   * Changed love.keyreleased to be love.keyreleased(key, scancode).
   * Changed Font:getWrap's second return value to be a table containing the text split into lines.
   * Changed Font:getWrap's second return value to be a table containing the text split into lines.

+ 4 - 0
platform/xcode/love.xcodeproj/project.pbxproj

@@ -17,6 +17,7 @@
 		A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		FA0797991BF480A200034B7C /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA0797981BF480A200034B7C /* GameController.framework */; };
 		FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
 		FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
 		FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		FA0B78D21A95814A000E1D17 /* love.icns in Resources */ = {isa = PBXBuildFile; fileRef = FA0B78D01A95814A000E1D17 /* love.icns */; };
 		FA0B78D21A95814A000E1D17 /* love.icns in Resources */ = {isa = PBXBuildFile; fileRef = FA0B78D01A95814A000E1D17 /* love.icns */; };
@@ -107,6 +108,7 @@
 		A9D307E9106635C3004FEDF8 /* physfs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = physfs.framework; path = /Library/Frameworks/physfs.framework; sourceTree = "<absolute>"; };
 		A9D307E9106635C3004FEDF8 /* physfs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = physfs.framework; path = /Library/Frameworks/physfs.framework; sourceTree = "<absolute>"; };
 		A9F16926109E7BAD00FC83D1 /* libmodplug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libmodplug.framework; path = /Library/Frameworks/libmodplug.framework; sourceTree = "<absolute>"; };
 		A9F16926109E7BAD00FC83D1 /* libmodplug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libmodplug.framework; path = /Library/Frameworks/libmodplug.framework; sourceTree = "<absolute>"; };
 		A9F169A6109E824900FC83D1 /* mpg123.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mpg123.framework; path = /Library/Frameworks/mpg123.framework; sourceTree = "<absolute>"; };
 		A9F169A6109E824900FC83D1 /* mpg123.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mpg123.framework; path = /Library/Frameworks/mpg123.framework; sourceTree = "<absolute>"; };
+		FA0797981BF480A200034B7C /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.1.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
 		FA08F69116C765A200F007B5 /* love.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		FA08F69116C765A200F007B5 /* love.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		FA0B78D01A95814A000E1D17 /* love.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = love.icns; path = macosx/love.icns; sourceTree = "<group>"; };
 		FA0B78D01A95814A000E1D17 /* love.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = love.icns; path = macosx/love.icns; sourceTree = "<group>"; };
 		FA0B78D11A95814A000E1D17 /* lovedocument.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = lovedocument.icns; path = macosx/lovedocument.icns; sourceTree = "<group>"; };
 		FA0B78D11A95814A000E1D17 /* lovedocument.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = lovedocument.icns; path = macosx/lovedocument.icns; sourceTree = "<group>"; };
@@ -148,6 +150,7 @@
 				FA5D24D11A96E73300C6FC8F /* liblove.a in Frameworks */,
 				FA5D24D11A96E73300C6FC8F /* liblove.a in Frameworks */,
 				FA5D24C21A96D78000C6FC8F /* Foundation.framework in Frameworks */,
 				FA5D24C21A96D78000C6FC8F /* Foundation.framework in Frameworks */,
 				FA5D24961A96CAC200C6FC8F /* CoreMotion.framework in Frameworks */,
 				FA5D24961A96CAC200C6FC8F /* CoreMotion.framework in Frameworks */,
+				FA0797991BF480A200034B7C /* GameController.framework in Frameworks */,
 				FA5D24941A96CABA00C6FC8F /* libz.dylib in Frameworks */,
 				FA5D24941A96CABA00C6FC8F /* libz.dylib in Frameworks */,
 				FA5D248E1A96CAA700C6FC8F /* CoreGraphics.framework in Frameworks */,
 				FA5D248E1A96CAA700C6FC8F /* CoreGraphics.framework in Frameworks */,
 				FA5D248C1A96CA9E00C6FC8F /* QuartzCore.framework in Frameworks */,
 				FA5D248C1A96CA9E00C6FC8F /* QuartzCore.framework in Frameworks */,
@@ -243,6 +246,7 @@
 		FA5D24801A96C97900C6FC8F /* ios */ = {
 		FA5D24801A96C97900C6FC8F /* ios */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				FA0797981BF480A200034B7C /* GameController.framework */,
 				FA5D24C11A96D78000C6FC8F /* Foundation.framework */,
 				FA5D24C11A96D78000C6FC8F /* Foundation.framework */,
 				FA5D24891A96CA9600C6FC8F /* AudioToolbox.framework */,
 				FA5D24891A96CA9600C6FC8F /* AudioToolbox.framework */,
 				FA5D248D1A96CAA700C6FC8F /* CoreGraphics.framework */,
 				FA5D248D1A96CAA700C6FC8F /* CoreGraphics.framework */,

+ 27 - 14
src/modules/graphics/opengl/Text.cpp

@@ -33,7 +33,6 @@ namespace opengl
 Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
 Text::Text(Font *font, const std::vector<Font::ColoredString> &text)
 	: font(font)
 	: font(font)
 	, vbo(nullptr)
 	, vbo(nullptr)
-	, text_info()
 	, vert_offset(0)
 	, vert_offset(0)
 	, texture_cache_id((uint32) -1)
 	, texture_cache_id((uint32) -1)
 {
 {
@@ -82,7 +81,7 @@ void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t
 		vbo = new_vbo;
 		vbo = new_vbo;
 	}
 	}
 
 
-	if (vbo != nullptr)
+	if (vbo != nullptr && datasize > 0)
 	{
 	{
 		GLBuffer::Bind bind(*vbo);
 		GLBuffer::Bind bind(*vbo);
 		vbodata = (uint8 *) vbo->map();
 		vbodata = (uint8 *) vbo->map();
@@ -113,6 +112,8 @@ void Text::addTextData(const TextData &t)
 	std::vector<Font::GlyphVertex> vertices;
 	std::vector<Font::GlyphVertex> vertices;
 	std::vector<Font::DrawCommand> new_commands;
 	std::vector<Font::DrawCommand> new_commands;
 
 
+	Font::TextInfo text_info;
+
 	// We only have formatted text if the align mode is valid.
 	// We only have formatted text if the align mode is valid.
 	if (t.align == Font::ALIGN_MAX_ENUM)
 	if (t.align == Font::ALIGN_MAX_ENUM)
 		new_commands = font->generateVertices(t.codepoints, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
 		new_commands = font->generateVertices(t.codepoints, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
@@ -158,7 +159,9 @@ void Text::addTextData(const TextData &t)
 	}
 	}
 
 
 	vert_offset = voffset + vertices.size();
 	vert_offset = voffset + vertices.size();
+
 	text_data.push_back(t);
 	text_data.push_back(t);
+	text_data.back().text_info = text_info;
 
 
 	// Font::generateVertices can invalidate the font's texture cache.
 	// Font::generateVertices can invalidate the font's texture cache.
 	if (font->getTextureCacheID() != texture_cache_id)
 	if (font->getTextureCacheID() != texture_cache_id)
@@ -178,7 +181,7 @@ void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::A
 	Font::ColoredCodepoints codepoints;
 	Font::ColoredCodepoints codepoints;
 	Font::getCodepointsFromString(text, codepoints);
 	Font::getCodepointsFromString(text, codepoints);
 
 
-	addTextData({codepoints, wrap, align, false, false, Matrix3()});
+	addTextData({codepoints, wrap, align, {}, false, false, Matrix3()});
 }
 }
 
 
 void Text::set()
 void Text::set()
@@ -186,22 +189,21 @@ void Text::set()
 	clear();
 	clear();
 }
 }
 
 
-void Text::add(const std::vector<Font::ColoredString> &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
+int Text::add(const std::vector<Font::ColoredString> &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
 {
 {
 	return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, x, y, angle, sx, sy, ox, oy, kx, ky);
 	return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, x, y, angle, sx, sy, ox, oy, kx, ky);
 }
 }
 
 
-void Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
+int Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
 {
 {
-	if (text.empty() || (text.size() == 1 && text[0].str.empty()))
-		return;
-
 	Font::ColoredCodepoints codepoints;
 	Font::ColoredCodepoints codepoints;
 	Font::getCodepointsFromString(text, codepoints);
 	Font::getCodepointsFromString(text, codepoints);
 
 
 	Matrix3 m(x, y, angle, sx, sy, ox, oy, kx, ky);
 	Matrix3 m(x, y, angle, sx, sy, ox, oy, kx, ky);
 
 
-	addTextData({codepoints, wrap, align, true, true, m});
+	addTextData({codepoints, wrap, align, {}, true, true, m});
+
+	return (int) text_data.size() - 1;
 }
 }
 
 
 void Text::clear()
 void Text::clear()
@@ -209,7 +211,6 @@ void Text::clear()
 	text_data.clear();
 	text_data.clear();
 	draw_commands.clear();
 	draw_commands.clear();
 	texture_cache_id = font->getTextureCacheID();
 	texture_cache_id = font->getTextureCacheID();
-	text_info = {};
 	vert_offset = 0;
 	vert_offset = 0;
 }
 }
 
 
@@ -262,14 +263,26 @@ Font *Text::getFont() const
 	return font.get();
 	return font.get();
 }
 }
 
 
-int Text::getWidth() const
+int Text::getWidth(int index) const
 {
 {
-	return text_info.width;
+	if (index < 0)
+		index = std::max((int) text_data.size() - 1, 0);
+
+	if (index >= (int) text_data.size())
+		return 0;
+
+	return text_data[index].text_info.width;
 }
 }
 
 
-int Text::getHeight() const
+int Text::getHeight(int index) const
 {
 {
-	return text_info.height;
+	if (index < 0)
+		index = std::max((int) text_data.size() - 1, 0);
+
+	if (index >= (int) text_data.size())
+		return 0;
+
+	return text_data[index].text_info.height;
 }
 }
 
 
 } // opengl
 } // opengl

+ 5 - 5
src/modules/graphics/opengl/Text.h

@@ -45,8 +45,8 @@ public:
 	void set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align);
 	void set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align);
 	void set();
 	void set();
 
 
-	void add(const std::vector<Font::ColoredString> &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
-	void addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
+	int add(const std::vector<Font::ColoredString> &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
+	int addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky);
 	void clear();
 	void clear();
 
 
 	// Implements Drawable.
 	// Implements Drawable.
@@ -58,12 +58,12 @@ public:
 	/**
 	/**
 	 * Gets the width of the currently set text.
 	 * Gets the width of the currently set text.
 	 **/
 	 **/
-	int getWidth() const;
+	int getWidth(int index = 0) const;
 
 
 	/**
 	/**
 	 * Gets the height of the currently set text.
 	 * Gets the height of the currently set text.
 	 **/
 	 **/
-	int getHeight() const;
+	int getHeight(int index = 0) const;
 
 
 private:
 private:
 
 
@@ -72,6 +72,7 @@ private:
 		Font::ColoredCodepoints codepoints;
 		Font::ColoredCodepoints codepoints;
 		float wrap;
 		float wrap;
 		Font::AlignMode align;
 		Font::AlignMode align;
+		Font::TextInfo text_info;
 		bool use_matrix;
 		bool use_matrix;
 		bool append_vertices;
 		bool append_vertices;
 		Matrix3 matrix;
 		Matrix3 matrix;
@@ -87,7 +88,6 @@ private:
 	std::vector<Font::DrawCommand> draw_commands;
 	std::vector<Font::DrawCommand> draw_commands;
 
 
 	std::vector<TextData> text_data;
 	std::vector<TextData> text_data;
-	Font::TextInfo text_info;
 
 
 	size_t vert_offset;
 	size_t vert_offset;
 
 

+ 14 - 6
src/modules/graphics/opengl/wrap_Text.cpp

@@ -144,8 +144,11 @@ int w_Text_add(lua_State *L)
 	float kx = (float) luaL_optnumber(L, 10, 0.0);
 	float kx = (float) luaL_optnumber(L, 10, 0.0);
 	float ky = (float) luaL_optnumber(L, 11, 0.0);
 	float ky = (float) luaL_optnumber(L, 11, 0.0);
 
 
-	luax_catchexcept(L, [&](){ t->add(text, x, y, a, sx, sy, ox, oy, kx, ky); });
-	return 0;
+	int index = 0;
+	luax_catchexcept(L, [&](){ index = t->add(text, x, y, a, sx, sy, ox, oy, kx, ky); });
+	lua_pushnumber(L, index + 1);
+
+	return 1;
 }
 }
 
 
 int w_Text_addf(lua_State *L)
 int w_Text_addf(lua_State *L)
@@ -173,8 +176,11 @@ int w_Text_addf(lua_State *L)
 	float kx = (float) luaL_optnumber(L, 12, 0.0);
 	float kx = (float) luaL_optnumber(L, 12, 0.0);
 	float ky = (float) luaL_optnumber(L, 13, 0.0);
 	float ky = (float) luaL_optnumber(L, 13, 0.0);
 
 
-	luax_catchexcept(L, [&](){ t->addf(text, wrap, align, x, y, a, sx, sy, ox, oy, kx, ky); });
-	return 0;
+	int index = 0;
+	luax_catchexcept(L, [&](){ index = t->addf(text, wrap, align, x, y, a, sx, sy, ox, oy, kx, ky); });
+	lua_pushnumber(L, index + 1);
+
+	return 1;
 }
 }
 
 
 int w_Text_clear(lua_State *L)
 int w_Text_clear(lua_State *L)
@@ -203,14 +209,16 @@ int w_Text_getFont(lua_State *L)
 int w_Text_getWidth(lua_State *L)
 int w_Text_getWidth(lua_State *L)
 {
 {
 	Text *t = luax_checktext(L, 1);
 	Text *t = luax_checktext(L, 1);
-	lua_pushnumber(L, t->getWidth());
+	int index = (int) luaL_optnumber(L, 2, 0) - 1;
+	lua_pushnumber(L, t->getWidth(index));
 	return 1;
 	return 1;
 }
 }
 
 
 int w_Text_getHeight(lua_State *L)
 int w_Text_getHeight(lua_State *L)
 {
 {
 	Text *t = luax_checktext(L, 1);
 	Text *t = luax_checktext(L, 1);
-	lua_pushnumber(L, t->getHeight());
+	int index = (int) luaL_optnumber(L, 2, 0) - 1;
+	lua_pushnumber(L, t->getHeight(index));
 	return 1;
 	return 1;
 }
 }
 
 

+ 8 - 6
src/scripts/nogame.lua

@@ -761,11 +761,13 @@ function love.nogame()
 			return COLORS[love.math.random(1, #COLORS)]
 			return COLORS[love.math.random(1, #COLORS)]
 		end
 		end
 
 
-		-- When using the higher-resolution mosaic sprite sheet we want to draw
-		-- its sprites at the same scale as the regular-resolution one.
-		-- We can avoid a lot of scaling by taking advantage of the fact that
-		-- Quads use normalized texture coordinates internally - if we use the
-		-- 'source image size' and quad size of the @1x image for the Quads
+		-- When using the higher-res mosaic sprite sheet, we want to draw its
+		-- sprites at the same scale as the regular-resolution one, because
+		-- we'll globally love.graphics.scale *everything* by the screen's
+		-- pixel density ratio.
+		-- We can avoid a lot of Quad scaling by taking advantage of the fact
+		-- that Quads use normalized texture coordinates internally - if we use 
+		-- the 'source image size' and quad size of the @1x image for the Quads
 		-- even when rendering them using the @2x image, it will automatically
 		-- even when rendering them using the @2x image, it will automatically
 		-- scale as expected.
 		-- scale as expected.
 		local QUADS = {
 		local QUADS = {
@@ -889,7 +891,7 @@ function love.nogame()
 		love.graphics.setBackgroundColor(136, 193, 206)
 		love.graphics.setBackgroundColor(136, 193, 206)
 
 
 		local function load_image(file, name)
 		local function load_image(file, name)
-			return love.graphics.newImage(love.image.newImageData(love.filesystem.newFileData(file, name:gsub("_", "."), "base64")))
+			return love.graphics.newImage(love.filesystem.newFileData(file, name:gsub("_", "."), "base64"))
 		end
 		end
 
 
 		g_images = {}
 		g_images = {}

+ 30 - 24
src/scripts/nogame.lua.h

@@ -3187,26 +3187,33 @@ const unsigned char nogame_lua[] =
 	0x20, 0x23, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x53, 0x29, 0x5d, 0x0a,
 	0x20, 0x23, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x53, 0x29, 0x5d, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 
-	0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 
-	0x6e, 0x20, 0x6d, 0x6f, 0x73, 0x61, 0x69, 0x63, 0x20, 0x73, 0x70, 0x72, 0x69, 0x74, 0x65, 0x20, 0x73, 0x68, 
-	0x65, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x61, 
-	0x77, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x69, 0x74, 0x73, 0x20, 0x73, 0x70, 0x72, 0x69, 0x74, 0x65, 0x73, 0x20, 0x61, 
-	0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x61, 
-	0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x6f, 
-	0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x2e, 0x0a,
+	0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x65, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x20, 0x6d, 0x6f, 0x73, 0x61, 0x69, 
+	0x63, 0x20, 0x73, 0x70, 0x72, 0x69, 0x74, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2c, 0x20, 0x77, 0x65, 
+	0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x61, 0x77, 0x20, 0x69, 0x74, 0x73, 0x0a,
+	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x73, 0x70, 0x72, 0x69, 0x74, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 
+	0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 
+	0x65, 0x20, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x2d, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 
+	0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x0a,
+	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x77, 0x65, 0x27, 0x6c, 0x6c, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x6c, 
+	0x79, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x63, 
+	0x61, 0x6c, 0x65, 0x20, 0x2a, 0x65, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2a, 0x20, 0x62, 
+	0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x27, 0x73, 0x0a,
+	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x64, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 
+	0x20, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x2e, 0x0a,
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x57, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x20, 
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x57, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x76, 0x6f, 0x69, 0x64, 0x20, 
-	0x61, 0x20, 0x6c, 0x6f, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x62, 
-	0x79, 0x20, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x74, 0x61, 0x67, 0x65, 
-	0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x51, 0x75, 0x61, 0x64, 0x73, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x72, 
-	0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x63, 0x6f, 
-	0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 
-	0x6c, 0x79, 0x20, 0x2d, 0x20, 0x69, 0x66, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x0a,
-	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x27, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 
-	0x20, 0x73, 0x69, 0x7a, 0x65, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x71, 0x75, 0x61, 0x64, 0x20, 0x73, 0x69, 
-	0x7a, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x40, 0x31, 0x78, 0x20, 0x69, 0x6d, 0x61, 0x67, 
-	0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x51, 0x75, 0x61, 0x64, 0x73, 0x0a,
+	0x61, 0x20, 0x6c, 0x6f, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x51, 0x75, 0x61, 0x64, 0x20, 0x73, 0x63, 0x61, 0x6c, 
+	0x69, 0x6e, 0x67, 0x20, 0x62, 0x79, 0x20, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x64, 0x76, 0x61, 
+	0x6e, 0x74, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x74, 0x0a,
+	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x51, 0x75, 0x61, 0x64, 0x73, 0x20, 0x75, 0x73, 
+	0x65, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 
+	0x72, 0x65, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 
+	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x2d, 0x20, 0x69, 0x66, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 
+	0x65, 0x20, 0x0a,
+	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x69, 
+	0x6d, 0x61, 0x67, 0x65, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x71, 0x75, 0x61, 
+	0x64, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x40, 0x31, 0x78, 0x20, 
+	0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x51, 0x75, 0x61, 0x64, 
+	0x73, 0x0a,
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x6e, 
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x6e, 
 	0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 
 	0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 
 	0x74, 0x68, 0x65, 0x20, 0x40, 0x32, 0x78, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 
 	0x74, 0x68, 0x65, 0x20, 0x40, 0x32, 0x78, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 
@@ -3463,11 +3470,10 @@ const unsigned char nogame_lua[] =
 	0x6d, 0x65, 0x29, 0x0a,
 	0x6d, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
 	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
 	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x28, 0x6c, 0x6f, 0x76, 
 	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x28, 0x6c, 0x6f, 0x76, 
-	0x65, 0x2e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2e, 0x6e, 0x65, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x61, 
-	0x74, 0x61, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 
-	0x2e, 0x6e, 0x65, 0x77, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x2c, 
-	0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5f, 0x22, 0x2c, 0x20, 0x22, 0x2e, 
-	0x22, 0x29, 0x2c, 0x20, 0x22, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x22, 0x29, 0x29, 0x29, 0x0a,
+	0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x6e, 0x65, 0x77, 0x46, 0x69, 
+	0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 
+	0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5f, 0x22, 0x2c, 0x20, 0x22, 0x2e, 0x22, 0x29, 0x2c, 0x20, 0x22, 0x62, 
+	0x61, 0x73, 0x65, 0x36, 0x34, 0x22, 0x29, 0x29, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
 	0x09, 0x09, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
 	0x09, 0x09, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a,
 	0x09, 0x09, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x74, 0x6f, 0x61, 0x73, 0x74, 0x20, 0x3d, 
 	0x09, 0x09, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x74, 0x6f, 0x61, 0x73, 0x74, 0x20, 0x3d,