diff --git a/CMakeLists.txt b/CMakeLists.txt index 34a183cdf..4a08aca41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,12 @@ set(LOVE_SRC_MODULE_FILESYSTEM_ROOT src/modules/filesystem/File.h src/modules/filesystem/FileData.cpp src/modules/filesystem/FileData.h + src/modules/filesystem/wrap_File.cpp + src/modules/filesystem/wrap_File.h + src/modules/filesystem/wrap_FileData.cpp + src/modules/filesystem/wrap_FileData.h + src/modules/filesystem/wrap_Filesystem.cpp + src/modules/filesystem/wrap_Filesystem.h ) set(LOVE_SRC_MODULE_FILESYSTEM_PHYSFS @@ -192,12 +198,6 @@ set(LOVE_SRC_MODULE_FILESYSTEM_PHYSFS src/modules/filesystem/physfs/File.h src/modules/filesystem/physfs/Filesystem.cpp src/modules/filesystem/physfs/Filesystem.h - src/modules/filesystem/physfs/wrap_File.cpp - src/modules/filesystem/physfs/wrap_File.h - src/modules/filesystem/physfs/wrap_FileData.cpp - src/modules/filesystem/physfs/wrap_FileData.h - src/modules/filesystem/physfs/wrap_Filesystem.cpp - src/modules/filesystem/physfs/wrap_Filesystem.h ) set(LOVE_SRC_MODULE_FILESYSTEM @@ -369,6 +369,10 @@ set(LOVE_SRC_MODULE_JOYSTICK_ROOT src/modules/joystick/Joystick.cpp src/modules/joystick/Joystick.h src/modules/joystick/JoystickModule.h + src/modules/joystick/wrap_Joystick.cpp + src/modules/joystick/wrap_Joystick.h + src/modules/joystick/wrap_JoystickModule.cpp + src/modules/joystick/wrap_JoystickModule.h ) set(LOVE_SRC_MODULE_JOYSTICK_SDL @@ -376,10 +380,6 @@ set(LOVE_SRC_MODULE_JOYSTICK_SDL src/modules/joystick/sdl/Joystick.h src/modules/joystick/sdl/JoystickModule.cpp src/modules/joystick/sdl/JoystickModule.h - src/modules/joystick/sdl/wrap_Joystick.cpp - src/modules/joystick/sdl/wrap_Joystick.h - src/modules/joystick/sdl/wrap_JoystickModule.cpp - src/modules/joystick/sdl/wrap_JoystickModule.h ) set(LOVE_SRC_MODULE_JOYSTICK diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj index 91a317797..6161972bc 100644 --- a/platform/macosx/love-framework.xcodeproj/project.pbxproj +++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj @@ -1462,6 +1462,10 @@ FAB0078E1740C12D00A9664D /* Joystick.h */, 4C606AEC342457600C3F0741 /* JoystickModule.h */, 687216AD6FA406C838284B91 /* sdl */, + FAB007951740C87D00A9664D /* wrap_Joystick.cpp */, + FAB007961740C87D00A9664D /* wrap_Joystick.h */, + 139411436818381E493F00F5 /* wrap_JoystickModule.cpp */, + 2D7B7DEC4FC87878332E41B3 /* wrap_JoystickModule.h */, ); path = joystick; sourceTree = ""; @@ -1580,12 +1584,6 @@ 47D46915001F342A3CD23E86 /* File.h */, 6DE3129F3A0B2D9C178118F3 /* Filesystem.cpp */, 219636CF6780074F7871463D /* Filesystem.h */, - 6C367AE309C453C412D91363 /* wrap_File.cpp */, - 52E15B702C40593D3BF431DF /* wrap_File.h */, - 597478A255B82B56488B4717 /* wrap_FileData.cpp */, - 3512460642B046876D687B22 /* wrap_FileData.h */, - 1E827AE8548C52493ED95629 /* wrap_Filesystem.cpp */, - 5DC271240F0119AE16FA1B8E /* wrap_Filesystem.h */, ); path = physfs; sourceTree = ""; @@ -1642,10 +1640,6 @@ FAB007921740C28900A9664D /* Joystick.h */, 55B425307C0C1C4B3EFC3A5F /* JoystickModule.cpp */, 439E46D768A266780E894800 /* JoystickModule.h */, - FAB007951740C87D00A9664D /* wrap_Joystick.cpp */, - FAB007961740C87D00A9664D /* wrap_Joystick.h */, - 139411436818381E493F00F5 /* wrap_JoystickModule.cpp */, - 2D7B7DEC4FC87878332E41B3 /* wrap_JoystickModule.h */, ); path = sdl; sourceTree = ""; @@ -1762,6 +1756,12 @@ 62370A494F9D6E2D570065EB /* FileData.cpp */, 54A13C2209F945671BC27974 /* FileData.h */, 64DD03B45BF6265723662DAF /* physfs */, + 6C367AE309C453C412D91363 /* wrap_File.cpp */, + 52E15B702C40593D3BF431DF /* wrap_File.h */, + 597478A255B82B56488B4717 /* wrap_FileData.cpp */, + 3512460642B046876D687B22 /* wrap_FileData.h */, + 1E827AE8548C52493ED95629 /* wrap_Filesystem.cpp */, + 5DC271240F0119AE16FA1B8E /* wrap_Filesystem.h */, ); path = filesystem; sourceTree = ""; diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index 720090176..eed6295c0 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -486,6 +486,10 @@ int luax_getfunction(lua_State *L, const char *mod, const char *fn) int luax_convobj(lua_State *L, int idx, const char *mod, const char *fn) { + // Convert to absolute index if necessary. + if (idx < 0 && idx > LUA_REGISTRYINDEX) + idx += lua_gettop(L) + 1; + // Convert string to a file. luax_getfunction(L, mod, fn); lua_pushvalue(L, idx); // The initial argument. diff --git a/src/common/runtime.h b/src/common/runtime.h index dae24f97c..c9c4ffafd 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -33,6 +33,9 @@ extern "C" { #include } +// C++ +#include + namespace love { @@ -471,22 +474,55 @@ T *luax_totype(lua_State *L, int idx, const char * /* name */, love::bits /* typ Type luax_type(lua_State *L, int idx); /** - * Macro for converting a LOVE exception into a Lua error. + * Converts any exceptions thrown by the passed lambda function into a Lua error. * lua_error (and luaL_error) cannot be called from inside the exception handler * because they use longjmp, which causes undefined behaviour when the * destructor of the exception would have been called. **/ -#define EXCEPT_GUARD(A) \ -{ \ - bool should_error = false; \ - try { A } \ - catch (love::Exception &e) \ - { \ - should_error = true; \ - lua_pushstring(L, e.what()); \ - } \ - if (should_error) \ - return luaL_error(L, "%s", lua_tostring(L, -1)); \ +template +int luax_catchexcept(lua_State *L, const T& func) +{ + bool should_error = false; + + try + { + func(); + } + catch (const std::exception &e) + { + should_error = true; + lua_pushstring(L, e.what()); + } + + if (should_error) + return luaL_error(L, "%s", lua_tostring(L, -1)); + + return 0; + +} + +template +int luax_catchexcept(lua_State *L, const T& func, const F& finallyfunc) +{ + bool should_error = false; + + try + { + func(); + } + catch (const std::exception &e) + { + should_error = true; + lua_pushstring(L, e.what()); + } + + finallyfunc(); + + if (should_error) + return luaL_error(L, "%s", lua_tostring(L, -1)); + + return 0; + } } // love diff --git a/src/modules/audio/openal/Source.cpp b/src/modules/audio/openal/Source.cpp index df81d4ec8..9d845a89e 100644 --- a/src/modules/audio/openal/Source.cpp +++ b/src/modules/audio/openal/Source.cpp @@ -692,6 +692,7 @@ int Source::streamAtomic(ALuint buffer, love::sound::Decoder *d) { // Get more sound data. int decoded = d->decode(); + decoded = decoded >= 0 ? decoded : 0; int fmt = getFormat(d->getChannels(), d->getBitDepth()); diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 217c4f98e..3b3c48568 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/src/modules/audio/wrap_Audio.cpp @@ -41,10 +41,7 @@ int w_getSourceCount(lua_State *L) int w_newSource(lua_State *L) { - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) luax_convobj(L, 1, "sound", "newDecoder"); Source::Type stype = Source::TYPE_STREAM; diff --git a/src/modules/audio/wrap_Source.cpp b/src/modules/audio/wrap_Source.cpp index c0b70df3d..ba1bc55bd 100644 --- a/src/modules/audio/wrap_Source.cpp +++ b/src/modules/audio/wrap_Source.cpp @@ -36,7 +36,7 @@ int w_Source_clone(lua_State *L) { Source *t = luax_checksource(L, 1); Source *clone = nullptr; - EXCEPT_GUARD(clone = t->clone();) + luax_catchexcept(L, [&](){ clone = t->clone(); }); luax_pushtype(L, "Source", AUDIO_SOURCE_T, clone); return 1; } @@ -146,7 +146,7 @@ int w_Source_setPosition(lua_State *L) v[0] = (float)luaL_checknumber(L, 2); v[1] = (float)luaL_checknumber(L, 3); v[2] = (float)luaL_optnumber(L, 4, 0); - EXCEPT_GUARD(t->setPosition(v);) + luax_catchexcept(L, [&](){ t->setPosition(v); }); return 0; } @@ -154,7 +154,7 @@ int w_Source_getPosition(lua_State *L) { Source *t = luax_checksource(L, 1); float v[3]; - EXCEPT_GUARD(t->getPosition(v);) + luax_catchexcept(L, [&](){ t->getPosition(v); }); lua_pushnumber(L, v[0]); lua_pushnumber(L, v[1]); lua_pushnumber(L, v[2]); @@ -168,7 +168,7 @@ int w_Source_setVelocity(lua_State *L) v[0] = (float)luaL_checknumber(L, 2); v[1] = (float)luaL_checknumber(L, 3); v[2] = (float)luaL_optnumber(L, 4, 0); - EXCEPT_GUARD(t->setVelocity(v);) + luax_catchexcept(L, [&](){ t->setVelocity(v); }); return 0; } @@ -176,7 +176,7 @@ int w_Source_getVelocity(lua_State *L) { Source *t = luax_checksource(L, 1); float v[3]; - EXCEPT_GUARD(t->getVelocity(v);) + luax_catchexcept(L, [&](){ t->getVelocity(v); }); lua_pushnumber(L, v[0]); lua_pushnumber(L, v[1]); lua_pushnumber(L, v[2]); @@ -190,7 +190,7 @@ int w_Source_setDirection(lua_State *L) v[0] = (float)luaL_checknumber(L, 2); v[1] = (float)luaL_checknumber(L, 3); v[2] = (float)luaL_optnumber(L, 4, 0); - EXCEPT_GUARD(t->setDirection(v);) + luax_catchexcept(L, [&](){ t->setDirection(v); }); return 0; } @@ -198,7 +198,7 @@ int w_Source_getDirection(lua_State *L) { Source *t = luax_checksource(L, 1); float v[3]; - EXCEPT_GUARD(t->getDirection(v);) + luax_catchexcept(L, [&](){ t->getDirection(v); }); lua_pushnumber(L, v[0]); lua_pushnumber(L, v[1]); lua_pushnumber(L, v[2]); @@ -211,7 +211,7 @@ int w_Source_setCone(lua_State *L) float innerAngle = (float) luaL_checknumber(L, 2); float outerAngle = (float) luaL_checknumber(L, 3); float outerVolume = (float) luaL_optnumber(L, 4, 0.0); - EXCEPT_GUARD(t->setCone(innerAngle, outerAngle, outerVolume);) + luax_catchexcept(L, [&](){ t->setCone(innerAngle, outerAngle, outerVolume); }); return 0; } @@ -219,7 +219,7 @@ int w_Source_getCone(lua_State *L) { Source *t = luax_checksource(L, 1); float innerAngle, outerAngle, outerVolume; - EXCEPT_GUARD(t->getCone(innerAngle, outerAngle, outerVolume);) + luax_catchexcept(L, [&](){ t->getCone(innerAngle, outerAngle, outerVolume); }); lua_pushnumber(L, innerAngle); lua_pushnumber(L, outerAngle); lua_pushnumber(L, outerVolume); @@ -229,14 +229,14 @@ int w_Source_getCone(lua_State *L) int w_Source_setRelative(lua_State *L) { Source *t = luax_checksource(L, 1); - EXCEPT_GUARD(t->setRelative(luax_toboolean(L, 2));) + luax_catchexcept(L, [&](){ t->setRelative(luax_toboolean(L, 2)); }); return 0; } int w_Source_isRelative(lua_State *L) { Source *t = luax_checksource(L, 1); - EXCEPT_GUARD(luax_pushboolean(L, t->isRelative());) + luax_catchexcept(L, [&](){ luax_pushboolean(L, t->isRelative()); }); return 1; } @@ -302,16 +302,20 @@ int w_Source_setAttenuationDistances(lua_State *L) float dmax = (float)luaL_checknumber(L, 3); if (dref < .0f || dmax < .0f) return luaL_error(L, "Invalid distances: %f, %f. Must be > 0", dref, dmax); - EXCEPT_GUARD(t->setReferenceDistance(dref);) - EXCEPT_GUARD(t->setMaxDistance(dmax);) + luax_catchexcept(L, [&]() { + t->setReferenceDistance(dref); + t->setMaxDistance(dmax); + }); return 0; } int w_Source_getAttenuationDistances(lua_State *L) { Source *t = luax_checksource(L, 1); - EXCEPT_GUARD(lua_pushnumber(L, t->getReferenceDistance());) - EXCEPT_GUARD(lua_pushnumber(L, t->getMaxDistance());) + luax_catchexcept(L, [&]() { + lua_pushnumber(L, t->getReferenceDistance()); + lua_pushnumber(L, t->getMaxDistance()); + }); return 2; } @@ -321,14 +325,14 @@ int w_Source_setRolloff(lua_State *L) float rolloff = (float)luaL_checknumber(L, 2); if (rolloff < .0f) return luaL_error(L, "Invalid rolloff: %f. Must be > 0.", rolloff); - EXCEPT_GUARD(t->setRolloffFactor(rolloff);) + luax_catchexcept(L, [&](){ t->setRolloffFactor(rolloff); }); return 0; } int w_Source_getRolloff(lua_State *L) { Source *t = luax_checksource(L, 1); - EXCEPT_GUARD(lua_pushnumber(L, t->getRolloffFactor());) + luax_catchexcept(L, [&](){ lua_pushnumber(L, t->getRolloffFactor()); }); return 1; } diff --git a/src/modules/event/sdl/wrap_Event.cpp b/src/modules/event/sdl/wrap_Event.cpp index f33bd6619..67481f3f2 100644 --- a/src/modules/event/sdl/wrap_Event.cpp +++ b/src/modules/event/sdl/wrap_Event.cpp @@ -123,7 +123,7 @@ extern "C" int luaopen_love_event(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new Event();) + luax_catchexcept(L, [&](){ instance = new Event(); }); } else instance->retain(); diff --git a/src/modules/filesystem/physfs/File.cpp b/src/modules/filesystem/physfs/File.cpp index ce2ac50eb..95eafa800 100644 --- a/src/modules/filesystem/physfs/File.cpp +++ b/src/modules/filesystem/physfs/File.cpp @@ -31,11 +31,12 @@ namespace love { namespace filesystem { -namespace physfs -{ extern bool hack_setupWriteDirectory(); +namespace physfs +{ + File::File(const std::string &filename) : filename(filename) , file(0) diff --git a/src/modules/filesystem/physfs/wrap_File.cpp b/src/modules/filesystem/wrap_File.cpp similarity index 97% rename from src/modules/filesystem/physfs/wrap_File.cpp rename to src/modules/filesystem/wrap_File.cpp index d136e4b4d..dda6da74a 100644 --- a/src/modules/filesystem/physfs/wrap_File.cpp +++ b/src/modules/filesystem/wrap_File.cpp @@ -20,6 +20,8 @@ #include "wrap_File.h" +#include "physfs/Filesystem.h" + #include "common/Data.h" #include "common/Exception.h" #include "common/int.h" @@ -28,8 +30,6 @@ namespace love { namespace filesystem { -namespace physfs -{ int luax_ioError(lua_State *L, const char *fmt, ...) { @@ -236,13 +236,13 @@ int w_File_lines(lua_State *L) file->close(); bool success = false; - EXCEPT_GUARD(success = file->open(File::READ);) + luax_catchexcept(L, [&](){ success = file->open(File::READ); }); if (!success) return luaL_error(L, "Could not open file."); } - lua_pushcclosure(L, Filesystem::lines_i, 3); + lua_pushcclosure(L, physfs::Filesystem::lines_i, 3); return 1; } @@ -323,6 +323,5 @@ extern "C" int luaopen_file(lua_State *L) return luax_register_type(L, "File", functions); } -} // physfs } // filesystem } // love diff --git a/src/modules/filesystem/physfs/wrap_File.h b/src/modules/filesystem/wrap_File.h similarity index 90% rename from src/modules/filesystem/physfs/wrap_File.h rename to src/modules/filesystem/wrap_File.h index a3d0b964d..d4bd65d74 100644 --- a/src/modules/filesystem/physfs/wrap_File.h +++ b/src/modules/filesystem/wrap_File.h @@ -18,20 +18,17 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#ifndef LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H -#define LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H +#ifndef LOVE_FILESYSTEM_WRAP_FILE_H +#define LOVE_FILESYSTEM_WRAP_FILE_H // LOVE #include "common/runtime.h" -#include "Filesystem.h" #include "File.h" namespace love { namespace filesystem { -namespace physfs -{ // Does not use lua_error, so it's safe to call in exception handling code. int luax_ioError(lua_State *L, const char *fmt, ...); @@ -53,8 +50,7 @@ int w_File_getBuffer(lua_State *L); int w_File_getMode(lua_State *L); extern "C" int luaopen_file(lua_State *L); -} // physfs } // filesystem } // love -#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_H +#endif // LOVE_FILESYSTEM_WRAP_FILE_H diff --git a/src/modules/filesystem/physfs/wrap_FileData.cpp b/src/modules/filesystem/wrap_FileData.cpp similarity index 98% rename from src/modules/filesystem/physfs/wrap_FileData.cpp rename to src/modules/filesystem/wrap_FileData.cpp index b50c8123b..3b78c47a5 100644 --- a/src/modules/filesystem/physfs/wrap_FileData.cpp +++ b/src/modules/filesystem/wrap_FileData.cpp @@ -26,8 +26,6 @@ namespace love { namespace filesystem { -namespace physfs -{ FileData *luax_checkfiledata(lua_State *L, int idx) { @@ -66,6 +64,5 @@ extern "C" int luaopen_filedata(lua_State *L) return luax_register_type(L, "FileData", w_FileData_functions); } -} // physfs } // filesystem } // love diff --git a/src/modules/filesystem/physfs/wrap_FileData.h b/src/modules/filesystem/wrap_FileData.h similarity index 85% rename from src/modules/filesystem/physfs/wrap_FileData.h rename to src/modules/filesystem/wrap_FileData.h index 2d46165fb..326387024 100644 --- a/src/modules/filesystem/physfs/wrap_FileData.h +++ b/src/modules/filesystem/wrap_FileData.h @@ -18,28 +18,24 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#ifndef LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H -#define LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H +#ifndef LOVE_FILESYSTEM_WRAP_FILE_DATA_H +#define LOVE_FILESYSTEM_WRAP_FILE_DATA_H // LOVE #include "common/runtime.h" - -#include "filesystem/FileData.h" +#include "FileData.h" namespace love { namespace filesystem { -namespace physfs -{ FileData *luax_checkfiledata(lua_State *L, int idx); int w_FileData_getFilename(lua_State *L); int w_FileData_getExtension(lua_State *L); extern "C" int luaopen_filedata(lua_State *L); -} // physfs } // filesystem } // love -#endif // LOVE_FILESYSTEM_PHYSFS_WRAP_FILE_DATA_H +#endif // LOVE_FILESYSTEM_WRAP_FILE_DATA_H diff --git a/src/modules/filesystem/wrap_Filesystem.cpp b/src/modules/filesystem/wrap_Filesystem.cpp new file mode 100644 index 000000000..96a5114ac --- /dev/null +++ b/src/modules/filesystem/wrap_Filesystem.cpp @@ -0,0 +1,675 @@ +/** + * Copyright (c) 2006-2014 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_Filesystem.h" +#include "wrap_File.h" +#include "wrap_FileData.h" + +#include "physfs/Filesystem.h" + +// SDL +#include + +namespace love +{ +namespace filesystem +{ + +static physfs::Filesystem *instance = 0; + +bool hack_setupWriteDirectory() +{ + if (instance != 0) + return instance->setupWriteDirectory(); + return false; +} + +int w_init(lua_State *L) +{ + const char *arg0 = luaL_checkstring(L, 1); + luax_catchexcept(L, [&](){ instance->init(arg0); }); + return 0; +} + +int w_setFused(lua_State *L) +{ + // no error checking needed, everything, even nothing + // can be converted to a boolean + instance->setFused(luax_toboolean(L, 1)); + return 0; +} + +int w_isFused(lua_State *L) +{ + luax_pushboolean(L, instance->isFused()); + return 1; +} + +int w_setIdentity(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + bool append = luax_optboolean(L, 2, false); + + if (!instance->setIdentity(arg, append)) + return luaL_error(L, "Could not set write directory."); + + return 0; +} + +int w_getIdentity(lua_State *L) +{ + lua_pushstring(L, instance->getIdentity()); + return 1; +} + +int w_setSource(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + + if (!instance->setSource(arg)) + return luaL_error(L, "Could not set source."); + + return 0; +} + +int w_getSource(lua_State *L) +{ + lua_pushstring(L, instance->getSource()); + return 1; +} + +int w_mount(lua_State *L) +{ + const char *archive = luaL_checkstring(L, 1); + const char *mountpoint = luaL_checkstring(L, 2); + bool append = luax_optboolean(L, 3, false); + + luax_pushboolean(L, instance->mount(archive, mountpoint, append)); + return 1; +} + +int w_unmount(lua_State *L) +{ + const char *archive = luaL_checkstring(L, 1); + + luax_pushboolean(L, instance->unmount(archive)); + return 1; +} + +int w_newFile(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + + const char *str = 0; + File::Mode mode = File::CLOSED; + + if (lua_isstring(L, 2)) + { + str = luaL_checkstring(L, 2); + if (!File::getConstant(str, mode)) + return luaL_error(L, "Incorrect file open mode: %s", str); + } + + File *t = instance->newFile(filename); + + if (mode != File::CLOSED) + { + try + { + if (!t->open(mode)) + throw love::Exception("Could not open file."); + } + catch (love::Exception &e) + { + t->release(); + return luax_ioError(L, "%s", e.what()); + } + } + + luax_pushtype(L, "File", FILESYSTEM_FILE_T, t); + return 1; +} + +FileData *luax_getfiledata(lua_State *L, int idx) +{ + FileData *data = nullptr; + File *file = nullptr; + + if (lua_isstring(L, idx)) + { + const char *filename = luaL_checkstring(L, idx); + file = instance->newFile(filename); + } + else if (luax_istype(L, idx, FILESYSTEM_FILE_T)) + { + file = luax_checkfile(L, idx); + file->retain(); + } + else if (luax_istype(L, idx, FILESYSTEM_FILE_DATA_T)) + { + data = luax_checkfiledata(L, idx); + data->retain(); + } + + if (!data && !file) + { + luaL_argerror(L, idx, "filename, File, or FileData expected"); + return nullptr; // Never reached. + } + + if (file) + { + luax_catchexcept(L, + [&]() { data = file->read(); }, + [&]() { file->release(); } + ); + } + + return data; +} + +int w_newFileData(lua_State *L) +{ + // Single argument: treat as filepath or File. + if (lua_gettop(L) == 1) + { + // We don't use luax_getfiledata because we want to use an ioError. + if (lua_isstring(L, 1)) + luax_convobj(L, 1, "filesystem", "newFile"); + + // Get FileData from the File. + if (luax_istype(L, 1, FILESYSTEM_FILE_T)) + { + File *file = luax_checkfile(L, 1); + + FileData *data = 0; + try + { + data = file->read(); + } + catch (love::Exception &e) + { + return luax_ioError(L, "%s", e.what()); + } + luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, data); + return 1; + } + else + return luaL_argerror(L, 1, "filename or File expected"); + } + + size_t length = 0; + const char *str = luaL_checklstring(L, 1, &length); + const char *filename = luaL_checkstring(L, 2); + const char *decstr = lua_isstring(L, 3) ? lua_tostring(L, 3) : 0; + + FileData::Decoder decoder = FileData::FILE; + + if (decstr && !FileData::getConstant(decstr, decoder)) + return luaL_error(L, "Invalid FileData decoder: %s", decstr); + + FileData *t = 0; + + switch (decoder) + { + case FileData::FILE: + t = instance->newFileData((void *)str, (int)length, filename); + break; + case FileData::BASE64: + t = instance->newFileData(str, filename); + break; + default: + return luaL_error(L, "Invalid FileData decoder: %s", decstr); + } + + luax_pushtype(L, "FileData", FILESYSTEM_FILE_DATA_T, t); + return 1; +} + +int w_getWorkingDirectory(lua_State *L) +{ + lua_pushstring(L, instance->getWorkingDirectory()); + return 1; +} + +int w_getUserDirectory(lua_State *L) +{ + luax_pushstring(L, instance->getUserDirectory()); + return 1; +} + +int w_getAppdataDirectory(lua_State *L) +{ + luax_pushstring(L, instance->getAppdataDirectory()); + return 1; +} + +int w_getSaveDirectory(lua_State *L) +{ + lua_pushstring(L, instance->getSaveDirectory()); + return 1; +} + +int w_getSourceBaseDirectory(lua_State *L) +{ + luax_pushstring(L, instance->getSourceBaseDirectory()); + return 1; +} + +int w_isDirectory(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + luax_pushboolean(L, instance->isDirectory(arg)); + return 1; +} + +int w_isFile(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + luax_pushboolean(L, instance->isFile(arg)); + return 1; +} + +int w_createDirectory(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + luax_pushboolean(L, instance->createDirectory(arg)); + return 1; +} + +int w_remove(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + luax_pushboolean(L, instance->remove(arg)); + return 1; +} + +int w_read(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int64 len = (int64) luaL_optinteger(L, 2, File::ALL); + + Data *data = 0; + try + { + data = instance->read(filename, len); + } + catch (love::Exception &e) + { + return luax_ioError(L, "%s", e.what()); + } + + if (data == 0) + return luax_ioError(L, "File could not be read."); + + // Push the string. + lua_pushlstring(L, (const char *) data->getData(), data->getSize()); + + // Push the size. + lua_pushinteger(L, data->getSize()); + + // Lua has a copy now, so we can free it. + data->release(); + + return 2; +} + +static int w_write_or_append(lua_State *L, File::Mode mode) +{ + const char *filename = luaL_checkstring(L, 1); + + const char *input = 0; + size_t len = 0; + + if (luax_istype(L, 2, DATA_T)) + { + love::Data *data = luax_totype(L, 2, "Data", DATA_T); + input = (const char *) data->getData(); + len = data->getSize(); + } + else if (lua_isstring(L, 2)) + input = lua_tolstring(L, 2, &len); + else + return luaL_argerror(L, 2, "string or Data expected"); + + // Get how much we should write. Length of string default. + len = luaL_optinteger(L, 3, len); + + try + { + if (mode == File::APPEND) + instance->append(filename, (const void *) input, len); + else + instance->write(filename, (const void *) input, len); + } + catch (love::Exception &e) + { + return luax_ioError(L, "%s", e.what()); + } + + luax_pushboolean(L, true); + return 1; +} + +int w_write(lua_State *L) +{ + return w_write_or_append(L, File::WRITE); +} + +int w_append(lua_State *L) +{ + return w_write_or_append(L, File::APPEND); +} + +int w_getDirectoryItems(lua_State *L) +{ + return instance->getDirectoryItems(L); +} + +int w_lines(lua_State *L) +{ + File *file; + + if (lua_isstring(L, 1)) + { + file = instance->newFile(lua_tostring(L, 1)); + bool success = false; + + luax_catchexcept(L, [&](){ success = file->open(File::READ); }); + + if (!success) + return luaL_error(L, "Could not open file."); + + luax_pushtype(L, "File", FILESYSTEM_FILE_T, file); + } + else + return luaL_argerror(L, 1, "expected filename."); + + lua_pushcclosure(L, physfs::Filesystem::lines_i, 1); + return 1; +} + +int w_load(lua_State *L) +{ + std::string filename = std::string(luaL_checkstring(L, 1)); + + Data *data = 0; + try + { + data = instance->read(filename.c_str()); + } + catch (love::Exception &e) + { + return luax_ioError(L, "%s", e.what()); + } + + int status = luaL_loadbuffer(L, (const char *)data->getData(), data->getSize(), ("@" + filename).c_str()); + + data->release(); + + // Load the chunk, but don't run it. + switch (status) + { + case LUA_ERRMEM: + return luaL_error(L, "Memory allocation error: %s\n", lua_tostring(L, -1)); + case LUA_ERRSYNTAX: + return luaL_error(L, "Syntax error: %s\n", lua_tostring(L, -1)); + default: // success + return 1; + } +} + +int w_getLastModified(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + + int64 time = 0; + try + { + time = instance->getLastModified(filename); + } + catch (love::Exception &e) + { + return luax_ioError(L, "%s", e.what()); + } + + lua_pushnumber(L, static_cast(time)); + return 1; +} + +int w_getSize(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + + int64 size = -1; + try + { + size = instance->getSize(filename); + } + catch (love::Exception &e) + { + return luax_ioError(L, "%s", e.what()); + } + + // Error on failure or if size does not fit into a double precision floating-point number. + if (size == -1) + return luax_ioError(L, "Could not determine file size."); + else if (size >= 0x20000000000000LL) + return luax_ioError(L, "Size too large to fit into a Lua number!"); + + lua_pushnumber(L, (lua_Number) size); + return 1; +} + +int loader(lua_State *L) +{ + const char *filename = lua_tostring(L, -1); + + std::string tmp(filename); + tmp += ".lua"; + + int size = tmp.size(); + + for (int i=0; iisFile(tmp.c_str())) + { + lua_pop(L, 1); + lua_pushstring(L, tmp.c_str()); + // Ok, load it. + return w_load(L); + } + + tmp = filename; + size = tmp.size(); + for (int i=0; iisDirectory(tmp.c_str())) + { + tmp += "/init.lua"; + if (instance->isFile(tmp.c_str())) + { + lua_pop(L, 1); + lua_pushstring(L, tmp.c_str()); + // Ok, load it. + return w_load(L); + } + } + + std::string errstr = "\n\tno file '%s' in LOVE game directories."; + errstr += errstr; + + lua_pushfstring(L, errstr.c_str(), (tmp + ".lua").c_str(), (tmp + "/init.lua").c_str()); + return 1; +} + +inline const char *library_extension() +{ +#ifdef LOVE_WINDOWS + return ".dll"; +#else + return ".so"; +#endif +} + +int extloader(lua_State *L) +{ + const char *filename = lua_tostring(L, -1); + std::string tokenized_name(filename); + std::string tokenized_function(filename); + + for (unsigned int i = 0; i < tokenized_name.size(); i++) + { + if (tokenized_name[i] == '.') + { + tokenized_name[i] = '/'; + tokenized_function[i] = '_'; + } + } + + tokenized_name += library_extension(); + + void *handle = nullptr; + + // If the game is fused, try looking for the DLL in the game's read paths. + if (instance->isFused()) + { + try + { + std::string dir = instance->getRealDirectory(tokenized_name.c_str()); + + // We don't want to look in the game's source, because it can be a + // zip sometimes and a folder other times. + if (dir.find(instance->getSource()) == std::string::npos) + handle = SDL_LoadObject((dir + LOVE_PATH_SEPARATOR + tokenized_name).c_str()); + } + catch (love::Exception &) + { + // Nothing... + } + } + + if (!handle) + { + std::string path = std::string(instance->getAppdataDirectory()) + LOVE_PATH_SEPARATOR LOVE_APPDATA_FOLDER LOVE_PATH_SEPARATOR + tokenized_name; + handle = SDL_LoadObject(path.c_str()); + } + + if (!handle) + { + lua_pushfstring(L, "\n\tno file '%s' in LOVE paths.", tokenized_name.c_str()); + return 1; + } + + void *func = SDL_LoadFunction(handle, ("loveopen_" + tokenized_function).c_str()); + if (!func) + func = SDL_LoadFunction(handle, ("luaopen_" + tokenized_function).c_str()); + + if (!func) + { + SDL_UnloadObject(handle); + lua_pushfstring(L, "\n\tC library '%s' is incompatible.", tokenized_name.c_str()); + return 1; + } + + lua_pushcfunction(L, (lua_CFunction) func); + return 1; +} + +// List of functions to wrap. +static const luaL_Reg functions[] = +{ + { "init", w_init }, + { "setFused", w_setFused }, + { "isFused", w_isFused }, + { "setIdentity", w_setIdentity }, + { "getIdentity", w_getIdentity }, + { "setSource", w_setSource }, + { "getSource", w_getSource }, + { "mount", w_mount }, + { "unmount", w_unmount }, + { "newFile", w_newFile }, + { "getWorkingDirectory", w_getWorkingDirectory }, + { "getUserDirectory", w_getUserDirectory }, + { "getAppdataDirectory", w_getAppdataDirectory }, + { "getSaveDirectory", w_getSaveDirectory }, + { "getSourceBaseDirectory", w_getSourceBaseDirectory }, + { "isDirectory", w_isDirectory }, + { "isFile", w_isFile }, + { "createDirectory", w_createDirectory }, + { "remove", w_remove }, + { "read", w_read }, + { "write", w_write }, + { "append", w_append }, + { "getDirectoryItems", w_getDirectoryItems }, + { "lines", w_lines }, + { "load", w_load }, + { "getLastModified", w_getLastModified }, + { "getSize", w_getSize }, + { "newFileData", w_newFileData }, + { 0, 0 } +}; + +static const lua_CFunction types[] = +{ + luaopen_file, + luaopen_filedata, + 0 +}; + +extern "C" int luaopen_love_filesystem(lua_State *L) +{ + if (instance == 0) + { + luax_catchexcept(L, [&](){ instance = new physfs::Filesystem(); }); + } + else + instance->retain(); + + // The love loaders should be tried after package.preload. + love::luax_register_searcher(L, loader, 2); + love::luax_register_searcher(L, extloader, 3); + + WrappedModule w; + w.module = instance; + w.name = "filesystem"; + w.flags = MODULE_FILESYSTEM_T; + w.functions = functions; + w.types = types; + + return luax_register_module(L, w); +} + +} // filesystem +} // love diff --git a/src/modules/filesystem/wrap_Filesystem.h b/src/modules/filesystem/wrap_Filesystem.h new file mode 100644 index 000000000..4a6161011 --- /dev/null +++ b/src/modules/filesystem/wrap_Filesystem.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2006-2014 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_FILESYSTEM_WRAP_FILESYSTEM_H +#define LOVE_FILESYSTEM_WRAP_FILESYSTEM_H + +// LOVE +#include "common/runtime.h" +#include "FileData.h" + +namespace love +{ +namespace filesystem +{ + +/** + * Gets FileData at the specified index. If the index contains a filepath or + * a File object, the FileData will be created from that. + * Note that this function retains the FileData object (possibly by creating it), + * so a matching release() is required! + * May trigger a Lua error. + **/ +FileData *luax_getfiledata(lua_State *L, int idx); + +bool hack_setupWriteDirectory(); +int w_init(lua_State *L); +int w_setFused(lua_State *L); +int w_isFused(lua_State *L); +int w_setIdentity(lua_State *L); +int w_getIdentity(lua_State *L); +int w_setSource(lua_State *L); +int w_getSource(lua_State *L); +int w_mount(lua_State *L); +int w_unmount(lua_State *L); +int w_newFile(lua_State *L); +int w_newFileData(lua_State *L); +int w_getWorkingDirectory(lua_State *L); +int w_getUserDirectory(lua_State *L); +int w_getAppdataDirectory(lua_State *L); +int w_getSaveDirectory(lua_State *L); +int w_getSourceBaseDirectory(lua_State *L); +int w_isDirectory(lua_State *L); +int w_isFile(lua_State *L); +int w_createDirectory(lua_State *L); +int w_remove(lua_State *L); +int w_open(lua_State *L); +int w_close(lua_State *L); +int w_read(lua_State *L); +int w_write(lua_State *L); +int w_append(lua_State *L); +int w_getDirectoryItems(lua_State *L); +int w_lines(lua_State *L); +int w_load(lua_State *L); +int w_getLastModified(lua_State *L); +int w_getSize(lua_State *L); +int loader(lua_State *L); +int extloader(lua_State *L); +extern "C" LOVE_EXPORT int luaopen_love_filesystem(lua_State *L); + +} // filesystem +} // love + +#endif // LOVE_FILESYSTEM_WRAP_FILESYSTEM_H diff --git a/src/modules/font/freetype/wrap_Font.cpp b/src/modules/font/freetype/wrap_Font.cpp index 935df7d1c..310d09a1f 100644 --- a/src/modules/font/freetype/wrap_Font.cpp +++ b/src/modules/font/freetype/wrap_Font.cpp @@ -25,6 +25,8 @@ #include "font/wrap_GlyphData.h" #include "font/wrap_Rasterizer.h" +#include "filesystem/wrap_Filesystem.h" + #include "TrueTypeRasterizer.h" namespace love @@ -34,31 +36,28 @@ namespace font namespace freetype { -static Font *instance = 0; +static Font *instance = nullptr; int w_newRasterizer(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); + Rasterizer *t = nullptr; - Rasterizer *t = 0; - - EXCEPT_GUARD( - if (luax_istype(L, 1, IMAGE_IMAGE_DATA_T)) - { - love::image::ImageData *d = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); - const char *g = luaL_checkstring(L, 2); - std::string glyphs(g); - t = instance->newRasterizer(d, glyphs); - } - else if (luax_istype(L, 1, DATA_T)) - { - Data *d = luax_checkdata(L, 1); - int size = luaL_checkint(L, 2); - t = instance->newRasterizer(d, size); - } - ) + if (luax_istype(L, 1, IMAGE_IMAGE_DATA_T)) + { + love::image::ImageData *d = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); + const char *g = luaL_checkstring(L, 2); + std::string glyphs(g); + luax_catchexcept(L, [&](){ t = instance->newRasterizer(d, glyphs); }); + } + else if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + { + love::filesystem::FileData *d = love::filesystem::luax_getfiledata(L, 1); + int size = luaL_checkint(L, 2); + luax_catchexcept(L, + [&]() { t = instance->newRasterizer(d, size); }, + [&]() { d->release(); } + ); + } luax_pushtype(L, "Rasterizer", FONT_RASTERIZER_T, t); return 1; @@ -67,14 +66,13 @@ int w_newRasterizer(lua_State *L) int w_newGlyphData(lua_State *L) { Rasterizer *r = luax_checkrasterizer(L, 1); - GlyphData *t = 0; + GlyphData *t = nullptr; // newGlyphData accepts a unicode character or a codepoint number. if (lua_type(L, 2) == LUA_TSTRING) { std::string glyph = luax_checkstring(L, 2); - - EXCEPT_GUARD(t = instance->newGlyphData(r, glyph);) + luax_catchexcept(L, [&](){ t = instance->newGlyphData(r, glyph); }); } else { @@ -103,9 +101,9 @@ static const lua_CFunction types[] = extern "C" int luaopen_love_font(lua_State *L) { - if (instance == 0) + if (instance == nullptr) { - EXCEPT_GUARD(instance = new Font();) + luax_catchexcept(L, [](){ instance = new Font(); }); } else instance->retain(); diff --git a/src/modules/font/wrap_GlyphData.cpp b/src/modules/font/wrap_GlyphData.cpp index c71dcb844..9a8bcfb60 100644 --- a/src/modules/font/wrap_GlyphData.cpp +++ b/src/modules/font/wrap_GlyphData.cpp @@ -64,7 +64,7 @@ int w_GlyphData_getGlyphString(lua_State *L) { GlyphData *t = luax_checkglyphdata(L, 1); - EXCEPT_GUARD(luax_pushstring(L, t->getGlyphString());) + luax_catchexcept(L, [&](){ luax_pushstring(L, t->getGlyphString()); }); return 1; } diff --git a/src/modules/font/wrap_Rasterizer.cpp b/src/modules/font/wrap_Rasterizer.cpp index 0f483a7d9..048c9edc9 100644 --- a/src/modules/font/wrap_Rasterizer.cpp +++ b/src/modules/font/wrap_Rasterizer.cpp @@ -72,7 +72,7 @@ int w_Rasterizer_getGlyphData(lua_State *L) Rasterizer *t = luax_checkrasterizer(L, 1); GlyphData *g = 0; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { // getGlyphData accepts a unicode character or a codepoint number. if (lua_type(L, 2) == LUA_TSTRING) { @@ -84,7 +84,7 @@ int w_Rasterizer_getGlyphData(lua_State *L) uint32 glyph = (uint32) luaL_checknumber(L, 2); g = t->getGlyphData(glyph); } - ) + }); luax_pushtype(L, "GlyphData", FONT_GLYPH_DATA_T, g); return 1; @@ -106,7 +106,7 @@ int w_Rasterizer_hasGlyphs(lua_State *L) int count = lua_gettop(L) - 1; count = count < 1 ? 1 : count; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { for (int i = 2; i < count + 2; i++) { if (lua_type(L, i) == LUA_TSTRING) @@ -117,7 +117,7 @@ int w_Rasterizer_hasGlyphs(lua_State *L) if (!hasglyph) break; } - ) + }); luax_pushboolean(L, hasglyph); return 1; diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index bd7555e89..e6cb81ca4 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -191,6 +191,7 @@ void Image::createMipmaps() GL_RGBA, GL_UNSIGNED_BYTE, data->getData()); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); } } diff --git a/src/modules/graphics/opengl/Mesh.cpp b/src/modules/graphics/opengl/Mesh.cpp index 10597568f..7d38a5710 100644 --- a/src/modules/graphics/opengl/Mesh.cpp +++ b/src/modules/graphics/opengl/Mesh.cpp @@ -39,7 +39,6 @@ Mesh::Mesh(const std::vector &verts, Mesh::DrawMode mode) , ibo(nullptr) , element_count(0) , element_data_type(getGLDataTypeFromMax(verts.size())) - , instance_count(1) , draw_mode(mode) , range_min(-1) , range_max(-1) @@ -175,20 +174,7 @@ void Mesh::setVertexMap(const std::vector &map) GLenum datatype = getGLDataTypeFromMax(vertex_count); // Calculate the size in bytes of the index buffer data. - size_t size = map.size(); - switch (datatype) - { - case GL_UNSIGNED_BYTE: - size *= sizeof(uint8); - break; - case GL_UNSIGNED_SHORT: - size *= sizeof(uint16); - break; - case GL_UNSIGNED_INT: - default: - size *= sizeof(uint32); - break; - } + size_t size = map.size() * getGLDataTypeSize(datatype); if (ibo && size > ibo->getSize()) { @@ -232,10 +218,10 @@ void Mesh::setVertexMap(const std::vector &map) * Copies index data from a mapped buffer to a vector. **/ template -static void copyFromIndexBuffer(void *buffer, std::vector &indices, size_t maxval) +static void copyFromIndexBuffer(void *buffer, size_t count, std::vector &indices) { T *elems = (T *) buffer; - for (size_t i = 0; i < maxval; i++) + for (size_t i = 0; i < count; i++) indices.push_back((uint32) elems[i]); } @@ -256,14 +242,14 @@ void Mesh::getVertexMap(std::vector &map) const switch (element_data_type) { case GL_UNSIGNED_BYTE: - copyFromIndexBuffer(buffer, map, vertex_count); + copyFromIndexBuffer(buffer, element_count, map); break; case GL_UNSIGNED_SHORT: - copyFromIndexBuffer(buffer, map, vertex_count); + copyFromIndexBuffer(buffer, element_count, map); break; case GL_UNSIGNED_INT: default: - copyFromIndexBuffer(buffer, map, vertex_count); + copyFromIndexBuffer(buffer, element_count, map); break; } } @@ -273,16 +259,6 @@ size_t Mesh::getVertexMapCount() const return element_count; } -void Mesh::setInstanceCount(int count) -{ - instance_count = std::max(count, 1); -} - -int Mesh::getInstanceCount() const -{ - return instance_count; -} - void Mesh::setTexture(Texture *tex) { tex->retain(); @@ -398,35 +374,29 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo int max = element_count - 1; if (range_max >= 0) - max = std::min(std::max(range_max, 0), (int) element_count - 1); + max = std::min(range_max, max); int min = 0; if (range_min >= 0) - min = std::min(std::max(range_min, 0), max); + min = std::min(range_min, max); - const void *indices = ibo->getPointer(min * sizeof(uint32)); GLenum type = element_data_type; + const void *indices = ibo->getPointer(min * getGLDataTypeSize(type)); - if (instance_count > 1) - gl.drawElementsInstanced(mode, max - min + 1, type, indices, instance_count); - else - glDrawElements(mode, max - min + 1, type, indices); + glDrawElements(mode, max - min + 1, type, indices); } else { int max = vertex_count - 1; if (range_max >= 0) - max = std::min(std::max(range_max, 0), (int) vertex_count - 1); + max = std::min(range_max, max); int min = 0; if (range_min >= 0) - min = std::min(std::max(range_min, 0), max); + min = std::min(range_min, max); // Normal non-indexed drawing (no custom vertex map.) - if (instance_count > 1) - gl.drawArraysInstanced(mode, min, max - min + 1, instance_count); - else - glDrawArrays(mode, min, max - min + 1); + glDrawArrays(mode, min, max - min + 1); } glDisableClientState(GL_VERTEX_ARRAY); @@ -454,24 +424,34 @@ GLenum Mesh::getGLDrawMode(DrawMode mode) const case DRAW_MODE_STRIP: return GL_TRIANGLE_STRIP; case DRAW_MODE_TRIANGLES: + default: return GL_TRIANGLES; case DRAW_MODE_POINTS: return GL_POINTS; - default: - break; } - - return GL_TRIANGLES; } GLenum Mesh::getGLDataTypeFromMax(size_t maxvalue) const { if (maxvalue > LOVE_UINT16_MAX) return GL_UNSIGNED_INT; - else if (maxvalue > LOVE_UINT8_MAX) - return GL_UNSIGNED_SHORT; else - return GL_UNSIGNED_BYTE; + return GL_UNSIGNED_SHORT; +} + +size_t Mesh::getGLDataTypeSize(GLenum datatype) const +{ + switch (datatype) + { + case GL_UNSIGNED_BYTE: + return sizeof(uint8); + case GL_UNSIGNED_SHORT: + return sizeof(uint16); + case GL_UNSIGNED_INT: + return sizeof(uint32); + default: + return 0; + } } bool Mesh::getConstant(const char *in, Mesh::DrawMode &out) diff --git a/src/modules/graphics/opengl/Mesh.h b/src/modules/graphics/opengl/Mesh.h index da73af438..64b50bd48 100644 --- a/src/modules/graphics/opengl/Mesh.h +++ b/src/modules/graphics/opengl/Mesh.h @@ -119,15 +119,6 @@ public: **/ size_t getVertexMapCount() const; - /** - * Sets the number of instances of this Mesh to draw (uses hardware - * instancing when possible.) - * A custom vertex shader is necessary in order to introduce differences - * in each instance. - **/ - void setInstanceCount(int count); - int getInstanceCount() const; - /** * Sets the texture used when drawing the Mesh. **/ @@ -171,6 +162,7 @@ private: GLenum getGLDrawMode(DrawMode mode) const; GLenum getGLDataTypeFromMax(size_t maxvalue) const; + size_t getGLDataTypeSize(GLenum datatype) const; // Vertex buffer. VertexBuffer *vbo; @@ -181,8 +173,6 @@ private: size_t element_count; GLenum element_data_type; - int instance_count; - DrawMode draw_mode; int range_min; diff --git a/src/modules/graphics/opengl/wrap_Canvas.cpp b/src/modules/graphics/opengl/wrap_Canvas.cpp index 8b1bb32f6..885374202 100644 --- a/src/modules/graphics/opengl/wrap_Canvas.cpp +++ b/src/modules/graphics/opengl/wrap_Canvas.cpp @@ -40,7 +40,7 @@ int w_Canvas_renderTo(lua_State *L) // Save the current Canvas so we can restore it when we're done. Canvas *oldcanvas = Canvas::current; - EXCEPT_GUARD(canvas->startGrab();) + luax_catchexcept(L, [&](){ canvas->startGrab(); }); lua_settop(L, 2); // make sure the function is on top of the stack lua_call(L, 0, 0); @@ -69,7 +69,7 @@ int w_Canvas_getPixel(lua_State * L) int y = luaL_checkint(L, 3); unsigned char c[4]; - EXCEPT_GUARD(canvas->getPixel(c, x, y);) + luax_catchexcept(L, [&](){ canvas->getPixel(c, x, y); }); lua_pushnumber(L, c[0]); lua_pushnumber(L, c[1]); diff --git a/src/modules/graphics/opengl/wrap_Font.cpp b/src/modules/graphics/opengl/wrap_Font.cpp index e30fa12c2..379a5245f 100644 --- a/src/modules/graphics/opengl/wrap_Font.cpp +++ b/src/modules/graphics/opengl/wrap_Font.cpp @@ -45,7 +45,7 @@ int w_Font_getWidth(lua_State *L) Font *t = luax_checkfont(L, 1); const char *str = luaL_checkstring(L, 2); - EXCEPT_GUARD(lua_pushinteger(L, t->getWidth(str));) + luax_catchexcept(L, [&](){ lua_pushinteger(L, t->getWidth(str)); }); return 1; } @@ -56,10 +56,10 @@ int w_Font_getWrap(lua_State *L) float wrap = (float) luaL_checknumber(L, 3); int max_width = 0, numlines = 0; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { std::vector lines = t->getWrap(str, wrap, &max_width); numlines = lines.size(); - ) + }); lua_pushinteger(L, max_width); lua_pushinteger(L, numlines); @@ -96,7 +96,7 @@ int w_Font_setFilter(lua_State *L) f.anisotropy = (float) luaL_optnumber(L, 4, 1.0); - EXCEPT_GUARD(t->setFilter(f);) + luax_catchexcept(L, [&](){ t->setFilter(f); }); return 0; } @@ -143,7 +143,7 @@ int w_Font_hasGlyphs(lua_State *L) int count = lua_gettop(L) - 1; count = count < 1 ? 1 : count; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { for (int i = 2; i < count + 2; i++) { if (lua_type(L, i) == LUA_TSTRING) @@ -154,7 +154,7 @@ int w_Font_hasGlyphs(lua_State *L) if (!hasglyph) break; } - ) + }); luax_pushboolean(L, hasglyph); return 1; diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index cc5d77745..929edd263 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -22,7 +22,9 @@ #include "OpenGL.h" #include "graphics/Texture.h" #include "image/ImageData.h" +#include "image/Image.h" #include "font/Rasterizer.h" +#include "filesystem/wrap_Filesystem.h" #include "scripts/graphics.lua.h" #include @@ -155,43 +157,59 @@ int w_newImage(lua_State *L) if (fstr != nullptr && !Image::getConstant(fstr, format)) return luaL_error(L, "Invalid Image format: %s", fstr); - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); + bool releasedata = false; - // Convert to ImageData/CompressedData, if necessary. - if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + // Convert to ImageData / CompressedData, if necessary. + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) { - // Determine whether to convert to ImageData or CompressedData. - luax_getfunction(L, "image", "isCompressed"); - lua_pushvalue(L, 1); - lua_call(L, 1, 1); + love::image::Image *image = (love::image::Image *) Module::findInstance("love.image."); + if (image == nullptr) + return luaL_error(L, "Cannot load images without the love.image module."); - bool compressed = luax_toboolean(L, -1); - lua_pop(L, 1); + love::filesystem::FileData *fdata = love::filesystem::luax_getfiledata(L, 1); - if (compressed) - luax_convobj(L, 1, "image", "newCompressedData"); + if (image->isCompressed(fdata)) + { + luax_catchexcept(L, + [&]() { cdata = image->newCompressedData(fdata); }, + [&]() { fdata->release(); } + ); + } else - luax_convobj(L, 1, "image", "newImageData"); - } + { + luax_catchexcept(L, + [&]() { data = image->newImageData(fdata); }, + [&]() { fdata->release(); } + ); + } - if (luax_istype(L, 1, IMAGE_COMPRESSED_DATA_T)) + // Lua's GC won't release the image data, so we should do it ourselves. + releasedata = true; + } + else if (luax_istype(L, 1, IMAGE_COMPRESSED_DATA_T)) cdata = luax_checktype(L, 1, "CompressedData", IMAGE_COMPRESSED_DATA_T); else data = luax_checktype(L, 1, "ImageData", IMAGE_IMAGE_DATA_T); if (!data && !cdata) - return luaL_error(L, "Error creating image."); + return luaL_error(L, "Error creating image (could not load data.)"); // Create the image. Image *image = nullptr; - EXCEPT_GUARD( - if (cdata) - image = instance->newImage(cdata, format); - else if (data) - image = instance->newImage(data, format); - ) + luax_catchexcept(L, + [&]() { + if (cdata) + image = instance->newImage(cdata, format); + else if (data) + image = instance->newImage(data, format); + }, + [&]() { + if (releasedata && data) + data->release(); + else if (releasedata && cdata) + cdata->release(); + } + ); if (image == nullptr) return luaL_error(L, "Could not load image."); @@ -219,12 +237,8 @@ int w_newQuad(lua_State *L) int w_newFont(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - // Convert to Rasterizer, if necessary. - if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T)) { int idxs[] = {1, 2}; luax_convobj(L, idxs, 2, "font", "newRasterizer"); @@ -233,7 +247,9 @@ int w_newFont(lua_State *L) love::font::Rasterizer *rasterizer = luax_checktype(L, 1, "Rasterizer", FONT_RASTERIZER_T); Font *font = 0; - EXCEPT_GUARD(font = instance->newFont(rasterizer, instance->getDefaultFilter());) + luax_catchexcept(L, [&]() { + font = instance->newFont(rasterizer, instance->getDefaultFilter()); } + ); if (font == 0) return luaL_error(L, "Could not load font."); @@ -297,7 +313,9 @@ int w_newSpriteBatch(lua_State *L) } SpriteBatch *t = nullptr; - EXCEPT_GUARD(t = instance->newSpriteBatch(texture, size, usage);) + luax_catchexcept(L, + [&](){ t = instance->newSpriteBatch(texture, size, usage); } + ); luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t); return 1; @@ -311,7 +329,9 @@ int w_newParticleSystem(lua_State *L) if (size < 1.0 || size > ParticleSystem::MAX_PARTICLES) return luaL_error(L, "Invalid ParticleSystem size"); - EXCEPT_GUARD(t = instance->newParticleSystem(texture, int(size));) + luax_catchexcept(L, + [&](){ t = instance->newParticleSystem(texture, int(size)); } + ); luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t); return 1; @@ -330,7 +350,9 @@ int w_newCanvas(lua_State *L) return luaL_error(L, "Invalid Canvas format: %s", str); Canvas *canvas = nullptr; - EXCEPT_GUARD(canvas = instance->newCanvas(width, height, format, fsaa);) + luax_catchexcept(L, + [&](){ canvas = instance->newCanvas(width, height, format, fsaa); } + ); if (canvas == nullptr) return luaL_error(L, "Canvas not created, but no error thrown. I don't even..."); @@ -498,13 +520,13 @@ int w_newMesh(lua_State *L) vertices.push_back(v); } - EXCEPT_GUARD(t = instance->newMesh(vertices, mode);) + luax_catchexcept(L, [&](){ t = instance->newMesh(vertices, mode); }); t->setVertexColors(use_colors); } else { int count = luaL_checkint(L, 1); - EXCEPT_GUARD(t = instance->newMesh(count, mode);) + luax_catchexcept(L, [&](){ t = instance->newMesh(count, mode); }); } if (tex) @@ -643,7 +665,7 @@ int w_setBlendMode(lua_State *L) if (!Graphics::getConstant(str, mode)) return luaL_error(L, "Invalid blend mode: %s", str); - EXCEPT_GUARD(instance->setBlendMode(mode);) + luax_catchexcept(L, [&](){ instance->setBlendMode(mode); }); return 0; } @@ -652,7 +674,7 @@ int w_getBlendMode(lua_State *L) const char *str; Graphics::BlendMode mode; - EXCEPT_GUARD(mode = instance->getBlendMode();) + luax_catchexcept(L, [&](){ mode = instance->getBlendMode(); }); if (!Graphics::getConstant(mode, str)) return luaL_error(L, "Unknown blend mode"); @@ -822,7 +844,7 @@ int w_newScreenshot(lua_State *L) bool copyAlpha = luax_optboolean(L, 1, false); love::image::ImageData *i = 0; - EXCEPT_GUARD(i = instance->newScreenshot(image, copyAlpha);) + luax_catchexcept(L, [&](){ i = instance->newScreenshot(image, copyAlpha); }); luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i); return 1; @@ -866,12 +888,12 @@ int w_setCanvas(lua_State *L) attachments.push_back(luax_checkcanvas(L, i)); } - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { if (attachments.size() > 0) canvas->startGrab(attachments); else canvas->startGrab(); - ) + }); return 0; } @@ -990,10 +1012,12 @@ int w_getRendererInfo(lua_State *L) { std::string name, version, vendor, device; - EXCEPT_GUARD(name = instance->getRendererInfo(Graphics::RENDERER_INFO_NAME);) - EXCEPT_GUARD(version = instance->getRendererInfo(Graphics::RENDERER_INFO_VERSION);) - EXCEPT_GUARD(vendor = instance->getRendererInfo(Graphics::RENDERER_INFO_VENDOR);) - EXCEPT_GUARD(device = instance->getRendererInfo(Graphics::RENDERER_INFO_DEVICE);) + luax_catchexcept(L, [&]() { + name = instance->getRendererInfo(Graphics::RENDERER_INFO_NAME); + version = instance->getRendererInfo(Graphics::RENDERER_INFO_VERSION); + vendor = instance->getRendererInfo(Graphics::RENDERER_INFO_VENDOR); + device = instance->getRendererInfo(Graphics::RENDERER_INFO_DEVICE); + }); luax_pushstring(L, name); luax_pushstring(L, version); @@ -1069,7 +1093,9 @@ int w_print(lua_State *L) float kx = (float)luaL_optnumber(L, 9, 0.0f); float ky = (float)luaL_optnumber(L, 10, 0.0f); - EXCEPT_GUARD(instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky);) + luax_catchexcept(L, + [&](){ instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky); } + ); return 0; } @@ -1105,7 +1131,9 @@ int w_printf(lua_State *L) ky = (float) luaL_optnumber(L, 12, 0.0f); } - EXCEPT_GUARD(instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky);) + luax_catchexcept(L, + [&](){ instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky); } + ); return 0; } @@ -1261,13 +1289,13 @@ int w_polygon(lua_State *L) int w_push(lua_State *L) { - EXCEPT_GUARD(instance->push();) + luax_catchexcept(L, [&](){ instance->push(); }); return 0; } int w_pop(lua_State *L) { - EXCEPT_GUARD(instance->pop();) + luax_catchexcept(L, [&](){ instance->pop(); }); return 0; } @@ -1417,7 +1445,7 @@ extern "C" int luaopen_love_graphics(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new Graphics();) + luax_catchexcept(L, [&](){ instance = new Graphics(); }); } else instance->retain(); diff --git a/src/modules/graphics/opengl/wrap_Image.cpp b/src/modules/graphics/opengl/wrap_Image.cpp index be95571e7..da9107e5a 100644 --- a/src/modules/graphics/opengl/wrap_Image.cpp +++ b/src/modules/graphics/opengl/wrap_Image.cpp @@ -47,7 +47,7 @@ int w_Image_setMipmapFilter(lua_State *L) return luaL_error(L, "Invalid filter mode: %s", mipmapstr); } - EXCEPT_GUARD(t->setFilter(f);) + luax_catchexcept(L, [&](){ t->setFilter(f); }); float sharpness = (float) luaL_optnumber(L, 3, 0); t->setMipmapSharpness(sharpness); @@ -81,7 +81,7 @@ int w_Image_isCompressed(lua_State *L) int w_Image_refresh(lua_State *L) { Image *i = luax_checkimage(L, 1); - EXCEPT_GUARD(i->refresh();) + luax_catchexcept(L, [&](){ i->refresh(); }); return 0; } diff --git a/src/modules/graphics/opengl/wrap_Mesh.cpp b/src/modules/graphics/opengl/wrap_Mesh.cpp index fb3987011..bacc5282c 100644 --- a/src/modules/graphics/opengl/wrap_Mesh.cpp +++ b/src/modules/graphics/opengl/wrap_Mesh.cpp @@ -74,7 +74,7 @@ int w_Mesh_setVertex(lua_State *L) v.a = luaL_optinteger(L, 10, 255); } - EXCEPT_GUARD(t->setVertex(i, v);) + luax_catchexcept(L, [&](){ t->setVertex(i, v); }); return 0; } @@ -84,7 +84,7 @@ int w_Mesh_getVertex(lua_State *L) size_t i = (size_t) (luaL_checkinteger(L, 2) - 1); Vertex v; - EXCEPT_GUARD(v = t->getVertex(i);) + luax_catchexcept(L, [&](){ v = t->getVertex(i); }); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); @@ -134,7 +134,7 @@ int w_Mesh_setVertices(lua_State *L) vertices.push_back(v); } - EXCEPT_GUARD(t->setVertices(vertices);) + luax_catchexcept(L, [&](){ t->setVertices(vertices); }); return 0; } @@ -216,7 +216,7 @@ int w_Mesh_setVertexMap(lua_State *L) vertexmap.push_back(uint32(luaL_checkinteger(L, i + 2) - 1)); } - EXCEPT_GUARD(t->setVertexMap(vertexmap);) + luax_catchexcept(L, [&](){ t->setVertexMap(vertexmap); }); return 0; } @@ -225,7 +225,7 @@ int w_Mesh_getVertexMap(lua_State *L) Mesh *t = luax_checkmesh(L, 1); std::vector vertex_map; - EXCEPT_GUARD(t->getVertexMap(vertex_map);) + luax_catchexcept(L, [&](){ t->getVertexMap(vertex_map); }); size_t element_count = vertex_map.size(); @@ -240,20 +240,6 @@ int w_Mesh_getVertexMap(lua_State *L) return 1; } -int w_Mesh_setInstanceCount(lua_State *L) -{ - Mesh *t = luax_checkmesh(L, 1); - t->setInstanceCount(luaL_checkint(L, 2)); - return 0; -} - -int w_Mesh_getInstanceCount(lua_State *L) -{ - Mesh *t = luax_checkmesh(L, 1); - lua_pushinteger(L, t->getInstanceCount()); - return 1; -} - int w_Mesh_setTexture(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); @@ -329,7 +315,7 @@ int w_Mesh_setDrawRange(lua_State *L) { int rangemin = luaL_checkint(L, 2) - 1; int rangemax = luaL_checkint(L, 3) - 1; - EXCEPT_GUARD(t->setDrawRange(rangemin, rangemax);) + luax_catchexcept(L, [&](){ t->setDrawRange(rangemin, rangemax); }); } return 0; @@ -374,12 +360,6 @@ static const luaL_Reg functions[] = { "getVertexCount", w_Mesh_getVertexCount }, { "setVertexMap", w_Mesh_setVertexMap }, { "getVertexMap", w_Mesh_getVertexMap }, - - // Disabled for now, since implementation is incomplete and might change - // if/when VertexBuffers / custom vertex attributes are added. - // { "setInstanceCount", w_Mesh_setInstanceCount }, - // { "getInstanceCount", w_Mesh_getInstanceCount }, - { "setTexture", w_Mesh_setTexture }, { "getTexture", w_Mesh_getTexture }, { "setDrawMode", w_Mesh_setDrawMode }, diff --git a/src/modules/graphics/opengl/wrap_Mesh.h b/src/modules/graphics/opengl/wrap_Mesh.h index aa7c0f08b..60b07b853 100644 --- a/src/modules/graphics/opengl/wrap_Mesh.h +++ b/src/modules/graphics/opengl/wrap_Mesh.h @@ -41,8 +41,6 @@ int w_Mesh_getVertices(lua_State *L); int w_Mesh_getVertexCount(lua_State *L); int w_Mesh_setVertexMap(lua_State *L); int w_Mesh_getVertexMap(lua_State *L); -int w_Mesh_setInstanceCount(lua_State *L); -int w_Mesh_getInstanceCount(lua_State *L); int w_Mesh_setTexture(lua_State *L); int w_Mesh_getTexture(lua_State *L); int w_Mesh_setDrawMode(lua_State *L); diff --git a/src/modules/graphics/opengl/wrap_ParticleSystem.cpp b/src/modules/graphics/opengl/wrap_ParticleSystem.cpp index 6026cb230..5f196d475 100644 --- a/src/modules/graphics/opengl/wrap_ParticleSystem.cpp +++ b/src/modules/graphics/opengl/wrap_ParticleSystem.cpp @@ -49,7 +49,7 @@ int w_ParticleSystem_clone(lua_State *L) ParticleSystem *t = luax_checkparticlesystem(L, 1); ParticleSystem *clone = nullptr; - EXCEPT_GUARD(clone = t->clone();) + luax_catchexcept(L, [&](){ clone = t->clone(); }); luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, clone); return 1; @@ -90,7 +90,7 @@ int w_ParticleSystem_setBufferSize(lua_State *L) if (arg1 < 1.0 || arg1 > ParticleSystem::MAX_PARTICLES) return luaL_error(L, "Invalid buffer size"); - EXCEPT_GUARD(t->setBufferSize((uint32) arg1);) + luax_catchexcept(L, [&](){ t->setBufferSize((uint32) arg1); }); return 0; } @@ -128,7 +128,7 @@ int w_ParticleSystem_setEmissionRate(lua_State *L) { ParticleSystem *t = luax_checkparticlesystem(L, 1); float arg1 = (float) luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setEmissionRate(arg1);) + luax_catchexcept(L, [&](){ t->setEmissionRate(arg1); }); return 0; } diff --git a/src/modules/graphics/opengl/wrap_Shader.cpp b/src/modules/graphics/opengl/wrap_Shader.cpp index 914c153c3..5911a253f 100644 --- a/src/modules/graphics/opengl/wrap_Shader.cpp +++ b/src/modules/graphics/opengl/wrap_Shader.cpp @@ -232,22 +232,10 @@ int w_Shader_sendMatrix(lua_State *L) lua_pop(L, 1 + dimension); } - bool should_error = false; - - try - { - shader->sendMatrix(name, dimension, values, count); - } - catch(love::Exception &e) - { - should_error = true; - lua_pushstring(L, e.what()); - } - - delete[] values; - - if (should_error) - return luaL_error(L, "%s", lua_tostring(L, -1)); + luax_catchexcept(L, + [&]() { shader->sendMatrix(name, dimension, values, count); }, + [&]() { delete[] values; } + ); return 0; } @@ -258,7 +246,7 @@ int w_Shader_sendTexture(lua_State *L) const char *name = luaL_checkstring(L, 2); Texture *texture = luax_checktexture(L, 3); - EXCEPT_GUARD(shader->sendTexture(name, texture);) + luax_catchexcept(L, [&](){ shader->sendTexture(name, texture); }); return 0; } diff --git a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp index 6c7083ca3..fb2b5f3ba 100644 --- a/src/modules/graphics/opengl/wrap_SpriteBatch.cpp +++ b/src/modules/graphics/opengl/wrap_SpriteBatch.cpp @@ -64,12 +64,12 @@ int w_SpriteBatch_add(lua_State *L) float ky = (float) luaL_optnumber(L, startidx + 8, 0.0); int id = 0; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { if (quad) id = t->addq(quad, x, y, a, sx, sy, ox, oy, kx, ky); else id = t->add(x, y, a, sx, sy, ox, oy, kx, ky); - ) + }); lua_pushinteger(L, id); return 1; @@ -101,12 +101,12 @@ int w_SpriteBatch_set(lua_State *L) float kx = (float) luaL_optnumber(L, startidx + 7, 0.0); float ky = (float) luaL_optnumber(L, startidx + 8, 0.0); - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { if (quad) t->addq(quad, x, y, a, sx, sy, ox, oy, kx, ky, id); else t->add(x, y, a, sx, sy, ox, oy, kx, ky, id); - ) + }); return 0; } @@ -216,7 +216,7 @@ int w_SpriteBatch_setBufferSize(lua_State *L) { SpriteBatch *t = luax_checkspritebatch(L, 1); int size = luaL_checkint(L, 2); - EXCEPT_GUARD(t->setBufferSize(size);) + luax_catchexcept(L, [&]() {t->setBufferSize(size); }); return 0; } diff --git a/src/modules/graphics/opengl/wrap_Texture.cpp b/src/modules/graphics/opengl/wrap_Texture.cpp index 3401115a5..830c72659 100644 --- a/src/modules/graphics/opengl/wrap_Texture.cpp +++ b/src/modules/graphics/opengl/wrap_Texture.cpp @@ -69,7 +69,7 @@ int w_Texture_setFilter(lua_State *L) f.anisotropy = (float) luaL_optnumber(L, 4, 1.0); - EXCEPT_GUARD(t->setFilter(f);) + luax_catchexcept(L, [&](){ t->setFilter(f); }); return 0; } diff --git a/src/modules/image/CompressedData.cpp b/src/modules/image/CompressedData.cpp index e4d47331c..d72ab5b0d 100644 --- a/src/modules/image/CompressedData.cpp +++ b/src/modules/image/CompressedData.cpp @@ -87,7 +87,7 @@ CompressedData::Format CompressedData::getFormat() const void CompressedData::checkMipmapLevelExists(int miplevel) const { if (miplevel < 0 || miplevel >= (int) dataImages.size()) - throw love::Exception("Mipmap level %d does not exist", miplevel); + throw love::Exception("Mipmap level %d does not exist", miplevel + 1); } bool CompressedData::getConstant(const char *in, CompressedData::Format &out) diff --git a/src/modules/image/wrap_CompressedData.cpp b/src/modules/image/wrap_CompressedData.cpp index f4b0c5752..3b0fd65ce 100644 --- a/src/modules/image/wrap_CompressedData.cpp +++ b/src/modules/image/wrap_CompressedData.cpp @@ -37,7 +37,7 @@ int w_CompressedData_getWidth(lua_State *L) int miplevel = luaL_optinteger(L, 2, 1); int width = 0; - EXCEPT_GUARD(width = t->getWidth(miplevel >= 1 ? miplevel - 1 : 0);) + luax_catchexcept(L, [&](){ width = t->getWidth(miplevel - 1); }); lua_pushinteger(L, width); return 1; @@ -49,7 +49,7 @@ int w_CompressedData_getHeight(lua_State *L) int miplevel = luaL_optinteger(L, 2, 1); int height = 0; - EXCEPT_GUARD(height = t->getHeight(miplevel >= 1 ? miplevel - 1 : 0);) + luax_catchexcept(L, [&](){ height = t->getHeight(miplevel - 1); }); lua_pushinteger(L, height); return 1; @@ -61,10 +61,11 @@ int w_CompressedData_getDimensions(lua_State *L) int miplevel = luaL_optinteger(L, 2, 1); int width = 0, height = 0; - EXCEPT_GUARD( - width = t->getWidth(miplevel >= 1 ? miplevel - 1 : 0); - height = t->getHeight(miplevel >= 1 ? miplevel - 1 : 0); - ) + luax_catchexcept(L, [&]() + { + width = t->getWidth(miplevel - 1); + height = t->getHeight(miplevel - 1); + }); lua_pushinteger(L, width); lua_pushinteger(L, height); diff --git a/src/modules/image/wrap_Image.cpp b/src/modules/image/wrap_Image.cpp index 93896f852..33ce40cce 100644 --- a/src/modules/image/wrap_Image.cpp +++ b/src/modules/image/wrap_Image.cpp @@ -25,12 +25,14 @@ #include "magpie/Image.h" +#include "filesystem/wrap_Filesystem.h" + namespace love { namespace image { -static Image *instance = 0; +static Image *instance = nullptr; int w_newImageData(lua_State *L) { @@ -42,23 +44,21 @@ int w_newImageData(lua_State *L) if (w <= 0 || h <= 0) return luaL_error(L, "Invalid image size."); - ImageData *t = 0; - EXCEPT_GUARD(t = instance->newImageData(w, h);) + ImageData *t = nullptr; + luax_catchexcept(L, [&](){ t = instance->newImageData(w, h); }); luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t); return 1; } // Case 2: File(Data). + love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1); - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - - ImageData *t = 0; - EXCEPT_GUARD(t = instance->newImageData(data);) + ImageData *t = nullptr; + luax_catchexcept(L, + [&]() { t = instance->newImageData(data); }, + [&]() { data->release(); } + ); luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, t); return 1; @@ -66,14 +66,13 @@ int w_newImageData(lua_State *L) int w_newCompressedData(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); + love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1); - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - - CompressedData *t = 0; - EXCEPT_GUARD(t = instance->newCompressedData(data);) + CompressedData *t = nullptr; + luax_catchexcept(L, + [&]() { t = instance->newCompressedData(data); }, + [&]() { data->release(); } + ); luax_pushtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, t); return 1; @@ -81,14 +80,9 @@ int w_newCompressedData(lua_State *L) int w_isCompressed(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - - bool compressed = false; - EXCEPT_GUARD(compressed = instance->isCompressed(data);) + love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1); + bool compressed = instance->isCompressed(data); + data->release(); luax_pushboolean(L, compressed); return 1; @@ -112,9 +106,9 @@ static const lua_CFunction types[] = extern "C" int luaopen_love_image(lua_State *L) { - if (instance == 0) + if (instance == nullptr) { - EXCEPT_GUARD(instance = new love::image::magpie::Image();) + luax_catchexcept(L, [&](){ instance = new love::image::magpie::Image(); }); } else instance->retain(); diff --git a/src/modules/image/wrap_ImageData.cpp b/src/modules/image/wrap_ImageData.cpp index 401e4b718..cb3c941a1 100644 --- a/src/modules/image/wrap_ImageData.cpp +++ b/src/modules/image/wrap_ImageData.cpp @@ -62,7 +62,7 @@ int w_ImageData_getPixel(lua_State *L) int y = luaL_checkint(L, 3); pixel c; - EXCEPT_GUARD(c = t->getPixel(x, y);) + luax_catchexcept(L, [&](){ c = t->getPixel(x, y); }); lua_pushnumber(L, c.r); lua_pushnumber(L, c.g); @@ -98,7 +98,7 @@ int w_ImageData_setPixel(lua_State *L) c.a = (unsigned char)luaL_optinteger(L, 7, 255); } - EXCEPT_GUARD(t->setPixel(x, y, c);) + luax_catchexcept(L, [&](){ t->setPixel(x, y, c); }); return 0; } @@ -261,7 +261,7 @@ int w_ImageData_encode(lua_State *L) return luaL_error(L, "Invalid image format '%s'.", fmt); } - EXCEPT_GUARD(t->encode(file, format);) + luax_catchexcept(L, [&](){ t->encode(file, format); }); return 0; } diff --git a/src/modules/joystick/JoystickModule.h b/src/modules/joystick/JoystickModule.h index d1a488c3d..b7df698ff 100644 --- a/src/modules/joystick/JoystickModule.h +++ b/src/modules/joystick/JoystickModule.h @@ -85,6 +85,20 @@ public: **/ virtual Joystick::JoystickInput getGamepadMapping(const std::string &pguid, Joystick::GamepadInput gpinput) = 0; + /** + * Loads a newline-separated list of virtual Gamepad mapping strings for + * multiple joysticks at a time. The mapping strings must have been + * generated with saveGamepadMappings, via Steam, or some other tool which + * generates SDL GameController mappings. + **/ + virtual void loadGamepadMappings(const std::string &mappings) = 0; + + /** + * Gets a newline-separated list of virtual Gamepad mapping strings for + * all used or modified Joysticks which are identified as Gamepads. + **/ + virtual std::string saveGamepadMappings() = 0; + }; // JoystickModule } // joystick diff --git a/src/modules/joystick/sdl/Joystick.cpp b/src/modules/joystick/sdl/Joystick.cpp index a7eccae0c..3ae2a03dd 100644 --- a/src/modules/joystick/sdl/Joystick.cpp +++ b/src/modules/joystick/sdl/Joystick.cpp @@ -191,12 +191,14 @@ bool Joystick::isDown(const std::vector &buttonlist) const if (!isConnected()) return false; - int num = getButtonCount(); + int numbuttons = getButtonCount(); - for (size_t i = 0; i < buttonlist.size(); i++) + for (int button : buttonlist) { - int button = buttonlist[i]; - if (button >= 0 && button < num && SDL_JoystickGetButton(joyhandle, button) == 1) + if (button < 0 || button >= numbuttons) + continue; + + if (SDL_JoystickGetButton(joyhandle, button) == 1) return true; } @@ -244,9 +246,9 @@ bool Joystick::isGamepadDown(const std::vector &blist) const SDL_GameControllerButton sdlbutton; - for (size_t i = 0; i < blist.size(); i++) + for (GamepadButton button : blist) { - if (!getConstant(blist[i], sdlbutton)) + if (!getConstant(button, sdlbutton)) continue; if (SDL_GameControllerGetButton(controller, sdlbutton) == 1) diff --git a/src/modules/joystick/sdl/JoystickModule.cpp b/src/modules/joystick/sdl/JoystickModule.cpp index ab0a28b16..4ec6deb00 100644 --- a/src/modules/joystick/sdl/JoystickModule.cpp +++ b/src/modules/joystick/sdl/JoystickModule.cpp @@ -57,10 +57,10 @@ JoystickModule::JoystickModule() JoystickModule::~JoystickModule() { // Close any open Joysticks. - for (auto it = joysticks.begin(); it != joysticks.end(); ++it) + for (auto stick : joysticks) { - (*it)->close(); - (*it)->release(); + stick->close(); + stick->release(); } if (SDL_WasInit(SDL_INIT_HAPTIC) != 0) @@ -101,10 +101,10 @@ int JoystickModule::getJoystickCount() const love::joystick::Joystick *JoystickModule::getJoystickFromID(int instanceid) { - for (size_t i = 0; i < activeSticks.size(); i++) + for (auto stick : activeSticks) { - if (instanceid == activeSticks[i]->getInstanceID()) - return activeSticks[i]; + if (stick->getInstanceID() == instanceid) + return stick; } return nullptr; @@ -119,12 +119,12 @@ love::joystick::Joystick *JoystickModule::addJoystick(int deviceindex) joystick::Joystick *joystick = 0; bool reused = false; - for (auto it = joysticks.begin(); it != joysticks.end(); ++it) + for (auto stick : joysticks) { // Try to re-use a disconnected Joystick with the same GUID. - if (!(*it)->isConnected() && (*it)->getGUID() == guidstr) + if (!stick->isConnected() && stick->getGUID() == guidstr) { - joystick = *it; + joystick = stick; reused = true; break; } @@ -144,9 +144,9 @@ love::joystick::Joystick *JoystickModule::addJoystick(int deviceindex) // Make sure multiple instances of the same physical joystick aren't added // to the active list. - for (auto it = activeSticks.begin(); it != activeSticks.end(); ++it) + for (auto activestick : activeSticks) { - if (joystick->getHandle() == (*it)->getHandle()) + if (joystick->getHandle() == activestick->getHandle()) { joystick->close(); @@ -157,10 +157,13 @@ love::joystick::Joystick *JoystickModule::addJoystick(int deviceindex) joystick->release(); } - return *it; + return activestick; } } + if (joystick->isGamepad()) + recentGamepadGUIDs[joystick->getGUID()] = true; + activeSticks.push_back(joystick); return joystick; } @@ -257,6 +260,9 @@ bool JoystickModule::setGamepadMapping(const std::string &guid, Joystick::Gamepa // 1 == added, 0 == updated, -1 == error. int status = SDL_GameControllerAddMapping(mapstr.c_str()); + if (status != -1) + recentGamepadGUIDs[guid] = true; + // FIXME: massive hack until missing APIs are added to SDL 2: // https://bugzilla.libsdl.org/show_bug.cgi?id=1975 if (status == 1) @@ -427,22 +433,23 @@ void JoystickModule::checkGamepads(const std::string &guid) const if (guid.compare(getDeviceGUID(d_index)) != 0) continue; - for (auto it = activeSticks.begin(); it != activeSticks.end(); ++it) + for (auto stick : activeSticks) { - if ((*it)->isGamepad() || guid.compare((*it)->getGUID()) != 0) + if (stick->isGamepad() || guid.compare(stick->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 == nullptr) + SDL_GameController *controller = SDL_GameControllerOpen(d_index); + if (controller == nullptr) continue; - SDL_Joystick *stick = SDL_GameControllerGetJoystick(ctrl); - if (stick == (SDL_Joystick *) (*it)->getHandle()) - (*it)->openGamepad(d_index); + SDL_Joystick *sdlstick = SDL_GameControllerGetJoystick(controller); + if (sdlstick == (SDL_Joystick *) stick->getHandle()) + stick->openGamepad(d_index); - SDL_GameControllerClose(ctrl); + // GameController objects are reference-counted in SDL. + SDL_GameControllerClose(controller); } } } @@ -462,6 +469,80 @@ std::string JoystickModule::getDeviceGUID(int deviceindex) const return std::string(guidstr); } +void JoystickModule::loadGamepadMappings(const std::string &mappings) +{ + // TODO: We should use SDL_GameControllerAddMappingsFromRW. We're + // duplicating its functionality for now because it was added after + // SDL 2.0.0's release, and we want runtime compat with 2.0.0 on Linux... + + std::stringstream ss(mappings); + std::string mapping; + bool success = false; + + // The mappings string contains newline-separated mappings. + while (std::getline(ss, mapping)) + { + if (mapping.empty()) + continue; + + // Strip out and compare any "platform:XYZ," in the mapping. + size_t pstartpos = mapping.find("platform:"); + if (pstartpos != std::string::npos) + { + pstartpos += strlen("platform:"); + + size_t pendpos = mapping.find_first_of(',', pstartpos); + std::string platform = mapping.substr(pstartpos, pendpos - pstartpos); + + if (platform.compare(SDL_GetPlatform()) != 0) + continue; + + pstartpos -= strlen("platform:"); + mapping.erase(pstartpos, pendpos - pstartpos + 1); + } + + if (SDL_GameControllerAddMapping(mapping.c_str()) != -1) + { + success = true; + std::string guid = mapping.substr(0, mapping.find_first_of(',')); + recentGamepadGUIDs[guid] = true; + + // FIXME: massive hack until missing APIs are added to SDL 2: + // https://bugzilla.libsdl.org/show_bug.cgi?id=1975 + checkGamepads(guid); + } + } + + if (!success) + throw love::Exception("Invalid gamepad mappings."); +} + +std::string JoystickModule::saveGamepadMappings() +{ + std::string mappings; + + for (const auto &g : recentGamepadGUIDs) + { + SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(g.first.c_str()); + + char *sdlmapping = SDL_GameControllerMappingForGUID(sdlguid); + if (sdlmapping == nullptr) + continue; + + std::string mapping = sdlmapping; + SDL_free(sdlmapping); + + if (mapping.find_last_of(',') != mapping.length() - 1) + mapping += ","; + + // Matches SDL_GameControllerAddMappingsFromRW. + mapping += "platform:" + std::string(SDL_GetPlatform()) + ",\n"; + mappings += mapping; + } + + return mappings; +} + } // sdl } // joystick } // love diff --git a/src/modules/joystick/sdl/JoystickModule.h b/src/modules/joystick/sdl/JoystickModule.h index ba7c8feb1..047fedf60 100644 --- a/src/modules/joystick/sdl/JoystickModule.h +++ b/src/modules/joystick/sdl/JoystickModule.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace love { @@ -56,6 +57,8 @@ public: bool setGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput, Joystick::JoystickInput joyinput); Joystick::JoystickInput getGamepadMapping(const std::string &guid, Joystick::GamepadInput gpinput); + void loadGamepadMappings(const std::string &mappings); + std::string saveGamepadMappings(); private: @@ -74,6 +77,10 @@ private: // Persistent list of all Joysticks which have been connected at some point. std::list joysticks; + // Persistent map indicating GUIDs for Gamepads which have been connected or + // modified at some point. + std::map recentGamepadGUIDs; + }; // JoystickModule } // sdl diff --git a/src/modules/joystick/sdl/wrap_Joystick.cpp b/src/modules/joystick/wrap_Joystick.cpp similarity index 98% rename from src/modules/joystick/sdl/wrap_Joystick.cpp rename to src/modules/joystick/wrap_Joystick.cpp index 90a3f4d3f..02e6484f5 100644 --- a/src/modules/joystick/sdl/wrap_Joystick.cpp +++ b/src/modules/joystick/wrap_Joystick.cpp @@ -28,8 +28,6 @@ namespace love { namespace joystick { -namespace sdl -{ Joystick *luax_checkjoystick(lua_State *L, int idx) { @@ -121,7 +119,7 @@ int w_Joystick_getHat(lua_State *L) Joystick::Hat h = j->getHat(hatindex); const char *direction = ""; - love::joystick::Joystick::getConstant(h, direction); + Joystick::getConstant(h, direction); lua_pushstring(L, direction); return 1; @@ -251,6 +249,7 @@ static const luaL_Reg functions[] = // From wrap_JoystickModule. { "getConnectedIndex", w_getIndex }, { "getGamepadMapping", w_getGamepadMapping }, + { 0, 0 }, }; @@ -259,6 +258,5 @@ extern "C" int luaopen_joystick(lua_State *L) return luax_register_type(L, "Joystick", functions); } -} // sdl } // joystick } // love diff --git a/src/modules/joystick/sdl/wrap_Joystick.h b/src/modules/joystick/wrap_Joystick.h similarity index 94% rename from src/modules/joystick/sdl/wrap_Joystick.h rename to src/modules/joystick/wrap_Joystick.h index 42f446d87..2b9205959 100644 --- a/src/modules/joystick/sdl/wrap_Joystick.h +++ b/src/modules/joystick/wrap_Joystick.h @@ -18,8 +18,8 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#ifndef LOVE_JOYSTICK_SDL_WRAP_JOYSTICK_H -#define LOVE_JOYSTICK_SDL_WRAP_JOYSTICK_H +#ifndef LOVE_JOYSTICK_WRAP_JOYSTICK_H +#define LOVE_JOYSTICK_WRAP_JOYSTICK_H // LOVE #include "common/config.h" @@ -30,8 +30,6 @@ namespace love { namespace joystick { -namespace sdl -{ Joystick *luax_checkjoystick(lua_State *L, int idx); int w_Joystick_isConnected(lua_State *L); @@ -53,7 +51,6 @@ int w_Joystick_setVibration(lua_State *L); int w_Joystick_getVibration(lua_State *L); extern "C" int luaopen_joystick(lua_State *L); -} // sdl } // joystick } // love diff --git a/src/modules/joystick/sdl/wrap_JoystickModule.cpp b/src/modules/joystick/wrap_JoystickModule.cpp similarity index 70% rename from src/modules/joystick/sdl/wrap_JoystickModule.cpp rename to src/modules/joystick/wrap_JoystickModule.cpp index 7a438ff16..2c0d51298 100644 --- a/src/modules/joystick/sdl/wrap_JoystickModule.cpp +++ b/src/modules/joystick/wrap_JoystickModule.cpp @@ -21,12 +21,14 @@ #include "wrap_JoystickModule.h" #include "wrap_Joystick.h" +#include "filesystem/wrap_Filesystem.h" + +#include "sdl/JoystickModule.h" + namespace love { namespace joystick { -namespace sdl -{ static JoystickModule *instance = nullptr; @@ -37,7 +39,7 @@ int w_getJoysticks(lua_State *L) for (int i = 0; i < stickcount; i++) { - love::joystick::Joystick *stick = instance->getJoystick(i); + Joystick *stick = instance->getJoystick(i); stick->retain(); luax_pushtype(L, "Joystick", JOYSTICK_JOYSTICK_T, stick); lua_rawseti(L, -2, i + 1); @@ -48,7 +50,7 @@ int w_getJoysticks(lua_State *L) int w_getIndex(lua_State *L) { - love::joystick::Joystick *j = luax_checkjoystick(L, 1); + Joystick *j = luax_checkjoystick(L, 1); int index = instance->getIndex(j); if (index >= 0) lua_pushinteger(L, index + 1); @@ -73,9 +75,9 @@ int w_setGamepadMapping(lua_State *L) const char *gpbindstr = luaL_checkstring(L, 2); Joystick::GamepadInput gpinput; - if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.axis)) + if (Joystick::getConstant(gpbindstr, gpinput.axis)) gpinput.type = Joystick::INPUT_TYPE_AXIS; - else if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.button)) + else if (Joystick::getConstant(gpbindstr, gpinput.button)) gpinput.type = Joystick::INPUT_TYPE_BUTTON; else return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr); @@ -83,7 +85,7 @@ int w_setGamepadMapping(lua_State *L) const char *jinputtypestr = luaL_checkstring(L, 3); Joystick::JoystickInput jinput; - if (!love::joystick::Joystick::getConstant(jinputtypestr, jinput.type)) + if (!Joystick::getConstant(jinputtypestr, jinput.type)) return luaL_error(L, "Invalid joystick input type: %s", jinputtypestr); const char *hatstr; @@ -99,7 +101,7 @@ int w_setGamepadMapping(lua_State *L) // 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)) + if (!Joystick::getConstant(hatstr, jinput.hat.value)) return luaL_error(L, "Invalid joystick hat: %s", hatstr); break; default: @@ -107,7 +109,7 @@ int w_setGamepadMapping(lua_State *L) } bool success = false; - EXCEPT_GUARD(success = instance->setGamepadMapping(guid, gpinput, jinput);) + luax_catchexcept(L, [&](){ success = instance->setGamepadMapping(guid, gpinput, jinput); }); luax_pushboolean(L, success); return 1; @@ -123,16 +125,16 @@ int w_getGamepadMapping(lua_State *L) guid = luax_checkstring(L, 1); else { - love::joystick::Joystick *stick = luax_checkjoystick(L, 1); + 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)) + if (Joystick::getConstant(gpbindstr, gpinput.axis)) gpinput.type = Joystick::INPUT_TYPE_AXIS; - else if (love::joystick::Joystick::getConstant(gpbindstr, gpinput.button)) + else if (Joystick::getConstant(gpbindstr, gpinput.button)) gpinput.type = Joystick::INPUT_TYPE_BUTTON; else return luaL_error(L, "Invalid gamepad axis/button: %s", gpbindstr); @@ -140,13 +142,13 @@ int w_getGamepadMapping(lua_State *L) Joystick::JoystickInput jinput; jinput.type = Joystick::INPUT_TYPE_MAX_ENUM; - EXCEPT_GUARD(jinput = instance->getGamepadMapping(guid, gpinput);) + luax_catchexcept(L, [&](){ jinput = instance->getGamepadMapping(guid, gpinput); }); if (jinput.type == Joystick::INPUT_TYPE_MAX_ENUM) return 0; const char *inputtypestr; - if (!love::joystick::Joystick::getConstant(jinput.type, inputtypestr)) + if (!Joystick::getConstant(jinput.type, inputtypestr)) return luaL_error(L, "Unknown joystick input type."); lua_pushstring(L, inputtypestr); @@ -162,7 +164,7 @@ int w_getGamepadMapping(lua_State *L) return 2; case Joystick::INPUT_TYPE_HAT: lua_pushinteger(L, jinput.hat.index + 1); - if (love::joystick::Joystick::getConstant(jinput.hat.value, hatstr)) + if (Joystick::getConstant(jinput.hat.value, hatstr)) { lua_pushstring(L, hatstr); return 3; @@ -176,6 +178,48 @@ int w_getGamepadMapping(lua_State *L) return 1; } +int w_loadGamepadMappings(lua_State *L) +{ + lua_pushvalue(L, 1); + luax_convobj(L, -1, "filesystem", "isFile"); + bool isfile = luax_toboolean(L, -1); + lua_pop(L, 1); + + std::string mappings; + + if (isfile) + { + love::filesystem::FileData *fd = love::filesystem::luax_getfiledata(L, 1); + mappings = std::string((const char *) fd->getData(), fd->getSize()); + fd->release(); + + } + else + mappings = luax_checkstring(L, 1); + + luax_catchexcept(L, [&](){ instance->loadGamepadMappings(mappings); }); + return 0; +} + +int w_saveGamepadMappings(lua_State *L) +{ + lua_settop(L, 1); + std::string mappings = instance->saveGamepadMappings(); + + // Optionally write the mappings string to a file. + if (!lua_isnoneornil(L, 1)) + { + luax_pushstring(L, mappings); + int idxs[] = {1, 2}; + luax_convobj(L, idxs, 2, "filesystem", "write"); + lua_pop(L, 1); // Pop the return value. + } + + // Return the actual string even if we also wrote it to a file. + luax_pushstring(L, mappings); + return 1; +} + // List of functions to wrap. static const luaL_Reg functions[] = { @@ -183,6 +227,8 @@ static const luaL_Reg functions[] = { "getJoystickCount", w_getJoystickCount }, { "setGamepadMapping", w_setGamepadMapping }, { "getGamepadMapping", w_getGamepadMapping }, + { "loadGamepadMappings", w_loadGamepadMappings }, + { "saveGamepadMappings", w_saveGamepadMappings }, { 0, 0 } }; @@ -196,7 +242,7 @@ extern "C" int luaopen_love_joystick(lua_State *L) { if (instance == nullptr) { - EXCEPT_GUARD(instance = new JoystickModule();) + luax_catchexcept(L, [&](){ instance = new sdl::JoystickModule(); }); } else instance->retain(); @@ -211,6 +257,5 @@ extern "C" int luaopen_love_joystick(lua_State *L) return luax_register_module(L, w); } -} // sdl } // joystick } // love diff --git a/src/modules/joystick/sdl/wrap_JoystickModule.h b/src/modules/joystick/wrap_JoystickModule.h similarity index 85% rename from src/modules/joystick/sdl/wrap_JoystickModule.h rename to src/modules/joystick/wrap_JoystickModule.h index 24de3264c..5d9223e79 100644 --- a/src/modules/joystick/sdl/wrap_JoystickModule.h +++ b/src/modules/joystick/wrap_JoystickModule.h @@ -18,8 +18,8 @@ * 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 +#ifndef LOVE_JOYSTICK_WRAP_JOYSTICK_MODULE_H +#define LOVE_JOYSTICK_WRAP_JOYSTICK_MODULE_H // LOVE #include "common/config.h" @@ -30,18 +30,17 @@ namespace love { namespace joystick { -namespace sdl -{ int w_getJoysticks(lua_State *L); int w_getIndex(lua_State *L); int w_getJoystickCount(lua_State *L); int w_setGamepadMapping(lua_State *L); int w_getGamepadMapping(lua_State *L); +int w_loadGamepadMappings(lua_State *L); +int w_saveGamepadMappings(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 +#endif // LOVE_JOYSTICK_WRAP_JOYSTICK_MODULE_H diff --git a/src/modules/keyboard/wrap_Keyboard.cpp b/src/modules/keyboard/wrap_Keyboard.cpp index da46ba3d3..de48c52bd 100644 --- a/src/modules/keyboard/wrap_Keyboard.cpp +++ b/src/modules/keyboard/wrap_Keyboard.cpp @@ -68,8 +68,34 @@ int w_setTextInput(lua_State *L) return 0; } +template +static int throwExcept(lua_State *L, const T& func) +{ + bool should_error = false; + + try + { + func(); + } + catch (love::Exception &e) + { + should_error = true; + lua_pushstring(L, e.what()); + } + + if (should_error) + return luaL_error(L, lua_tostring(L, -1)); + + return 0; +} + int w_hasTextInput(lua_State *L) { + bool asdf = true; + throwExcept(L, [&](){ instance->setTextInput(asdf); }); + +// throwExcept(L, L); + luax_pushboolean(L, instance->hasTextInput()); return 1; } @@ -89,7 +115,7 @@ extern "C" int luaopen_love_keyboard(lua_State *L) { if (instance == nullptr) { - EXCEPT_GUARD(instance = new love::keyboard::sdl::Keyboard();) + luax_catchexcept(L, [&](){ instance = new love::keyboard::sdl::Keyboard(); }); } else instance->retain(); diff --git a/src/modules/math/wrap_BezierCurve.cpp b/src/modules/math/wrap_BezierCurve.cpp index 4ab196455..e13d14701 100644 --- a/src/modules/math/wrap_BezierCurve.cpp +++ b/src/modules/math/wrap_BezierCurve.cpp @@ -56,11 +56,11 @@ int w_BezierCurve_getControlPoint(lua_State *L) if (idx > 0) // 1-indexing idx--; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { Vector v = curve->getControlPoint(idx); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); - ) + }); return 2; } @@ -75,7 +75,7 @@ int w_BezierCurve_setControlPoint(lua_State *L) if (idx > 0) // 1-indexing idx--; - EXCEPT_GUARD(curve->setControlPoint(idx, Vector(vx,vy));) + luax_catchexcept(L, [&](){ curve->setControlPoint(idx, Vector(vx,vy)); }); return 0; } @@ -89,7 +89,7 @@ int w_BezierCurve_insertControlPoint(lua_State *L) if (idx > 0) // 1-indexing idx--; - EXCEPT_GUARD(curve->insertControlPoint(Vector(vx,vy), idx);) + luax_catchexcept(L, [&](){ curve->insertControlPoint(Vector(vx,vy), idx); }); return 0; } @@ -134,11 +134,11 @@ int w_BezierCurve_evaluate(lua_State *L) BezierCurve *curve = luax_checkbeziercurve(L, 1); double t = luaL_checknumber(L, 2); - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { Vector v = curve->evaluate(t); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); - ) + }); return 2; @@ -150,7 +150,7 @@ int w_BezierCurve_render(lua_State *L) int accuracy = luaL_optinteger(L, 2, 5); std::vector points; - EXCEPT_GUARD(points = curve->render(accuracy);) + luax_catchexcept(L, [&](){ points = curve->render(accuracy); }); lua_createtable(L, points.size()*2, 0); for (size_t i = 0; i < points.size(); ++i) diff --git a/src/modules/math/wrap_Math.cpp b/src/modules/math/wrap_Math.cpp index 093f30e42..402d7af4f 100644 --- a/src/modules/math/wrap_Math.cpp +++ b/src/modules/math/wrap_Math.cpp @@ -49,7 +49,7 @@ int w_randomNormal(lua_State *L) int w_setRandomSeed(lua_State *L) { - EXCEPT_GUARD(Math::instance.setRandomSeed(luax_checkrandomseed(L, 1));) + luax_catchexcept(L, [&](){ Math::instance.setRandomSeed(luax_checkrandomseed(L, 1)); }); return 0; } @@ -63,7 +63,7 @@ int w_getRandomSeed(lua_State *L) int w_setRandomState(lua_State *L) { - EXCEPT_GUARD(Math::instance.setRandomState(luax_checkstring(L, 1));) + luax_catchexcept(L, [&](){ Math::instance.setRandomState(luax_checkstring(L, 1)); }); return 0; } @@ -180,12 +180,12 @@ int w_triangulate(lua_State *L) std::vector triangles; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { if (vertices.size() == 3) triangles.push_back(Triangle(vertices[0], vertices[1], vertices[2])); else triangles = Math::instance.triangulate(vertices); - ) + }); lua_createtable(L, triangles.size(), 0); for (size_t i = 0; i < triangles.size(); ++i) diff --git a/src/modules/math/wrap_RandomGenerator.cpp b/src/modules/math/wrap_RandomGenerator.cpp index ea029df2a..6935d8591 100644 --- a/src/modules/math/wrap_RandomGenerator.cpp +++ b/src/modules/math/wrap_RandomGenerator.cpp @@ -108,7 +108,7 @@ int w_RandomGenerator_randomNormal(lua_State *L) int w_RandomGenerator_setSeed(lua_State *L) { RandomGenerator *rng = luax_checkrandomgenerator(L, 1); - EXCEPT_GUARD(rng->setSeed(luax_checkrandomseed(L, 2));) + luax_catchexcept(L, [&](){ rng->setSeed(luax_checkrandomseed(L, 2)); }); return 0; } @@ -124,7 +124,7 @@ int w_RandomGenerator_getSeed(lua_State *L) int w_RandomGenerator_setState(lua_State *L) { RandomGenerator *rng = luax_checkrandomgenerator(L, 1); - EXCEPT_GUARD(rng->setState(luax_checkstring(L, 2));) + luax_catchexcept(L, [&](){ rng->setState(luax_checkstring(L, 2)); }); return 0; } diff --git a/src/modules/mouse/wrap_Mouse.cpp b/src/modules/mouse/wrap_Mouse.cpp index ea68f31d3..849117cda 100644 --- a/src/modules/mouse/wrap_Mouse.cpp +++ b/src/modules/mouse/wrap_Mouse.cpp @@ -43,7 +43,7 @@ int w_newCursor(lua_State *L) int hotx = luaL_optint(L, 2, 0); int hoty = luaL_optint(L, 3, 0); - EXCEPT_GUARD(cursor = instance->newCursor(data, hotx, hoty);) + luax_catchexcept(L, [&](){ cursor = instance->newCursor(data, hotx, hoty); }); luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor); return 1; @@ -58,7 +58,7 @@ int w_getSystemCursor(lua_State *L) return luaL_error(L, "Invalid system cursor type: %s", str); Cursor *cursor = 0; - EXCEPT_GUARD(cursor = instance->getSystemCursor(systemCursor);) + luax_catchexcept(L, [&](){ cursor = instance->getSystemCursor(systemCursor); }); cursor->retain(); luax_pushtype(L, "Cursor", MOUSE_CURSOR_T, cursor); @@ -214,7 +214,7 @@ extern "C" int luaopen_love_mouse(lua_State *L) { if (instance == nullptr) { - EXCEPT_GUARD(instance = new love::mouse::sdl::Mouse();) + luax_catchexcept(L, [&](){ instance = new love::mouse::sdl::Mouse(); }); } else instance->retain(); diff --git a/src/modules/physics/box2d/Physics.cpp b/src/modules/physics/box2d/Physics.cpp index a016c7a05..96bc49424 100644 --- a/src/modules/physics/box2d/Physics.cpp +++ b/src/modules/physics/box2d/Physics.cpp @@ -246,7 +246,7 @@ int Physics::getDistance(lua_State *L) b2SimplexCache c; c.count = 0; - EXCEPT_GUARD( + luax_catchexcept(L, [&]() { pA.Set(fixtureA->fixture->GetShape(), 0); pB.Set(fixtureB->fixture->GetShape(), 0); i.proxyA = pA; @@ -255,7 +255,7 @@ int Physics::getDistance(lua_State *L) i.transformB = fixtureB->fixture->GetBody()->GetTransform(); i.useRadii = true; b2Distance(&o, &c, &i); - ) + }); lua_pushnumber(L, Physics::scaleUp(o.distance)); lua_pushnumber(L, Physics::scaleUp(o.pointA.x)); diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index 61eb7529d..f3551030c 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -241,7 +241,7 @@ int w_Body_setX(lua_State *L) { Body *t = luax_checkbody(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setX(arg1);) + luax_catchexcept(L, [&](){ t->setX(arg1); }); return 0; } @@ -249,7 +249,7 @@ int w_Body_setY(lua_State *L) { Body *t = luax_checkbody(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setY(arg1);) + luax_catchexcept(L, [&](){ t->setY(arg1); }); return 0; } @@ -266,7 +266,7 @@ int w_Body_setAngle(lua_State *L) { Body *t = luax_checkbody(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setAngle(arg1);) + luax_catchexcept(L, [&](){ t->setAngle(arg1); }); return 0; } @@ -283,14 +283,14 @@ int w_Body_setPosition(lua_State *L) Body *t = luax_checkbody(L, 1); float arg1 = (float)luaL_checknumber(L, 2); float arg2 = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(t->setPosition(arg1, arg2);) + luax_catchexcept(L, [&](){ t->setPosition(arg1, arg2); }); return 0; } int w_Body_resetMassData(lua_State *L) { Body *t = luax_checkbody(L, 1); - EXCEPT_GUARD(t->resetMassData();) + luax_catchexcept(L, [&](){ t->resetMassData(); }); return 0; } @@ -301,7 +301,7 @@ int w_Body_setMassData(lua_State *L) float y = (float)luaL_checknumber(L, 3); float m = (float)luaL_checknumber(L, 4); float i = (float)luaL_checknumber(L, 5); - EXCEPT_GUARD(t->setMassData(x, y, m, i);) + luax_catchexcept(L, [&](){ t->setMassData(x, y, m, i); }); return 0; } @@ -309,7 +309,7 @@ int w_Body_setMass(lua_State *L) { Body *t = luax_checkbody(L, 1); float m = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setMass(m);) + luax_catchexcept(L, [&](){ t->setMass(m); }); return 0; } @@ -317,7 +317,7 @@ int w_Body_setInertia(lua_State *L) { Body *t = luax_checkbody(L, 1); float i = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setInertia(i);) + luax_catchexcept(L, [&](){ t->setInertia(i); }); return 0; } @@ -351,7 +351,7 @@ int w_Body_setType(lua_State *L) const char *typeStr = luaL_checkstring(L, 2); Body::Type type; Body::getConstant(typeStr, type); - EXCEPT_GUARD(t->setType(type);) + luax_catchexcept(L, [&](){ t->setType(type); }); return 0; } @@ -494,7 +494,7 @@ int w_Body_setActive(lua_State *L) { Body *t = luax_checkbody(L, 1); bool b = luax_toboolean(L, 2); - EXCEPT_GUARD(t->setActive(b);) + luax_catchexcept(L, [&](){ t->setActive(b); }); return 0; } @@ -510,7 +510,7 @@ int w_Body_setFixedRotation(lua_State *L) { Body *t = luax_checkbody(L, 1); bool b = luax_toboolean(L, 2); - EXCEPT_GUARD(t->setFixedRotation(b);) + luax_catchexcept(L, [&](){ t->setFixedRotation(b); }); return 0; } @@ -527,14 +527,14 @@ int w_Body_getFixtureList(lua_State *L) Body *t = luax_checkbody(L, 1); lua_remove(L, 1); int n = 0; - EXCEPT_GUARD(n = t->getFixtureList(L);) + luax_catchexcept(L, [&](){ n = t->getFixtureList(L); }); return n; } int w_Body_destroy(lua_State *L) { Body *t = luax_checkbody(L, 1); - EXCEPT_GUARD(t->destroy();) + luax_catchexcept(L, [&](){ t->destroy(); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_ChainShape.cpp b/src/modules/physics/box2d/wrap_ChainShape.cpp index 245d4c0f4..76a1a5b90 100644 --- a/src/modules/physics/box2d/wrap_ChainShape.cpp +++ b/src/modules/physics/box2d/wrap_ChainShape.cpp @@ -39,7 +39,7 @@ int w_ChainShape_setNextVertex(lua_State *L) ChainShape *c = luax_checkchainshape(L, 1); float x = (float)luaL_checknumber(L, 2); float y = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(c->setNextVertex(x, y);) + luax_catchexcept(L, [&](){ c->setNextVertex(x, y); }); return 0; } @@ -48,7 +48,7 @@ int w_ChainShape_setPreviousVertex(lua_State *L) ChainShape *c = luax_checkchainshape(L, 1); float x = (float)luaL_checknumber(L, 2); float y = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(c->setPreviousVertex(x, y);) + luax_catchexcept(L, [&](){ c->setPreviousVertex(x, y); }); return 0; } @@ -64,7 +64,7 @@ int w_ChainShape_getChildEdge(lua_State *L) ChainShape *c = luax_checkchainshape(L, 1); int index = luaL_checkint(L, 2) - 1; // Convert from 1-based index EdgeShape *e = 0; - EXCEPT_GUARD(e = c->getChildEdge(index);) + luax_catchexcept(L, [&](){ e = c->getChildEdge(index); }); luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, e); return 1; } @@ -82,7 +82,7 @@ int w_ChainShape_getPoint(lua_State *L) ChainShape *c = luax_checkchainshape(L, 1); int index = luaL_checkint(L, 2) - 1; // Convert from 1-based index b2Vec2 v; - EXCEPT_GUARD(v = c->getPoint(index);) + luax_catchexcept(L, [&](){ v = c->getPoint(index); }); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); return 2; diff --git a/src/modules/physics/box2d/wrap_Fixture.cpp b/src/modules/physics/box2d/wrap_Fixture.cpp index 953f68069..621e58bd9 100644 --- a/src/modules/physics/box2d/wrap_Fixture.cpp +++ b/src/modules/physics/box2d/wrap_Fixture.cpp @@ -65,7 +65,7 @@ int w_Fixture_setDensity(lua_State *L) { Fixture *t = luax_checkfixture(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setDensity(arg1);) + luax_catchexcept(L, [&](){ t->setDensity(arg1); }); return 0; } @@ -157,7 +157,7 @@ int w_Fixture_rayCast(lua_State *L) Fixture *t = luax_checkfixture(L, 1); lua_remove(L, 1); int ret = 0; - EXCEPT_GUARD(ret = t->rayCast(L);) + luax_catchexcept(L, [&](){ ret = t->rayCast(L); }); return ret; } @@ -258,7 +258,7 @@ int w_Fixture_setGroupIndex(lua_State *L) int w_Fixture_destroy(lua_State *L) { Fixture *t = luax_checkfixture(L, 1); - EXCEPT_GUARD(t->destroy();) + luax_catchexcept(L, [&](){ t->destroy(); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_FrictionJoint.cpp b/src/modules/physics/box2d/wrap_FrictionJoint.cpp index ce5336fac..7124a8530 100644 --- a/src/modules/physics/box2d/wrap_FrictionJoint.cpp +++ b/src/modules/physics/box2d/wrap_FrictionJoint.cpp @@ -40,7 +40,7 @@ int w_FrictionJoint_setMaxForce(lua_State *L) { FrictionJoint *t = luax_checkfrictionjoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setMaxForce(arg1);) + luax_catchexcept(L, [&](){ t->setMaxForce(arg1); }); return 0; } @@ -55,7 +55,7 @@ int w_FrictionJoint_setMaxTorque(lua_State *L) { FrictionJoint *t = luax_checkfrictionjoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setMaxTorque(arg1);) + luax_catchexcept(L, [&](){ t->setMaxTorque(arg1); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_GearJoint.cpp b/src/modules/physics/box2d/wrap_GearJoint.cpp index e8189f7a2..c6f84114f 100644 --- a/src/modules/physics/box2d/wrap_GearJoint.cpp +++ b/src/modules/physics/box2d/wrap_GearJoint.cpp @@ -40,7 +40,7 @@ int w_GearJoint_setRatio(lua_State *L) { GearJoint *t = luax_checkgearjoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setRatio(arg1);) + luax_catchexcept(L, [&](){ t->setRatio(arg1); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_Joint.cpp b/src/modules/physics/box2d/wrap_Joint.cpp index 259a09b23..053f8b45d 100644 --- a/src/modules/physics/box2d/wrap_Joint.cpp +++ b/src/modules/physics/box2d/wrap_Joint.cpp @@ -78,7 +78,7 @@ int w_Joint_getCollideConnected(lua_State *L) int w_Joint_destroy(lua_State *L) { Joint *t = luax_checkjoint(L, 1); - EXCEPT_GUARD(t->destroyJoint();) + luax_catchexcept(L, [&](){ t->destroyJoint(); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_MotorJoint.cpp b/src/modules/physics/box2d/wrap_MotorJoint.cpp index b264e17a9..4403ddc88 100644 --- a/src/modules/physics/box2d/wrap_MotorJoint.cpp +++ b/src/modules/physics/box2d/wrap_MotorJoint.cpp @@ -69,7 +69,7 @@ int w_MotorJoint_setMaxForce(lua_State *L) { MotorJoint *t = luax_checkmotorjoint(L, 1); float arg1 = (float) luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setMaxForce(arg1);) + luax_catchexcept(L, [&](){ t->setMaxForce(arg1); }); return 0; } @@ -84,7 +84,7 @@ int w_MotorJoint_setMaxTorque(lua_State *L) { MotorJoint *t = luax_checkmotorjoint(L, 1); float arg1 = (float) luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setMaxTorque(arg1);) + luax_catchexcept(L, [&](){ t->setMaxTorque(arg1); }); return 0; } @@ -99,7 +99,7 @@ int w_MotorJoint_setCorrectionFactor(lua_State *L) { MotorJoint *t = luax_checkmotorjoint(L, 1); float arg1 = (float) luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setCorrectionFactor(arg1);) + luax_catchexcept(L, [&](){ t->setCorrectionFactor(arg1); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index b53bb5c78..331e7d2f3 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -58,7 +58,7 @@ int w_newWorld(lua_State *L) bool sleep = luax_optboolean(L, 3, true); World *w; - EXCEPT_GUARD(w = instance->newWorld(gx, gy, sleep);) + luax_catchexcept(L, [&](){ w = instance->newWorld(gx, gy, sleep); }); luax_pushtype(L, "World", PHYSICS_WORLD_T, w); return 1; @@ -76,7 +76,7 @@ int w_newBody(lua_State *L) return luaL_error(L, "Invalid Body type: %s", typestr); Body *body; - EXCEPT_GUARD(body = instance->newBody(world, x, y, btype);) + luax_catchexcept(L, [&](){ body = instance->newBody(world, x, y, btype); }); luax_pushtype(L, "Body", PHYSICS_BODY_T, body); return 1; } @@ -87,7 +87,7 @@ int w_newFixture(lua_State *L) Shape *shape = luax_checkshape(L, 2); float density = (float)luaL_optnumber(L, 3, 1.0f); Fixture *fixture; - EXCEPT_GUARD(fixture = instance->newFixture(body, shape, density);) + luax_catchexcept(L, [&](){ fixture = instance->newFixture(body, shape, density); }); luax_pushtype(L, "Fixture", PHYSICS_FIXTURE_T, fixture); return 1; } @@ -100,7 +100,7 @@ int w_newCircleShape(lua_State *L) { float radius = (float)luaL_checknumber(L, 1); CircleShape *shape; - EXCEPT_GUARD(shape = instance->newCircleShape(radius);) + luax_catchexcept(L, [&](){ shape = instance->newCircleShape(radius); }); luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape); return 1; } @@ -110,7 +110,7 @@ int w_newCircleShape(lua_State *L) float y = (float)luaL_checknumber(L, 2); float radius = (float)luaL_checknumber(L, 3); CircleShape *shape; - EXCEPT_GUARD(shape = instance->newCircleShape(x, y, radius);) + luax_catchexcept(L, [&](){ shape = instance->newCircleShape(x, y, radius); }); luax_pushtype(L, "CircleShape", PHYSICS_CIRCLE_SHAPE_T, shape); return 1; } @@ -127,7 +127,7 @@ int w_newRectangleShape(lua_State *L) float w = (float)luaL_checknumber(L, 1); float h = (float)luaL_checknumber(L, 2); PolygonShape *shape; - EXCEPT_GUARD(shape = instance->newRectangleShape(w, h);) + luax_catchexcept(L, [&](){ shape = instance->newRectangleShape(w, h); }); luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape); return 1; } @@ -139,7 +139,7 @@ int w_newRectangleShape(lua_State *L) float h = (float)luaL_checknumber(L, 4); float angle = (float)luaL_optnumber(L, 5, 0); PolygonShape *shape; - EXCEPT_GUARD(shape = instance->newRectangleShape(x, y, w, h, angle);) + luax_catchexcept(L, [&](){ shape = instance->newRectangleShape(x, y, w, h, angle); }); luax_pushtype(L, "PolygonShape", PHYSICS_POLYGON_SHAPE_T, shape); return 1; } @@ -154,7 +154,7 @@ int w_newEdgeShape(lua_State *L) float x2 = (float)luaL_checknumber(L, 3); float y2 = (float)luaL_checknumber(L, 4); EdgeShape *shape; - EXCEPT_GUARD(shape = instance->newEdgeShape(x1, y1, x2, y2);) + luax_catchexcept(L, [&](){ shape = instance->newEdgeShape(x1, y1, x2, y2); }); luax_pushtype(L, "EdgeShape", PHYSICS_EDGE_SHAPE_T, shape); return 1; } @@ -162,14 +162,14 @@ int w_newEdgeShape(lua_State *L) int w_newPolygonShape(lua_State *L) { int ret = 0; - EXCEPT_GUARD(ret = instance->newPolygonShape(L);) + luax_catchexcept(L, [&](){ ret = instance->newPolygonShape(L); }); return ret; } int w_newChainShape(lua_State *L) { int ret = 0; - EXCEPT_GUARD(ret = instance->newChainShape(L);) + luax_catchexcept(L, [&](){ ret = instance->newChainShape(L); }); return ret; } @@ -183,7 +183,9 @@ int w_newDistanceJoint(lua_State *L) float y2 = (float)luaL_checknumber(L, 6); bool collideConnected = luax_optboolean(L, 7, false); DistanceJoint *j; - EXCEPT_GUARD(j = instance->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newDistanceJoint(body1, body2, x1, y1, x2, y2, collideConnected); + }); luax_pushtype(L, "DistanceJoint", PHYSICS_DISTANCE_JOINT_T, j); return 1; } @@ -194,7 +196,7 @@ int w_newMouseJoint(lua_State *L) float x = (float)luaL_checknumber(L, 2); float y = (float)luaL_checknumber(L, 3); MouseJoint *j; - EXCEPT_GUARD(j = instance->newMouseJoint(body, x, y);) + luax_catchexcept(L, [&](){ j = instance->newMouseJoint(body, x, y); }); luax_pushtype(L, "MouseJoint", PHYSICS_MOUSE_JOINT_T, j); return 1; } @@ -207,7 +209,9 @@ int w_newRevoluteJoint(lua_State *L) float y = (float)luaL_checknumber(L, 4); bool collideConnected = luax_optboolean(L, 5, false); RevoluteJoint *j; - EXCEPT_GUARD(j = instance->newRevoluteJoint(body1, body2, x, y, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newRevoluteJoint(body1, body2, x, y, collideConnected); + }); luax_pushtype(L, "RevoluteJoint", PHYSICS_REVOLUTE_JOINT_T, j); return 1; } @@ -237,7 +241,9 @@ int w_newPrismaticJoint(lua_State *L) collideConnected = luax_optboolean(L, 7, false); } PrismaticJoint *j; - EXCEPT_GUARD(j = instance->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newPrismaticJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected); + }); luax_pushtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, j); return 1; } @@ -258,7 +264,9 @@ int w_newPulleyJoint(lua_State *L) bool collideConnected = luax_optboolean(L, 12, true); // PulleyJoints default to colliding connected bodies, see b2PulleyJoint.h PulleyJoint *j; - EXCEPT_GUARD(j = instance->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio, collideConnected); + }); luax_pushtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, j); return 1; } @@ -271,7 +279,9 @@ int w_newGearJoint(lua_State *L) bool collideConnected = luax_optboolean(L, 4, false); GearJoint *j; - EXCEPT_GUARD(j = instance->newGearJoint(joint1, joint2, ratio, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newGearJoint(joint1, joint2, ratio, collideConnected); + }); luax_pushtype(L, "GearJoint", PHYSICS_GEAR_JOINT_T, j); return 1; } @@ -297,7 +307,9 @@ int w_newFrictionJoint(lua_State *L) collideConnected = luax_optboolean(L, 5, false); } FrictionJoint *j; - EXCEPT_GUARD(j = instance->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newFrictionJoint(body1, body2, xA, yA, xB, yB, collideConnected); + }); luax_pushtype(L, "FrictionJoint", PHYSICS_FRICTION_JOINT_T, j); return 1; } @@ -323,7 +335,9 @@ int w_newWeldJoint(lua_State *L) collideConnected = luax_optboolean(L, 5, false); } WeldJoint *j; - EXCEPT_GUARD(j = instance->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newWeldJoint(body1, body2, xA, yA, xB, yB, collideConnected); + }); luax_pushtype(L, "WeldJoint", PHYSICS_WELD_JOINT_T, j); return 1; } @@ -354,7 +368,9 @@ int w_newWheelJoint(lua_State *L) } WheelJoint *j; - EXCEPT_GUARD(j = instance->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newWheelJoint(body1, body2, xA, yA, xB, yB, ax, ay, collideConnected); + }); luax_pushtype(L, "WheelJoint", PHYSICS_WHEEL_JOINT_T, j); return 1; } @@ -370,7 +386,9 @@ int w_newRopeJoint(lua_State *L) float maxLength = (float)luaL_checknumber(L, 7); bool collideConnected = luax_optboolean(L, 8, false); RopeJoint *j; - EXCEPT_GUARD(j = instance->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected);) + luax_catchexcept(L, [&]() { + j = instance->newRopeJoint(body1, body2, x1, y1, x2, y2, maxLength, collideConnected); + }); luax_pushtype(L, "RopeJoint", PHYSICS_ROPE_JOINT_T, j); return 1; } @@ -383,11 +401,13 @@ int w_newMotorJoint(lua_State *L) if (!lua_isnoneornil(L, 3)) { float correctionFactor = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(j = instance->newMotorJoint(body1, body2, correctionFactor);) + luax_catchexcept(L, [&]() { + j = instance->newMotorJoint(body1, body2, correctionFactor); + }); } else { - EXCEPT_GUARD(j = instance->newMotorJoint(body1, body2);) + luax_catchexcept(L, [&](){ j = instance->newMotorJoint(body1, body2); }); } luax_pushtype(L, "MotorJoint", PHYSICS_MOTOR_JOINT_T, j); return 1; @@ -401,7 +421,7 @@ int w_getDistance(lua_State *L) int w_setMeter(lua_State *L) { int arg1 = luaL_checkint(L, 1); - EXCEPT_GUARD(Physics::setMeter(arg1);) + luax_catchexcept(L, [&](){ Physics::setMeter(arg1); }); return 0; } @@ -469,7 +489,7 @@ extern "C" int luaopen_love_physics(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new Physics();) + luax_catchexcept(L, [&](){ instance = new Physics(); }); } else instance->retain(); diff --git a/src/modules/physics/box2d/wrap_PrismaticJoint.cpp b/src/modules/physics/box2d/wrap_PrismaticJoint.cpp index e3514bf41..ed3b6838f 100644 --- a/src/modules/physics/box2d/wrap_PrismaticJoint.cpp +++ b/src/modules/physics/box2d/wrap_PrismaticJoint.cpp @@ -122,7 +122,7 @@ int w_PrismaticJoint_setUpperLimit(lua_State *L) { PrismaticJoint *t = luax_checkprismaticjoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setUpperLimit(arg1);) + luax_catchexcept(L, [&](){ t->setUpperLimit(arg1); }); return 0; } @@ -130,7 +130,7 @@ int w_PrismaticJoint_setLowerLimit(lua_State *L) { PrismaticJoint *t = luax_checkprismaticjoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setLowerLimit(arg1);) + luax_catchexcept(L, [&](){ t->setLowerLimit(arg1); }); return 0; } @@ -139,7 +139,7 @@ int w_PrismaticJoint_setLimits(lua_State *L) PrismaticJoint *t = luax_checkprismaticjoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); float arg2 = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(t->setLimits(arg1, arg2);) + luax_catchexcept(L, [&](){ t->setLimits(arg1, arg2); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_RevoluteJoint.cpp b/src/modules/physics/box2d/wrap_RevoluteJoint.cpp index e510dcf3b..82203f0ad 100644 --- a/src/modules/physics/box2d/wrap_RevoluteJoint.cpp +++ b/src/modules/physics/box2d/wrap_RevoluteJoint.cpp @@ -122,7 +122,7 @@ int w_RevoluteJoint_setUpperLimit(lua_State *L) { RevoluteJoint *t = luax_checkrevolutejoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setUpperLimit(arg1);) + luax_catchexcept(L, [&](){ t->setUpperLimit(arg1); }); return 0; } @@ -130,7 +130,7 @@ int w_RevoluteJoint_setLowerLimit(lua_State *L) { RevoluteJoint *t = luax_checkrevolutejoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->setLowerLimit(arg1);) + luax_catchexcept(L, [&](){ t->setLowerLimit(arg1); }); return 0; } @@ -139,7 +139,7 @@ int w_RevoluteJoint_setLimits(lua_State *L) RevoluteJoint *t = luax_checkrevolutejoint(L, 1); float arg1 = (float)luaL_checknumber(L, 2); float arg2 = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(t->setLimits(arg1, arg2);) + luax_catchexcept(L, [&](){ t->setLimits(arg1, arg2); }); return 0; } diff --git a/src/modules/physics/box2d/wrap_Shape.cpp b/src/modules/physics/box2d/wrap_Shape.cpp index d31d0fae5..c4d7679ba 100644 --- a/src/modules/physics/box2d/wrap_Shape.cpp +++ b/src/modules/physics/box2d/wrap_Shape.cpp @@ -76,7 +76,7 @@ int w_Shape_rayCast(lua_State *L) Shape *t = luax_checkshape(L, 1); lua_remove(L, 1); int ret = 0; - EXCEPT_GUARD(ret = t->rayCast(L);) + luax_catchexcept(L, [&](){ ret = t->rayCast(L); }); return ret; } diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index fb45ead88..775f6ecf5 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -39,7 +39,7 @@ int w_World_update(lua_State *L) { World *t = luax_checkworld(L, 1); float dt = (float)luaL_checknumber(L, 2); - EXCEPT_GUARD(t->update(dt);) + luax_catchexcept(L, [&](){ t->update(dt); }); return 0; } @@ -92,7 +92,7 @@ int w_World_translateOrigin(lua_State *L) World *t = luax_checkworld(L, 1); float arg1 = (float)luaL_checknumber(L, 2); float arg2 = (float)luaL_checknumber(L, 3); - EXCEPT_GUARD(t->translateOrigin(arg1, arg2);) + luax_catchexcept(L, [&](){ t->translateOrigin(arg1, arg2); }); return 0; } @@ -144,7 +144,7 @@ int w_World_getBodyList(lua_State *L) World *t = luax_checkworld(L, 1); lua_remove(L, 1); int ret = 0; - EXCEPT_GUARD(ret = t->getBodyList(L);) + luax_catchexcept(L, [&](){ ret = t->getBodyList(L); }); return ret; } @@ -153,7 +153,7 @@ int w_World_getJointList(lua_State *L) World *t = luax_checkworld(L, 1); lua_remove(L, 1); int ret = 0; - EXCEPT_GUARD(ret = t->getJointList(L);) + luax_catchexcept(L, [&](){ ret = t->getJointList(L); }); return ret; } @@ -162,7 +162,7 @@ int w_World_getContactList(lua_State *L) World *t = luax_checkworld(L, 1); lua_remove(L, 1); int ret = 0; - EXCEPT_GUARD(ret = t->getContactList(L);) + luax_catchexcept(L, [&](){ ret = t->getContactList(L); }); return ret; } @@ -178,14 +178,14 @@ int w_World_rayCast(lua_State *L) World *t = luax_checkworld(L, 1); lua_remove(L, 1); int ret = 0; - EXCEPT_GUARD(ret = t->rayCast(L);) + luax_catchexcept(L, [&](){ ret = t->rayCast(L); }); return ret; } int w_World_destroy(lua_State *L) { World *t = luax_checkworld(L, 1); - EXCEPT_GUARD(t->destroy();) + luax_catchexcept(L, [&](){ t->destroy(); }); return 0; } diff --git a/src/modules/sound/wrap_Sound.cpp b/src/modules/sound/wrap_Sound.cpp index d91641e00..563e1ae94 100644 --- a/src/modules/sound/wrap_Sound.cpp +++ b/src/modules/sound/wrap_Sound.cpp @@ -20,6 +20,8 @@ #include "wrap_Sound.h" +#include "filesystem/wrap_Filesystem.h" + // Implementations. #include "lullaby/Sound.h" @@ -41,7 +43,7 @@ int w_newSoundData(lua_State *L) int bitDepth = luaL_optint(L, 3, Decoder::DEFAULT_BIT_DEPTH); int channels = luaL_optint(L, 4, Decoder::DEFAULT_CHANNELS); - EXCEPT_GUARD(t = instance->newSoundData(samples, sampleRate, bitDepth, channels);) + luax_catchexcept(L, [&](){ t = instance->newSoundData(samples, sampleRate, bitDepth, channels); }); } // Must be string or decoder. else @@ -53,7 +55,7 @@ int w_newSoundData(lua_State *L) lua_replace(L, 1); } - EXCEPT_GUARD(t = instance->newSoundData(luax_checkdecoder(L, 1));) + luax_catchexcept(L, [&](){ t = instance->newSoundData(luax_checkdecoder(L, 1)); }); } luax_pushtype(L, "SoundData", SOUND_SOUND_DATA_T, t); @@ -62,18 +64,16 @@ int w_newSoundData(lua_State *L) int w_newDecoder(lua_State *L) { - // Convert to FileData, if necessary. - if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) - luax_convobj(L, 1, "filesystem", "newFileData"); - - love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); - + love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1); int bufferSize = luaL_optint(L, 2, Decoder::DEFAULT_BUFFER_SIZE); - Decoder *t = 0; - EXCEPT_GUARD(t = instance->newDecoder(data, bufferSize);) + Decoder *t = nullptr; + luax_catchexcept(L, + [&]() { t = instance->newDecoder(data, bufferSize); }, + [&]() { data->release(); } + ); - if (t == 0) + if (t == nullptr) return luaL_error(L, "Extension \"%s\" not supported.", data->getExtension().c_str()); luax_pushtype(L, "Decoder", SOUND_DECODER_T, t); @@ -99,7 +99,7 @@ extern "C" int luaopen_love_sound(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new lullaby::Sound();) + luax_catchexcept(L, [&](){ instance = new lullaby::Sound(); }); } else instance->retain(); diff --git a/src/modules/sound/wrap_SoundData.cpp b/src/modules/sound/wrap_SoundData.cpp index 1c5d26a99..dee6db00e 100644 --- a/src/modules/sound/wrap_SoundData.cpp +++ b/src/modules/sound/wrap_SoundData.cpp @@ -73,7 +73,7 @@ int w_SoundData_setSample(lua_State *L) int i = (int) luaL_checkinteger(L, 2); float sample = (float) luaL_checknumber(L, 3); - EXCEPT_GUARD(sd->setSample(i, sample);) + luax_catchexcept(L, [&](){ sd->setSample(i, sample); }); return 0; } @@ -82,7 +82,7 @@ int w_SoundData_getSample(lua_State *L) SoundData *sd = luax_checksounddata(L, 1); int i = (int) luaL_checkinteger(L, 2); - EXCEPT_GUARD(lua_pushnumber(L, sd->getSample(i));) + luax_catchexcept(L, [&](){ lua_pushnumber(L, sd->getSample(i)); }); return 1; } diff --git a/src/modules/thread/wrap_ThreadModule.cpp b/src/modules/thread/wrap_ThreadModule.cpp index c90fb9a6b..58b644959 100644 --- a/src/modules/thread/wrap_ThreadModule.cpp +++ b/src/modules/thread/wrap_ThreadModule.cpp @@ -91,7 +91,7 @@ extern "C" int luaopen_love_thread(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new love::thread::ThreadModule();) + luax_catchexcept(L, [&](){ instance = new love::thread::ThreadModule(); }); } else instance->retain(); diff --git a/src/modules/timer/wrap_Timer.cpp b/src/modules/timer/wrap_Timer.cpp index 247ae1922..701bc6566 100644 --- a/src/modules/timer/wrap_Timer.cpp +++ b/src/modules/timer/wrap_Timer.cpp @@ -85,7 +85,7 @@ extern "C" int luaopen_love_timer(lua_State *L) { if (instance == 0) { - EXCEPT_GUARD(instance = new love::timer::sdl::Timer();) + luax_catchexcept(L, [&](){ instance = new love::timer::sdl::Timer(); }); } else instance->retain(); diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index fad379785..f7c72d68f 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -101,7 +101,10 @@ int w_setMode(lua_State *L) // Display index is 1-based in Lua and 0-based internally. settings.display--; - EXCEPT_GUARD(luax_pushboolean(L, instance->setWindow(w, h, &settings));) + luax_catchexcept(L, + [&](){ luax_pushboolean(L, instance->setWindow(w, h, &settings)); } + ); + return 1; } @@ -317,7 +320,7 @@ static const luaL_Reg functions[] = extern "C" int luaopen_love_window(lua_State *L) { - EXCEPT_GUARD(instance = sdl::Window::createSingleton();) + luax_catchexcept(L, [&](){ instance = sdl::Window::createSingleton(); }); WrappedModule w; w.module = instance; diff --git a/src/scripts/graphics.lua b/src/scripts/graphics.lua index 80cef656d..95bb8f236 100644 --- a/src/scripts/graphics.lua +++ b/src/scripts/graphics.lua @@ -1387,13 +1387,14 @@ void main() { end local function isVertexCode(code) - return code:match("vec4%s*position%(") ~= nil + return code:match("vec4%s+position%s*%(") ~= nil end local function isPixelCode(code) - if code:match("vec4%s*effect%(") then + if code:match("vec4%s+effect%s*%(") then return true - elseif code:match("void%s*effects%(") then -- render to multiple canvases simultaniously + elseif code:match("void%s+effects%s*%(") then + -- function for rendering to multiple canvases simultaneously return true, true else return false @@ -1405,14 +1406,11 @@ void main() { local is_multicanvas = false -- whether pixel code has "effects" function instead of "effect" if arg1 then - local s = arg1:gsub("\r\n\t", " ") -- convert whitespace to spaces for parsing - s = s:gsub("(%w+)(%s+)%(", "%1(") -- convert "func ()" to "func()" - - if isVertexCode(s) then + if isVertexCode(arg1) then vertexcode = arg1 -- first arg contains vertex shader code end - local ispixel, isMultiCanvas = isPixelCode(s) + local ispixel, isMultiCanvas = isPixelCode(arg1) if ispixel then pixelcode = arg1 -- first arg contains pixel shader code is_multicanvas = isMultiCanvas @@ -1420,14 +1418,11 @@ void main() { end if arg2 then - local s = arg2:gsub("\r\n\t", " ") -- convert whitespace to spaces for parsing - s = s:gsub("(%w+)(%s+)%(", "%1(") -- convert "func ()" to "func()" - - if isVertexCode(s) then + if isVertexCode(arg2) then vertexcode = arg2 -- second arg contains vertex shader code end - local ispixel, isMultiCanvas = isPixelCode(s) + local ispixel, isMultiCanvas = isPixelCode(arg2) if ispixel then pixelcode = arg2 -- second arg contains pixel shader code is_multicanvas = isMultiCanvas diff --git a/src/scripts/graphics.lua.h b/src/scripts/graphics.lua.h index 0b9c7d48a..6a3463cc6 100644 --- a/src/scripts/graphics.lua.h +++ b/src/scripts/graphics.lua.h @@ -6444,20 +6444,22 @@ const unsigned char graphics_lua[] = 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x28, 0x22, 0x76, 0x65, 0x63, 0x34, 0x25, 0x73, 0x2a, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x25, 0x28, 0x22, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, + 0x68, 0x28, 0x22, 0x76, 0x65, 0x63, 0x34, 0x25, 0x73, 0x2b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x25, 0x73, 0x2a, 0x25, 0x28, 0x22, 0x29, 0x20, 0x7e, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x22, 0x76, - 0x65, 0x63, 0x34, 0x25, 0x73, 0x2a, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x25, 0x28, 0x22, 0x29, 0x20, 0x74, - 0x68, 0x65, 0x6e, 0x0a, + 0x65, 0x63, 0x34, 0x25, 0x73, 0x2b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x25, 0x73, 0x2a, 0x25, 0x28, 0x22, + 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x6d, 0x61, 0x74, 0x63, - 0x68, 0x28, 0x22, 0x76, 0x6f, 0x69, 0x64, 0x25, 0x73, 0x2a, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x73, 0x25, - 0x28, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x76, 0x61, - 0x73, 0x65, 0x73, 0x20, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x74, 0x61, 0x6e, 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x0a, + 0x68, 0x28, 0x22, 0x76, 0x6f, 0x69, 0x64, 0x25, 0x73, 0x2b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x73, 0x25, + 0x73, 0x2a, 0x25, 0x28, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, + 0x09, 0x09, 0x09, 0x2d, 0x2d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x65, 0x73, 0x20, 0x73, 0x69, 0x6d, 0x75, + 0x6c, 0x74, 0x61, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0a, @@ -6477,17 +6479,8 @@ const unsigned char graphics_lua[] = 0x66, 0x65, 0x63, 0x74, 0x22, 0x0a, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x61, 0x72, 0x67, 0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, - 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x31, 0x3a, - 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x72, 0x5c, 0x6e, 0x5c, 0x74, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, - 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x70, 0x61, 0x72, 0x73, 0x69, 0x6e, 0x67, 0x0a, - 0x09, 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x28, 0x25, 0x77, - 0x2b, 0x29, 0x28, 0x25, 0x73, 0x2b, 0x29, 0x25, 0x28, 0x22, 0x2c, 0x20, 0x22, 0x25, 0x31, 0x28, 0x22, 0x29, - 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x20, - 0x28, 0x29, 0x22, 0x20, 0x74, 0x6f, 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x29, 0x22, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x69, 0x73, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, - 0x28, 0x73, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, + 0x28, 0x61, 0x72, 0x67, 0x31, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x31, 0x20, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x73, 0x68, 0x61, @@ -6495,7 +6488,7 @@ const unsigned char graphics_lua[] = 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x69, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x20, 0x3d, 0x20, 0x69, 0x73, - 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x73, 0x29, 0x0a, + 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x61, 0x72, 0x67, 0x31, 0x29, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x69, 0x73, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x31, 0x20, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x61, 0x72, 0x67, 0x20, 0x63, 0x6f, @@ -6507,17 +6500,8 @@ const unsigned char graphics_lua[] = 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x09, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x61, 0x72, 0x67, 0x32, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, - 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x32, 0x3a, - 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x5c, 0x72, 0x5c, 0x6e, 0x5c, 0x74, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, - 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x70, 0x61, 0x72, 0x73, 0x69, 0x6e, 0x67, 0x0a, - 0x09, 0x09, 0x09, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x22, 0x28, 0x25, 0x77, - 0x2b, 0x29, 0x28, 0x25, 0x73, 0x2b, 0x29, 0x25, 0x28, 0x22, 0x2c, 0x20, 0x22, 0x25, 0x31, 0x28, 0x22, 0x29, - 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x20, - 0x28, 0x29, 0x22, 0x20, 0x74, 0x6f, 0x20, 0x22, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x29, 0x22, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x69, 0x73, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x64, 0x65, - 0x28, 0x73, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, + 0x28, 0x61, 0x72, 0x67, 0x32, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x32, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x73, 0x68, @@ -6525,7 +6509,7 @@ const unsigned char graphics_lua[] = 0x09, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x69, 0x73, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x20, 0x3d, 0x20, 0x69, 0x73, - 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x73, 0x29, 0x0a, + 0x50, 0x69, 0x78, 0x65, 0x6c, 0x43, 0x6f, 0x64, 0x65, 0x28, 0x61, 0x72, 0x67, 0x32, 0x29, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x69, 0x73, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x72, 0x67, 0x32, 0x20, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x67, 0x20, 0x63,