diff --git a/src/common/runtime.h b/src/common/runtime.h index 43807f5c6..eb3b2875e 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -474,6 +474,28 @@ extern "C" { // Also called from luasocket int luax_enumerror(lua_State *L, const char *enumName, const char *value); int luax_enumerror(lua_State *L, const char *enumName, const std::vector &values, const char *value); +template +void luax_checktablefields(lua_State *L, int idx, const char *enumName, bool (*getConstant)(const char *, T &)) +{ + luaL_checktype(L, idx, LUA_TTABLE); + + // We want to error for invalid / misspelled fields in the table. + lua_pushnil(L); + while (lua_next(L, idx)) + { + if (lua_type(L, -2) != LUA_TSTRING) + luax_typerror(L, -2, "string"); + + const char *key = luaL_checkstring(L, -2); + T constantvalue; + + if (!getConstant(key, constantvalue)) + luax_enumerror(L, enumName, key); + + lua_pop(L, 1); + } +} + /** * Calls luax_objlen/lua_rawlen depending on version **/ diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp index 5dfc98a09..15516ca5b 100644 --- a/src/modules/graphics/Canvas.cpp +++ b/src/modules/graphics/Canvas.cpp @@ -195,6 +195,28 @@ std::vector Canvas::getConstants(MipmapMode) return mipmapModes.getNames(); } +bool Canvas::getConstant(const char *in, SettingType &out) +{ + return settingTypes.find(in, out); +} + +bool Canvas::getConstant(SettingType in, const char *&out) +{ + return settingTypes.find(in, out); +} + +const char *Canvas::getConstant(SettingType in) +{ + const char *name = nullptr; + getConstant(in, name); + return name; +} + +std::vector Canvas::getConstants(SettingType) +{ + return settingTypes.getNames(); +} + StringMap::Entry Canvas::mipmapEntries[] = { { "none", MIPMAPS_NONE }, @@ -204,6 +226,20 @@ StringMap::Entry Canvas::mipmapEnt StringMap Canvas::mipmapModes(Canvas::mipmapEntries, sizeof(Canvas::mipmapEntries)); +StringMap::Entry Canvas::settingTypeEntries[] = +{ + // Width / height / layers are currently omittted because they're separate + // arguments to newCanvas in the wrapper code. + { "mipmaps", SETTING_MIPMAPS }, + { "format", SETTING_FORMAT }, + { "type", SETTING_TYPE }, + { "dpiscale", SETTING_DPI_SCALE }, + { "msaa", SETTING_MSAA }, + { "readable", SETTING_READABLE }, +}; + +StringMap Canvas::settingTypes(Canvas::settingTypeEntries, sizeof(Canvas::settingTypeEntries)); + } // graphics } // love diff --git a/src/modules/graphics/Canvas.h b/src/modules/graphics/Canvas.h index 5413e92dc..566b9d399 100644 --- a/src/modules/graphics/Canvas.h +++ b/src/modules/graphics/Canvas.h @@ -47,6 +47,20 @@ public: MIPMAPS_MAX_ENUM }; + enum SettingType + { + SETTING_WIDTH, + SETTING_HEIGHT, + SETTING_LAYERS, + SETTING_MIPMAPS, + SETTING_FORMAT, + SETTING_TYPE, + SETTING_DPI_SCALE, + SETTING_MSAA, + SETTING_READABLE, + SETTING_MAX_ENUM + }; + struct Settings { int width = 1; @@ -81,6 +95,11 @@ public: static bool getConstant(MipmapMode in, const char *&out); static std::vector getConstants(MipmapMode); + static bool getConstant(const char *in, SettingType &out); + static bool getConstant(SettingType in, const char *&out); + static const char *getConstant(SettingType in); + static std::vector getConstants(SettingType); + protected: Settings settings; @@ -89,6 +108,9 @@ private: static StringMap::Entry mipmapEntries[]; static StringMap mipmapModes; + + static StringMap::Entry settingTypeEntries[]; + static StringMap settingTypes; }; // Canvas diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 5109216fc..9cfff406d 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -129,6 +129,9 @@ Graphics::Graphics() pixelScaleStack.reserve(16); pixelScaleStack.push_back(1); + states.reserve(10); + states.push_back(DisplayState()); + if (!Shader::initialize()) throw love::Exception("Shader support failed to initialize!"); } diff --git a/src/modules/graphics/Image.cpp b/src/modules/graphics/Image.cpp index 22f535a45..13f11a4f6 100644 --- a/src/modules/graphics/Image.cpp +++ b/src/modules/graphics/Image.cpp @@ -340,5 +340,36 @@ Image::MipmapsType Image::Slices::validate() const return MIPMAPS_NONE; } +bool Image::getConstant(const char *in, SettingType &out) +{ + return settingTypes.find(in, out); +} + +bool Image::getConstant(SettingType in, const char *&out) +{ + return settingTypes.find(in, out); +} + +const char *Image::getConstant(SettingType in) +{ + const char *name = nullptr; + getConstant(in, name); + return name; +} + +std::vector Image::getConstants(SettingType) +{ + return settingTypes.getNames(); +} + +StringMap::Entry Image::settingTypeEntries[] = +{ + { "mipmaps", SETTING_MIPMAPS }, + { "linear", SETTING_LINEAR }, + { "dpiscale", SETTING_DPI_SCALE }, +}; + +StringMap Image::settingTypes(Image::settingTypeEntries, sizeof(Image::settingTypeEntries)); + } // graphics } // love diff --git a/src/modules/graphics/Image.h b/src/modules/graphics/Image.h index 7718cde56..e5c0d1e48 100644 --- a/src/modules/graphics/Image.h +++ b/src/modules/graphics/Image.h @@ -46,6 +46,14 @@ public: MIPMAPS_GENERATED, }; + enum SettingType + { + SETTING_MIPMAPS, + SETTING_LINEAR, + SETTING_DPI_SCALE, + SETTING_MAX_ENUM + }; + struct Settings { bool mipmaps = false; @@ -94,6 +102,11 @@ public: static int imageCount; + static bool getConstant(const char *in, SettingType &out); + static bool getConstant(SettingType in, const char *&out); + static const char *getConstant(SettingType in); + static std::vector getConstants(SettingType); + protected: Image(const Slices &data, const Settings &settings); @@ -122,6 +135,9 @@ private: void init(PixelFormat fmt, int w, int h, const Settings &settings); + static StringMap::Entry settingTypeEntries[]; + static StringMap settingTypes; + }; // Image } // graphics diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index ed3e556f7..e19153041 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -60,9 +60,6 @@ Graphics::Graphics() { gl = OpenGL(); - states.reserve(10); - states.push_back(DisplayState()); - auto window = getInstance(M_WINDOW); if (window != nullptr) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 8bdf451b6..06f4f10e7 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -701,10 +701,11 @@ static Image::Settings w__optImageSettings(lua_State *L, int idx, const Image::S if (!lua_isnoneornil(L, idx)) { - luaL_checktype(L, idx, LUA_TTABLE); - settings.mipmaps = luax_boolflag(L, idx, "mipmaps", s.mipmaps); - settings.linear = luax_boolflag(L, idx, "linear", s.linear); - settings.dpiScale = (float) luax_numberflag(L, idx, "dpiscale", s.dpiScale); + luax_checktablefields(L, idx, "image setting name", Image::getConstant); + + settings.mipmaps = luax_boolflag(L, idx, Image::getConstant(Image::SETTING_MIPMAPS), s.mipmaps); + settings.linear = luax_boolflag(L, idx, Image::getConstant(Image::SETTING_LINEAR), s.linear); + settings.dpiScale = (float) luax_numberflag(L, idx, Image::getConstant(Image::SETTING_DPI_SCALE), s.dpiScale); } return settings; @@ -1186,12 +1187,12 @@ int w_newCanvas(lua_State *L) if (!lua_isnoneornil(L, startidx)) { - luaL_checktype(L, startidx, LUA_TTABLE); + luax_checktablefields(L, startidx, "canvas setting name", Canvas::getConstant); - settings.dpiScale = (float) luax_numberflag(L, startidx, "dpiscale", settings.dpiScale); - settings.msaa = luax_intflag(L, startidx, "msaa", settings.msaa); + settings.dpiScale = (float) luax_numberflag(L, startidx, Canvas::getConstant(Canvas::SETTING_DPI_SCALE), settings.dpiScale); + settings.msaa = luax_intflag(L, startidx, Canvas::getConstant(Canvas::SETTING_MSAA), settings.msaa); - lua_getfield(L, startidx, "format"); + lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_FORMAT)); if (!lua_isnoneornil(L, -1)) { const char *str = luaL_checkstring(L, -1); @@ -1200,7 +1201,7 @@ int w_newCanvas(lua_State *L) } lua_pop(L, 1); - lua_getfield(L, startidx, "type"); + lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_TYPE)); if (!lua_isnoneornil(L, -1)) { const char *str = luaL_checkstring(L, -1); @@ -1209,7 +1210,7 @@ int w_newCanvas(lua_State *L) } lua_pop(L, 1); - lua_getfield(L, startidx, "readable"); + lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_READABLE)); if (!lua_isnoneornil(L, -1)) { settings.readable.hasValue = true; @@ -1217,7 +1218,7 @@ int w_newCanvas(lua_State *L) } lua_pop(L, 1); - lua_getfield(L, startidx, "mipmaps"); + lua_getfield(L, startidx, Canvas::getConstant(Canvas::SETTING_MIPMAPS)); if (!lua_isnoneornil(L, -1)) { const char *str = luaL_checkstring(L, -1); diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index 438089a66..a5171f43d 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -54,23 +54,7 @@ static const char *settingName(Window::Setting setting) static int readWindowSettings(lua_State *L, int idx, WindowSettings &settings) { - luaL_checktype(L, idx, LUA_TTABLE); - - // We want to error for invalid / misspelled window attributes. - lua_pushnil(L); - while (lua_next(L, idx)) - { - if (lua_type(L, -2) != LUA_TSTRING) - return luax_typerror(L, -2, "string"); - - const char *key = luaL_checkstring(L, -2); - Window::Setting setting; - - if (!Window::getConstant(key, setting)) - return luax_enumerror(L, "window setting", key); - - lua_pop(L, 1); - } + luax_checktablefields(L, idx, "window setting", Window::getConstant); lua_getfield(L, idx, settingName(Window::SETTING_FULLSCREEN_TYPE)); if (!lua_isnoneornil(L, -1))