diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index e8ca5bd58..06582226d 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -124,7 +124,7 @@ bool Graphics::setMode(int width, int height, bool fullscreen, bool vsync, int f height = currentWindow->getHeight(); // Okay, setup OpenGL. - + initializeContext(); // Enable blending diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 79efafe1f..d861f8135 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -38,44 +38,44 @@ void initializeContext() { if (contextInitialized) return; - + contextInitialized = true; - + textureUnits.clear(); - + // initialize multiple texture unit support, if available if (GLEE_ARB_multitexture || GLEE_VERSION_1_3) { GLint maxtextureunits; glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxtextureunits); - + // shaders/GL2.0 added "Texture Image Units." Total max texture units is the greater of the two if (GLEE_VERSION_2_0 || GLEE_ARB_vertex_shader) { GLint maxtextureimageunits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureimageunits); - + if (maxtextureimageunits > maxtextureunits) maxtextureunits = maxtextureimageunits; } - + textureUnits.resize(maxtextureunits, 0); - + GLenum activetextureunit; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *)&activetextureunit); - + curTextureUnitIndex = activetextureunit - GL_TEXTURE0; - + for (size_t i = 0; i < textureUnits.size(); ++i) { if (GLEE_VERSION_1_3) glActiveTexture(GL_TEXTURE0 + i); else glActiveTextureARB(GL_TEXTURE0 + i); - + glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &textureUnits[i]); } - + if (GLEE_VERSION_1_3) glActiveTexture(activetextureunit); else @@ -86,7 +86,7 @@ void initializeContext() // multitexturing not supported, so we only have 1 texture unit textureUnits.resize(1, 0); curTextureUnitIndex = 0; - + glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &textureUnits[0]); } } @@ -99,12 +99,12 @@ void uninitializeContext() void setActiveTextureUnit(GLenum textureunit) { initializeContext(); - + int textureunitindex = textureunit - GL_TEXTURE0; - + if (textureunitindex < 0 || (size_t) textureunitindex >= textureUnits.size()) throw love::Exception("Invalid texture unit index."); - + if (textureunitindex != curTextureUnitIndex) { if (GLEE_VERSION_1_3) @@ -114,14 +114,14 @@ void setActiveTextureUnit(GLenum textureunit) else throw love::Exception("Multitexturing not supported."); } - + curTextureUnitIndex = textureunitindex; } void bindTexture(GLuint texture) { initializeContext(); - + if (texture != textureUnits[curTextureUnitIndex]) { textureUnits[curTextureUnitIndex] = texture; @@ -132,20 +132,20 @@ void bindTexture(GLuint texture) void bindTextureToUnit(GLuint texture, GLenum textureunit, bool restoreprev) { initializeContext(); - + int textureunitindex = textureunit - GL_TEXTURE0; - + if (textureunitindex < 0 || (size_t) textureunitindex >= textureUnits.size()) throw love::Exception("Invalid texture unit index."); - + if (texture != textureUnits[textureunitindex]) { int oldtexunitindex = curTextureUnitIndex; setActiveTextureUnit(textureunit); - + textureUnits[textureunitindex] = texture; glBindTexture(GL_TEXTURE_2D, texture); - + if (restoreprev) setActiveTextureUnit(GL_TEXTURE0 + oldtexunitindex); } @@ -154,7 +154,7 @@ void bindTextureToUnit(GLuint texture, GLenum textureunit, bool restoreprev) void deleteTexture(GLuint texture) { initializeContext(); - + std::vector::iterator it; for (it = textureUnits.begin(); it != textureUnits.end(); ++it) { diff --git a/src/modules/graphics/opengl/ShaderEffect.cpp b/src/modules/graphics/opengl/ShaderEffect.cpp index a026ba8c2..216ff5bc6 100644 --- a/src/modules/graphics/opengl/ShaderEffect.cpp +++ b/src/modules/graphics/opengl/ShaderEffect.cpp @@ -40,7 +40,7 @@ namespace { cureffect->attach(true); } - + ~TemporaryAttacher() { if (preveffect != NULL) @@ -48,7 +48,7 @@ namespace else ShaderEffect::detach(); } - + ShaderEffect *cureffect; ShaderEffect *preveffect; }; @@ -66,15 +66,15 @@ ShaderEffect::ShaderEffect(const std::vector &shadersources) { if (shadersources.size() == 0) throw love::Exception("Cannot create shader effect: no source code!"); - + GLint maxtextureunits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits); _max_texture_units = std::max(maxtextureunits - 1, 0); - + // initialize global texture id counters if needed if (_texture_id_counters.size() < (size_t) _max_texture_units) _texture_id_counters.resize(_max_texture_units, 0); - + // load shader source and create program object loadVolatile(); } @@ -83,7 +83,7 @@ ShaderEffect::~ShaderEffect() { if (current == this) detach(); - + unloadVolatile(); } @@ -91,7 +91,7 @@ GLuint ShaderEffect::createShader(const ShaderSource &source) { GLenum shadertype; const char *shadertypename = NULL; - + switch (source.type) { case TYPE_VERTEX: @@ -118,47 +118,47 @@ GLuint ShaderEffect::createShader(const ShaderSource &source) throw love::Exception("Cannot create shader object: unknown shader type."); break; } - + // clear existing errors while (glGetError() != GL_NO_ERROR); - + GLuint shaderid = glCreateShader(shadertype); - + if (shaderid == 0) // oh no! { GLenum err = glGetError(); - + if (err == GL_INVALID_ENUM) // invalid or unsupported shader type throw love::Exception("Cannot create %s shader object: %s shaders not supported.", shadertypename, shadertypename); else // other errors should only happen between glBegin() and glEnd() throw love::Exception("Cannot create %s shader object.", shadertypename); } - + const char *src = source.code.c_str(); size_t srclen = source.code.length(); glShaderSource(shaderid, 1, (const GLchar **)&src, (GLint *)&srclen); - + glCompileShader(shaderid); - + GLint compile_status; glGetShaderiv(shaderid, GL_COMPILE_STATUS, &compile_status); - + if (compile_status == GL_FALSE) { GLint infologlen; glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &infologlen); - + GLchar *errorlog = new GLchar[infologlen + 1]; glGetShaderInfoLog(shaderid, infologlen, NULL, errorlog); - + std::string tmp(errorlog); - + delete[] errorlog; glDeleteShader(shaderid); - + throw love::Exception("Cannot compile %s shader:\n%s", shadertypename, tmp.c_str()); } - + return shaderid; } @@ -167,24 +167,24 @@ void ShaderEffect::createProgram(const std::vector &shaderids) _program = glCreateProgram(); if (_program == 0) // should only fail when called between glBegin() and glEnd() throw love::Exception("Cannot create shader program object."); - + std::vector::const_iterator it; for (it = shaderids.begin(); it != shaderids.end(); ++it) glAttachShader(_program, *it); - + glLinkProgram(_program); - + for (it = shaderids.begin(); it != shaderids.end(); ++it) glDeleteShader(*it); // flag shaders for auto-deletion when program object is deleted - + GLint link_ok; glGetProgramiv(_program, GL_LINK_STATUS, &link_ok); - + if (link_ok == GL_FALSE) { const std::string warnings = getWarnings(); glDeleteProgram(_program); - + throw love::Exception("Cannot link shader program object:\n%s", warnings.c_str()); } } @@ -194,18 +194,18 @@ bool ShaderEffect::loadVolatile() // zero out texture id list _texture_id_list.clear(); _texture_id_list.insert(_texture_id_list.begin(), _max_texture_units, 0); - + std::vector shaderids; - + std::vector::const_iterator source; for (source = _shadersources.begin(); source != _shadersources.end(); ++source) shaderids.push_back(createShader(*source)); - + if (shaderids.size() == 0) throw love::Exception("Cannot create shader effect: no valid source code!"); - + createProgram(shaderids); - + if (current == this) { current = NULL; // make sure glUseProgram gets called @@ -219,25 +219,25 @@ void ShaderEffect::unloadVolatile() { if (current == this) glUseProgram(0); - + if (_program != 0) glDeleteProgram(_program); - + _program = 0; - + // decrement global texture id counters for texture units which had textures bound from this shader for (size_t i = 0; i < _texture_id_list.size(); ++i) { if (_texture_id_list[i] == 0) continue; - + _texture_id_counters[i] = std::max(_texture_id_counters[i] - 1, 0); } - + // texture list is probably invalid, clear it _texture_id_list.clear(); _texture_id_list.insert(_texture_id_list.begin(), _max_texture_units, 0); - + // same with uniform location list _uniforms.clear(); } @@ -283,9 +283,9 @@ void ShaderEffect::attach(bool temporary) { if (current != this) glUseProgram(_program); - + current = this; - + if (!temporary) { // make sure all sent textures are properly bound to their respective texture units @@ -294,7 +294,7 @@ void ShaderEffect::attach(bool temporary) { if (_texture_id_list[i] == 0) continue; - + bindTextureToUnit(_texture_id_list[i], GL_TEXTURE0 + i + 1, false); } setActiveTextureUnit(GL_TEXTURE0); @@ -305,7 +305,7 @@ void ShaderEffect::detach() { if (current != NULL) glUseProgram(0); - + current = NULL; } @@ -372,21 +372,21 @@ void ShaderEffect::sendTexture(const std::string &name, GLuint texture) TemporaryAttacher attacher(this); GLint location = getUniformLocation(name); GLint texture_unit = getTextureUnit(name); - + // bind texture to assigned texture unit and send uniform to bound shader program bindTextureToUnit(texture, GL_TEXTURE0 + texture_unit, false); glUniform1i(location, texture_unit); - + // reset texture unit setActiveTextureUnit(GL_TEXTURE0); - + // increment global shader texture id counter for this texture unit, if we haven't already if (_texture_id_list[texture_unit-1] == 0) ++_texture_id_counters[texture_unit-1]; - + // store texture id so it can be re-bound to the proper texture unit when necessary _texture_id_list[texture_unit-1] = texture; - + // throw error if needed checkSetUniformError(); } @@ -422,28 +422,28 @@ GLint ShaderEffect::getUniformLocation(const std::string &name) GLint ShaderEffect::getTextureUnit(const std::string &name) { std::map::const_iterator it = _texture_unit_pool.find(name); - + if (it != _texture_unit_pool.end()) return it->second; - + int nextunitindex = 1; - + // prefer texture units which are unused by all other shaders std::vector::iterator nextfreeunit = std::find(_texture_id_counters.begin(), _texture_id_counters.end(), 0); - + if (nextfreeunit != _texture_id_counters.end()) nextunitindex = std::distance(_texture_id_counters.begin(), nextfreeunit) + 1; // we don't want to use unit 0 else { // no completely unused texture units exist, try to use next free slot in our own list std::vector::iterator nexttexunit = std::find(_texture_id_list.begin(), _texture_id_list.end(), 0); - + if (nexttexunit == _texture_id_list.end()) throw love::Exception("No more texture units available for shader."); - + nextunitindex = std::distance(_texture_id_list.begin(), nexttexunit) + 1; // we don't want to use unit 0 } - + _texture_unit_pool[name] = nextunitindex; return nextunitindex; } diff --git a/src/modules/graphics/opengl/ShaderEffect.h b/src/modules/graphics/opengl/ShaderEffect.h index ad0ca47e5..4e4638a29 100644 --- a/src/modules/graphics/opengl/ShaderEffect.h +++ b/src/modules/graphics/opengl/ShaderEffect.h @@ -51,14 +51,14 @@ public: TYPE_FRAGMENT, TYPE_MAX_ENUM }; - + // thin wrapper for GLSL source code. struct ShaderSource { std::string code; ShaderType type; }; - + /** * Creates a new ShaderEffect using a list of source codes. * Must contain at least one vertex or fragment shader source. @@ -66,7 +66,7 @@ public: * @param shadersources Vector of shader source codes. **/ ShaderEffect(const std::vector &shadersources); - + virtual ~ShaderEffect(); // Implements Volatile @@ -79,23 +79,23 @@ public: * @param temporary True if we just want to send values to the shader with no intention of rendering. **/ void attach(bool temporary = false); - + /** * Detach the currently bound ShaderEffect. * Causes OpenGL to use fixed functionality in place of shader programs. **/ static void detach(); - + /** * Returns any warnings this ShaderEffect may have generated. **/ std::string getWarnings() const; - + /** * Returns the maximum GLSL version supported on this system. **/ static std::string getGLSLVersion(); - + /** * Returns whether ShaderEffects are supported on this system. **/ @@ -111,7 +111,7 @@ public: * @param count Number of float or vector values. **/ void sendFloat(const std::string &name, int size, const GLfloat *vec, int count); - + /** * Send at least one matrix to this ShaderEffect as a uniform. * @@ -121,7 +121,7 @@ public: * @param count Number of matrices to send. **/ void sendMatrix(const std::string &name, int size, const GLfloat *m, int count); - + /** * Send an image to this ShaderEffect as a uniform. * @@ -129,7 +129,7 @@ public: * @param image The image to send. **/ void sendImage(const std::string &name, const Image &image); - + /** * Send a canvas to this ShaderEffect as a uniform. * @@ -137,38 +137,37 @@ public: * @param canvas The canvas to send. **/ void sendCanvas(const std::string &name, const Canvas &canvas); - + // pointer to currently active ShaderEffect. static ShaderEffect *current; private: - + GLint getUniformLocation(const std::string &name); void checkSetUniformError(); GLuint createShader(const ShaderSource &source); void createProgram(const std::vector &shaderids); - + // list of all shader code attached to this ShaderEffect std::vector _shadersources; - + GLuint _program; // volatile // uniform location buffer map std::map _uniforms; - + // total max GPU texture units for shaders static GLint _max_texture_units; - + // counts total number of textures bound to each texture unit in all shaders static std::vector _texture_id_counters; - + // texture unit pool for setting images std::map _texture_unit_pool; std::vector _texture_id_list; GLint getTextureUnit(const std::string &name); - + void sendTexture(const std::string &name, GLuint texture); - }; } // opengl diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index fcd9af353..ce8369090 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -444,16 +444,16 @@ int w_newShaderEffect(lua_State *L) lua_settop(L, 2); luax_getfunction(L, "graphics", "_effectCodeToGLSL"); - + // push vertcode and fragcode strings to the top of the stack so they become arguments for the function lua_pushvalue(L, 1); lua_pushvalue(L, 2); - + // call effectCodeToGLSL, returned values will be at the top of the stack lua_pcall(L, 2, 2, 0); - + std::vector shaderlist; - + // vertex shader code if (lua_isstring(L, -2)) { @@ -462,7 +462,7 @@ int w_newShaderEffect(lua_State *L) vertshader.code = luaL_checkstring(L, -2); shaderlist.push_back(vertshader); } - + // fragment shader code if (lua_isstring(L, -1)) { @@ -471,7 +471,7 @@ int w_newShaderEffect(lua_State *L) fragshader.code = luaL_checkstring(L, -1); shaderlist.push_back(fragshader); } - + ShaderEffect *effect = instance->newShaderEffect(shaderlist); luax_newtype(L, "ShaderEffect", GRAPHICS_SHADEREFFECT_T, (void *)effect); } diff --git a/src/scripts/graphics.lua b/src/scripts/graphics.lua index 2ff3aa558..a2d3e999c 100644 --- a/src/scripts/graphics.lua +++ b/src/scripts/graphics.lua @@ -1282,9 +1282,10 @@ do love.graphics.printf = _printf love.graphics.printf(...) end - + + local GLSL_VERSION = "#version 120" - + local GLSL_VERT = { HEADER = [[ #define VERTEX @@ -1294,17 +1295,17 @@ do #define extern uniform #define Texel texture2D +#define VertexPosition gl_Vertex +#define VertexTexCoord gl_MultiTexCoord0 +#define VertexColor gl_Color + #define ModelViewMatrix gl_ModelViewMatrix #define ProjectionMatrix gl_ProjectionMatrix #define ModelViewProjectionMatrix gl_ModelViewProjectionMatrix #define NormalMatrix gl_NormalMatrix -#define VertexColor gl_Color -#define VertexTexCoord gl_MultiTexCoord0 -#define VertexPosition gl_Vertex - -#define VaryingColor gl_FrontColor #define VaryingTexCoord gl_TexCoord[0] +#define VaryingColor gl_FrontColor uniform sampler2D _tex0_; @@ -1316,7 +1317,7 @@ void main() { gl_Position = position(ModelViewProjectionMatrix, VertexPosition); }]], } - + local GLSL_FRAG = { HEADER = [[ #define PIXEL @@ -1331,8 +1332,8 @@ void main() { #define ModelViewProjectionMatrix gl_ModelViewProjectionMatrix #define NormalMatrix gl_NormalMatrix -#define VaryingColor gl_Color #define VaryingTexCoord gl_TexCoord[0] +#define VaryingColor gl_Color uniform sampler2D _tex0_; @@ -1373,7 +1374,7 @@ void main() { if fragcode then fragcode = table.concat({GLSL_VERSION, GLSL_FRAG.HEADER, fragcode, GLSL_FRAG.FOOTER}, "\n") end - + return vertcode, fragcode end @@ -1408,7 +1409,7 @@ void main() { -- {a, b, c, d, e, f, ...} local function flattenMatrices(mat, ...) if not mat then return end - + local tonumber = tonumber local ret,l = {}, 1 @@ -1465,14 +1466,14 @@ void main() { meta.send = shadereffect_dispatch_send return effect end - - + + -- compatibility functions - + function love.graphics.newPixelEffect(fragcode) return love.graphics.newShaderEffect(nil, fragcode) end - + love.graphics.setPixelEffect = love.graphics.setShaderEffect love.graphics.getPixelEffect = love.graphics.getShaderEffect end diff --git a/src/scripts/graphics.lua.h b/src/scripts/graphics.lua.h index 1f6f28baa..f30645193 100644 --- a/src/scripts/graphics.lua.h +++ b/src/scripts/graphics.lua.h @@ -6259,10 +6259,8 @@ const unsigned char graphics_lua[] = 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x20, 0x3d, 0x20, 0x22, 0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x32, 0x30, 0x22, 0x0a, - 0x09, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x56, 0x45, 0x52, 0x54, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, @@ -6275,6 +6273,13 @@ const unsigned char graphics_lua[] = 0x66, 0x6f, 0x72, 0x6d, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x54, 0x65, 0x78, 0x65, 0x6c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x0a, + 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x6c, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0a, + 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, + 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x65, 0x78, 0x43, 0x6f, + 0x6f, 0x72, 0x64, 0x30, 0x0a, + 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, + 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, @@ -6287,18 +6292,11 @@ const unsigned char graphics_lua[] = 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x67, 0x6c, 0x5f, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, - 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x54, 0x65, 0x78, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x30, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x6c, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x5b, 0x30, 0x5d, 0x0a, + 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x3b, 0x0a, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x30, 0x5d, 0x5d, 0x2c, 0x0a, @@ -6314,7 +6312,6 @@ const unsigned char graphics_lua[] = 0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0a, 0x7d, 0x5d, 0x5d, 0x2c, 0x0a, 0x09, 0x7d, 0x0a, - 0x09, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x47, 0x4c, 0x53, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x47, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x09, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a, @@ -6339,11 +6336,11 @@ const unsigned char graphics_lua[] = 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x67, 0x6c, 0x5f, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x0a, - 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x67, 0x6c, 0x5f, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x5b, 0x30, 0x5d, 0x0a, + 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, + 0x6f, 0x72, 0x20, 0x67, 0x6c, 0x5f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x5f, 0x74, 0x65, 0x78, 0x30, 0x5f, 0x3b, 0x0a, 0x23, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x30, 0x5d, 0x5d, 0x2c, 0x0a, @@ -6430,7 +6427,6 @@ const unsigned char graphics_lua[] = 0x53, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x47, 0x2e, 0x46, 0x4f, 0x4f, 0x54, 0x45, 0x52, 0x7d, 0x2c, 0x20, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x09, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x65, 0x72, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, @@ -6520,7 +6516,6 @@ const unsigned char graphics_lua[] = 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x09, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x0a, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x2c, 0x6c, 0x20, 0x3d, 0x20, 0x7b, 0x7d, @@ -6643,11 +6638,8 @@ const unsigned char graphics_lua[] = 0x73, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x0a, - 0x09, 0x0a, 0x09, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, - 0x09, 0x0a, 0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a, @@ -6655,7 +6647,6 @@ const unsigned char graphics_lua[] = 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x66, 0x72, 0x61, 0x67, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, - 0x09, 0x0a, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x64, 0x65,