diff --git a/CMakeLists.txt b/CMakeLists.txt index 96a108fca..b3909077c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,8 @@ set(LOVE_SRC_COMMON src/common/Data.h src/common/delay.cpp src/common/delay.h + src/common/deprecation.cpp + src/common/deprecation.h src/common/EnumMap.h src/common/Exception.cpp src/common/Exception.h @@ -477,6 +479,8 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT src/modules/graphics/Canvas.h src/modules/graphics/depthstencil.cpp src/modules/graphics/depthstencil.h + src/modules/graphics/Deprecations.cpp + src/modules/graphics/Deprecations.h src/modules/graphics/Drawable.cpp src/modules/graphics/Drawable.h src/modules/graphics/Font.cpp diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 70de09544..bf20dd1d7 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -935,10 +935,16 @@ FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; }; FA91591F1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; }; FA9159201CF1ED7500A7053F /* halffloat.h in Headers */ = {isa = PBXBuildFile; fileRef = FA91591D1CF1ED7500A7053F /* halffloat.h */; }; + FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91DA891F377C3900C80E33 /* deprecation.cpp */; }; + FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91DA891F377C3900C80E33 /* deprecation.cpp */; }; + FA91DA8D1F377C3900C80E33 /* deprecation.h in Headers */ = {isa = PBXBuildFile; fileRef = FA91DA8A1F377C3900C80E33 /* deprecation.h */; }; FA93C4521F315B960087CCD4 /* CompressedFormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA93C44F1F315B960087CCD4 /* CompressedFormatHandler.h */; }; FA93C4531F315B960087CCD4 /* FormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA93C4501F315B960087CCD4 /* FormatHandler.h */; }; FA93C4541F315B960087CCD4 /* FormatHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA93C4511F315B960087CCD4 /* FormatHandler.cpp */; }; FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; }; + FA9D53AC1F5307E900125C6B /* Deprecations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D53AA1F5307E900125C6B /* Deprecations.cpp */; }; + FA9D53AD1F5307E900125C6B /* Deprecations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D53AA1F5307E900125C6B /* Deprecations.cpp */; }; + FA9D53AE1F5307E900125C6B /* Deprecations.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9D53AB1F5307E900125C6B /* Deprecations.h */; }; FA9D8DD11DEB56C3002CD881 /* pixelformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */; }; FA9D8DD21DEB56C3002CD881 /* pixelformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */; }; FA9D8DD31DEB56C3002CD881 /* pixelformat.h in Headers */ = {isa = PBXBuildFile; fileRef = FA9D8DD01DEB56C3002CD881 /* pixelformat.h */; }; @@ -1793,10 +1799,14 @@ FA8951A11AA2EDF300EC385A /* wrap_Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = ""; }; FA91591C1CF1ED7500A7053F /* halffloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = halffloat.cpp; sourceTree = ""; }; FA91591D1CF1ED7500A7053F /* halffloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halffloat.h; sourceTree = ""; }; + FA91DA891F377C3900C80E33 /* deprecation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = deprecation.cpp; sourceTree = ""; }; + FA91DA8A1F377C3900C80E33 /* deprecation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = deprecation.h; sourceTree = ""; }; FA93C44F1F315B960087CCD4 /* CompressedFormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedFormatHandler.h; sourceTree = ""; }; FA93C4501F315B960087CCD4 /* FormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatHandler.h; sourceTree = ""; }; FA93C4511F315B960087CCD4 /* FormatHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatHandler.cpp; sourceTree = ""; }; FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = ""; }; + FA9D53AA1F5307E900125C6B /* Deprecations.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Deprecations.cpp; sourceTree = ""; }; + FA9D53AB1F5307E900125C6B /* Deprecations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Deprecations.h; sourceTree = ""; }; FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pixelformat.cpp; sourceTree = ""; }; FA9D8DD01DEB56C3002CD881 /* pixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixelformat.h; sourceTree = ""; }; FA9D8DD41DEF8411002CD881 /* Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Data.cpp; sourceTree = ""; }; @@ -2025,6 +2035,8 @@ FA0B78FA1A958E3B000E1D17 /* Data.h */, FA0B78FB1A958E3B000E1D17 /* delay.cpp */, FA0B78FC1A958E3B000E1D17 /* delay.h */, + FA91DA891F377C3900C80E33 /* deprecation.cpp */, + FA91DA8A1F377C3900C80E33 /* deprecation.h */, FA0B78FD1A958E3B000E1D17 /* EnumMap.h */, FA0B78FE1A958E3B000E1D17 /* Exception.cpp */, FA0B78FF1A958E3B000E1D17 /* Exception.h */, @@ -2651,6 +2663,8 @@ FADF53F71E3C7ACD00012CC0 /* Buffer.h */, FA1BA0A51E16F20600AA2803 /* Canvas.cpp */, FA1BA0A61E16F20600AA2803 /* Canvas.h */, + FA9D53AA1F5307E900125C6B /* Deprecations.cpp */, + FA9D53AB1F5307E900125C6B /* Deprecations.h */, FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */, FAF1889D1E9DBBC8008C1479 /* depthstencil.h */, FA9D8DDC1DEF842A002CD881 /* Drawable.cpp */, @@ -3740,6 +3754,7 @@ FA0B7D2A1A95902C000E1D17 /* wrap_GlyphData.h in Headers */, FA0B7E741A95902C000E1D17 /* wrap_Shape.h in Headers */, FA0B7A5D1A958EA3000E1D17 /* b2Timer.h in Headers */, + FA91DA8D1F377C3900C80E33 /* deprecation.h in Headers */, FA0B7A4A1A958EA3000E1D17 /* b2Shape.h in Headers */, FAF1407F1E20934C00F898D2 /* localintermediate.h in Headers */, FAF1406B1E20934C00F898D2 /* glslang_tab.cpp.h in Headers */, @@ -3777,6 +3792,7 @@ FA0B7E2C1A95902C000E1D17 /* RevoluteJoint.h in Headers */, FA8951A41AA2EDF300EC385A /* wrap_Event.h in Headers */, FA0B7B2A1A958EA3000E1D17 /* simplexnoise1234.h in Headers */, + FA9D53AE1F5307E900125C6B /* Deprecations.h in Headers */, FA0B7ADC1A958EA3000E1D17 /* glad.hpp in Headers */, FA0B7CF91A95902C000E1D17 /* FileData.h in Headers */, FA0B7DA71A95902C000E1D17 /* PNGHandler.h in Headers */, @@ -4024,6 +4040,7 @@ FA0B7DB81A95902C000E1D17 /* Joystick.cpp in Sources */, FA0B794B1A958E3B000E1D17 /* wrap_Data.cpp in Sources */, FAB17BEC1ABFAF1800F9BA27 /* CompressedData.cpp in Sources */, + FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */, FA0B7E401A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */, FA0B7DEC1A95902C000E1D17 /* Cursor.cpp in Sources */, FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */, @@ -4078,6 +4095,7 @@ FA0B7D3D1A95902C000E1D17 /* Image.cpp in Sources */, FA0B7B351A958EA3000E1D17 /* wuff_convert.c in Sources */, FAF140941E20934C00F898D2 /* PpScanner.cpp in Sources */, + FA9D53AD1F5307E900125C6B /* Deprecations.cpp in Sources */, FA0B7E431A95902C000E1D17 /* wrap_CircleShape.cpp in Sources */, FA0B7CE61A95902C000E1D17 /* wrap_Source.cpp in Sources */, FA0B7AA21A958EA3000E1D17 /* b2PulleyJoint.cpp in Sources */, @@ -4381,6 +4399,7 @@ FA0B7DB71A95902C000E1D17 /* Joystick.cpp in Sources */, FA0B7A321A958EA3000E1D17 /* b2Collision.cpp in Sources */, FAB17BEB1ABFAF1800F9BA27 /* CompressedData.cpp in Sources */, + FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */, FA0B7E3F1A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */, FA0B7DEB1A95902C000E1D17 /* Cursor.cpp in Sources */, FA0B7D861A95902C000E1D17 /* ImageData.cpp in Sources */, @@ -4435,6 +4454,7 @@ FA0B7CE51A95902C000E1D17 /* wrap_Source.cpp in Sources */, FA0B792C1A958E3B000E1D17 /* Memoizer.cpp in Sources */, FAF140931E20934C00F898D2 /* PpScanner.cpp in Sources */, + FA9D53AC1F5307E900125C6B /* Deprecations.cpp in Sources */, FA0B7CCD1A95902C000E1D17 /* Audio.cpp in Sources */, FA0B7DCA1A95902C000E1D17 /* Keyboard.cpp in Sources */, FA0B7AA41A958EA3000E1D17 /* b2RevoluteJoint.cpp in Sources */, diff --git a/src/common/Module.cpp b/src/common/Module.cpp index 896303bd1..006520aeb 100644 --- a/src/common/Module.cpp +++ b/src/common/Module.cpp @@ -21,6 +21,7 @@ // LOVE #include "Module.h" #include "Exception.h" +#include "deprecation.h" // std #include @@ -61,6 +62,11 @@ namespace love love::Type Module::type("Module", &Object::type); Module *Module::instances[] = {}; +Module::Module() +{ + initDeprecation(); +} + Module::~Module() { ModuleRegistry ®istry = registryInstance(); @@ -83,6 +89,8 @@ Module::~Module() } freeEmptyRegistry(); + + deinitDeprecation(); } void Module::registerInstance(Module *instance) diff --git a/src/common/Module.h b/src/common/Module.h index d7e6708ff..ba839e833 100644 --- a/src/common/Module.h +++ b/src/common/Module.h @@ -59,6 +59,7 @@ public: M_MAX_ENUM }; + Module(); virtual ~Module(); /** diff --git a/src/common/deprecation.cpp b/src/common/deprecation.cpp new file mode 100644 index 000000000..33bfdd331 --- /dev/null +++ b/src/common/deprecation.cpp @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2006-2017 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. + **/ + +#include "common/config.h" +#include "deprecation.h" +#include "thread/threads.h" + +#include +#include + +namespace love +{ + +static std::map deprecated; +static std::vector deprecatedList; + +static std::atomic initCount; + +static thread::Mutex *mutex = nullptr; +static bool outputEnabled = false; + +void initDeprecation() +{ + if (initCount.fetch_add(1) == 0) + mutex = thread::newMutex(); +} + +void deinitDeprecation() +{ + if (initCount.fetch_sub(1) == 1) + { + deprecatedList.clear(); + deprecated.clear(); + + delete mutex; + mutex = nullptr; + } +} + +static void printDeprecationNotice(const DeprecationInfo &info) +{ + std::string notice = getDeprecationNotice(info, true); + printf("LOVE - Warning: %s\n", notice.c_str()); +} + +void setDeprecationOutputEnabled(bool enable) +{ + if (enable == outputEnabled) + return; + + outputEnabled = enable; + + if (enable) + { + GetDeprecated deprecated; + + for (const DeprecationInfo *info : deprecated.all) + { + if (info->uses == 1) + printDeprecationNotice(*info); + } + } +} + +std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere) +{ + std::string notice; + + if (usewhere) + notice += info.where; + + notice += "Using deprecated function " + info.name; + + if (info.type == DEPRECATED_REPLACEMENT && !info.replacement.empty()) + notice += " (replaced by " + info.replacement + ")"; + else if (info.type == DEPRECATED_RENAMED && !info.replacement.empty()) + notice += " (renamed to " + info.replacement + ")"; + + return notice; +} + +GetDeprecated::GetDeprecated() + : all(deprecatedList) +{ + if (mutex != nullptr) + mutex->lock(); +} + +GetDeprecated::~GetDeprecated() +{ + if (mutex != nullptr) + mutex->unlock(); +} + +MarkDeprecated::MarkDeprecated(const char *name) + : MarkDeprecated(name, DEPRECATED_NO_REPLACEMENT, nullptr) +{ +} + +MarkDeprecated::MarkDeprecated(const char *name, DeprecationType type, const char *replacement) + : info(nullptr) +{ + if (mutex != nullptr) + mutex->lock(); + + auto it = deprecated.find(name); + + if (it != deprecated.end()) + { + it->second.uses++; + info = &it->second; + } + else + { + DeprecationInfo newinfo = {}; + + newinfo.type = type; + newinfo.uses = 1; + newinfo.name = name; + + if (replacement != nullptr) + newinfo.replacement = replacement; + + auto inserted = deprecated.insert(std::make_pair(newinfo.name, newinfo)); + + info = &inserted.first->second; + deprecatedList.push_back(info); + } +} + +MarkDeprecated::~MarkDeprecated() +{ + if (outputEnabled && info != nullptr && info->uses == 1) + printDeprecationNotice(*info); + + if (mutex != nullptr) + mutex->unlock(); +} + +} // love diff --git a/src/common/deprecation.h b/src/common/deprecation.h new file mode 100644 index 000000000..1efad5f41 --- /dev/null +++ b/src/common/deprecation.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2006-2017 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. + **/ + +#pragma once + +#include "int.h" + +#include +#include + +namespace love +{ + +enum DeprecationType +{ + DEPRECATED_NO_REPLACEMENT, + DEPRECATED_REPLACEMENT, + DEPRECATED_RENAMED, +}; + +struct DeprecationInfo +{ + DeprecationType type; + int64 uses; + std::string name; + std::string replacement; + std::string where; +}; + +void initDeprecation(); +void deinitDeprecation(); + +void setDeprecationOutputEnabled(bool enable); +bool isDeprecationOutputEnabled(); + +std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere); + +struct GetDeprecated +{ + GetDeprecated(); + ~GetDeprecated(); + + const std::vector &all; +}; + +struct MarkDeprecated +{ + MarkDeprecated(const char *name); + MarkDeprecated(const char *name, DeprecationType type, const char *replacement); + ~MarkDeprecated(); + + DeprecationInfo *info; +}; + +} // love diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index cccbdc735..a9291fed5 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -786,6 +786,25 @@ lua_State *luax_getpinnedthread(lua_State *L) return thread; } +void luax_markdeprecated(lua_State *L, const char *name) +{ + luax_markdeprecated(L, name, DEPRECATED_NO_REPLACEMENT, nullptr); +} + +void luax_markdeprecated(lua_State *L, const char *name, DeprecationType type, const char *replacement) +{ + MarkDeprecated deprecated(name, type, replacement); + + if (deprecated.info != nullptr && deprecated.info->uses == 1) + { + luaL_where(L, 1); + const char *where = lua_tostring(L, -1); + if (where != nullptr) + deprecated.info->where = where; + lua_pop(L, 1); + } +} + extern "C" int luax_typerror(lua_State *L, int narg, const char *tname) { int argtype = lua_type(L, narg); diff --git a/src/common/runtime.h b/src/common/runtime.h index 569dc5274..fa9ed834b 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -23,6 +23,7 @@ // LOVE #include "types.h" +#include "deprecation.h" // Lua extern "C" { @@ -447,6 +448,13 @@ lua_State *luax_insistpinnedthread(lua_State *L); **/ lua_State *luax_getpinnedthread(lua_State *L); +/** + * Mark a function as deprecated. Should only be called inside wrapper function + * code. + **/ +void luax_markdeprecated(lua_State *L, const char *name); +void luax_markdeprecated(lua_State *L, const char *name, DeprecationType type, const char *replacement); + extern "C" { // Also called from luasocket int luax_typerror(lua_State *L, int narg, const char *tname); } diff --git a/src/modules/graphics/Deprecations.cpp b/src/modules/graphics/Deprecations.cpp new file mode 100644 index 000000000..70b8e60a4 --- /dev/null +++ b/src/modules/graphics/Deprecations.cpp @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2006-2017 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. + **/ + +#include "common/config.h" +#include "Deprecations.h" +#include "Graphics.h" +#include "Font.h" +#include "common/deprecation.h" +#include "timer/Timer.h" + +#include + +namespace love +{ +namespace graphics +{ + +Deprecations::Deprecations() + : currentDeprecationCount(0) + , lastUpdatedTime(0.0) +{ +} + +Deprecations::~Deprecations() +{ +} + +void Deprecations::draw(Graphics *gfx) +{ + GetDeprecated deprecations; + + if (deprecations.all.empty()) + return; + + int total = (int) deprecations.all.size(); + + if (total != currentDeprecationCount) + { + currentDeprecationCount = total; + lastUpdatedTime = timer::Timer::getTime(); + } + + double showTime = 20.0; + double fadeTime = 1.0; + + double delta = timer::Timer::getTime() - lastUpdatedTime; + + float alpha = 1.0f; + if (delta > (showTime - fadeTime)) + alpha = (float) (1.0 - (delta - showTime - fadeTime) / fadeTime); + + if (alpha <= 0.0f) + return; + + if (font.get() == nullptr) + { + auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL; + + if (!isGammaCorrect() && gfx->getScreenPixelDensity() <= 1.0) + hinting = font::TrueTypeRasterizer::HINTING_LIGHT; + + font.set(gfx->newDefaultFont(9, hinting), Acquire::NORETAIN); + } + + gfx->flushStreamDraws(); + + gfx->push(Graphics::STACK_ALL); + gfx->reset(); + + int maxcount = 4; + int remaining = std::max(0, total - maxcount); + + std::vector strings; + Colorf white(1, 1, 1, 1); + + // Grab the newest deprecation notices first. + for (int i = total - 1; i >= remaining; --i) + { + if (!strings.empty()) + strings.back().str += "\n"; + + const DeprecationInfo *info = deprecations.all[i]; + strings.push_back({getDeprecationNotice(*info, true), white}); + } + + if (remaining > 0) + strings.push_back({"\n(And " + std::to_string(remaining) + " more)", white}); + + int padding = 5; + int width = 600; + + for (const auto &coloredstr : strings) + width = std::max(width, font->getWidth(coloredstr.str) + padding * 2); + + float wraplimit = std::min(gfx->getWidth(), width - padding * 2); + + std::vector wrappedlines; + font->getWrap(strings, wraplimit, wrappedlines); + + int linecount = std::min((int) wrappedlines.size(), maxcount); + int height = font->getHeight() * linecount + padding * 2; + + int x = 0; + int y = std::max(gfx->getHeight() - height, 0); + + gfx->setColor(Colorf(0, 0, 0, 0.85 * alpha)); + gfx->rectangle(Graphics::DRAW_FILL, x, y, width, height); + + gfx->setColor(Colorf(1, 0.9, 0.8, 1 * alpha)); + gfx->setScissor({x, y, width, height}); + + Matrix4 textm(x + padding, y + padding, 0, 1, 1, 0, 0, 0, 0); + gfx->printf(strings, font.get(), wraplimit, Font::ALIGN_LEFT, textm); + + gfx->pop(); +} + +} // graphics +} // love diff --git a/src/modules/graphics/Deprecations.h b/src/modules/graphics/Deprecations.h new file mode 100644 index 000000000..5aa9b79d5 --- /dev/null +++ b/src/modules/graphics/Deprecations.h @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2006-2017 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. + **/ + +#pragma once + +#include "common/Object.h" + +namespace love +{ +namespace graphics +{ + +class Graphics; +class Font; + +class Deprecations +{ +public: + + Deprecations(); + ~Deprecations(); + + void draw(Graphics *gfx); + +private: + + int currentDeprecationCount; + double lastUpdatedTime; + StrongRef font; + +}; // Deprecations + +} // graphics +} // love diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 296bd7b28..12e43992e 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -27,6 +27,7 @@ #include "window/Window.h" #include "Font.h" #include "Video.h" +#include "common/deprecation.h" // C++ #include @@ -157,6 +158,16 @@ Font *Graphics::newFont(love::font::Rasterizer *data, const Texture::Filter &fil return new Font(data, filter); } +Font *Graphics::newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting, const Texture::Filter &filter) +{ + auto fontmodule = Module::getInstance(M_FONT); + if (!fontmodule) + throw love::Exception("Font module has not been loaded."); + + StrongRef r(fontmodule->newTrueTypeRasterizer(size, hinting), Acquire::NORETAIN); + return newFont(r.get(), filter); +} + Video *Graphics::newVideo(love::video::VideoStream *stream, float pixeldensity) { return new Video(this, stream, pixeldensity); @@ -357,16 +368,7 @@ void Graphics::checkSetDefaultFont() // Create a new default font if we don't have one yet. if (!defaultFont.get()) - { - auto fontmodule = Module::getInstance(M_FONT); - if (!fontmodule) - throw love::Exception("Font module has not been loaded."); - - auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL; - StrongRef r(fontmodule->newTrueTypeRasterizer(12, hinting), Acquire::NORETAIN); - - defaultFont.set(newFont(r.get()), Acquire::NORETAIN); - } + defaultFont.set(newDefaultFont(12, font::TrueTypeRasterizer::HINTING_NORMAL), Acquire::NORETAIN); states.back().font.set(defaultFont.get()); } diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 62be58800..33ca4c59e 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -38,9 +38,11 @@ #include "Quad.h" #include "Mesh.h" #include "Image.h" +#include "Deprecations.h" #include "depthstencil.h" #include "math/Transform.h" #include "font/Rasterizer.h" +#include "font/Font.h" #include "video/VideoStream.h" // C++ @@ -369,6 +371,7 @@ public: Quad *newQuad(Quad::Viewport v, double sw, double sh); Font *newFont(love::font::Rasterizer *data, const Texture::Filter &filter = Texture::defaultFilter); + Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting, const Texture::Filter &filter = Texture::defaultFilter); Video *newVideo(love::video::VideoStream *stream, float pixeldensity); virtual SpriteBatch *newSpriteBatch(Texture *texture, int size, vertex::Usage usage) = 0; @@ -905,6 +908,8 @@ protected: Capabilities capabilities; + Deprecations deprecations; + static const size_t MAX_USER_STACK_DEPTH = 64; private: diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index cce9290f8..c8c15d29c 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -899,6 +899,8 @@ void Graphics::present(void *screenshotCallbackData) if (isCanvasActive()) throw love::Exception("present cannot be called while a Canvas is active."); + deprecations.draw(this); + flushStreamDraws(); endPass(); diff --git a/src/modules/love/love.cpp b/src/modules/love/love.cpp index 2cd4f8007..e48156de1 100644 --- a/src/modules/love/love.cpp +++ b/src/modules/love/love.cpp @@ -21,6 +21,7 @@ // LOVE #include "common/config.h" #include "common/version.h" +#include "common/deprecation.h" #include "common/runtime.h" #include "common/wrap_Data.h" @@ -258,6 +259,25 @@ static int w__setGammaCorrect(lua_State *L) return 0; } +static int w_love_setDeprecationOutput(lua_State *L) +{ + bool enable = love::luax_checkboolean(L, 1); + love::setDeprecationOutputEnabled(enable); + return 0; +} + +static int w_love_hasDeprecationOutput(lua_State *L) +{ + love::luax_pushboolean(L, love::isDeprecationOutputEnabled()); + return 1; +} + +static int w_deprecation__gc(lua_State *) +{ + love::deinitDeprecation(); + return 0; +} + int luaopen_love(lua_State *L) { love::luax_insistpinnedthread(L); @@ -324,6 +344,27 @@ int luaopen_love(lua_State *L) #endif lua_setfield(L, -2, "_os"); + { + love::initDeprecation(); + + // Any old data that we can attach a metatable to, for __gc. We want to + // call deinitDeprecation when love is garbage collected. + lua_newuserdata(L, sizeof(int)); + + luaL_newmetatable(L, "love_deprecation"); + lua_pushcfunction(L, w_deprecation__gc); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + + lua_setfield(L, -2, "_deprecation"); + + lua_pushcfunction(L, w_love_setDeprecationOutput); + lua_setfield(L, -2, "setDeprecationOutput"); + + lua_pushcfunction(L, w_love_hasDeprecationOutput); + lua_setfield(L, -2, "hasDeprecationOutput"); + } + // Preload module loaders. for (int i = 0; modules[i].name != nullptr; i++) love::luax_preload(L, modules[i].func, modules[i].name); diff --git a/src/scripts/boot.lua b/src/scripts/boot.lua index 1066984bd..70f73094e 100644 --- a/src/scripts/boot.lua +++ b/src/scripts/boot.lua @@ -315,6 +315,8 @@ function love.boot() love.filesystem.setFused(is_fused_game) + love.setDeprecationOutput(not love.filesystem.isFused()) + local identity = "" if not can_has_game and o.game.set and o.game.arg[1] then local nouri = o.game.arg[1] diff --git a/src/scripts/boot.lua.h b/src/scripts/boot.lua.h index f0cb8cb06..1991564b8 100644 --- a/src/scripts/boot.lua.h +++ b/src/scripts/boot.lua.h @@ -578,6 +578,10 @@ const unsigned char boot_lua[] = 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x46, 0x75, 0x73, 0x65, 0x64, 0x28, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x29, 0x0a, + 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x75, 0x73, 0x65, 0x64, + 0x28, 0x29, 0x29, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x5f, 0x67, 0x61,