From 48e23a048deb16b563e3947187f9484482daa352 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Fri, 8 Sep 2023 22:38:17 -0300 Subject: [PATCH 001/409] Improve text wrapping when multiple characters are combined into one glyph. #1923 --- src/modules/font/GenericShaper.cpp | 44 ++++++++++++-------- src/modules/font/TextShaper.cpp | 6 +-- src/modules/font/freetype/HarfbuzzShaper.cpp | 44 ++++++++++++-------- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/modules/font/GenericShaper.cpp b/src/modules/font/GenericShaper.cpp index ef5854602..d96e8f90f 100644 --- a/src/modules/font/GenericShaper.cpp +++ b/src/modules/font/GenericShaper.cpp @@ -151,8 +151,7 @@ int GenericShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ran float w = 0.0f; float outwidth = 0.0f; float widthbeforelastspace = 0.0f; - int wrapindex = -1; - int lastspaceindex = -1; + int firstindexafterspace = -1; for (int i = (int)range.getMin(); i <= (int)range.getMax(); i++) { @@ -166,37 +165,48 @@ int GenericShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ran float newwidth = w + getKerning(prevglyph, g) + getGlyphAdvance(g); - // Only wrap when there's a non-space character. - if (newwidth > wraplimit && !isWhitespace(g)) - { - // Rewind to the last seen space when wrapping. - if (lastspaceindex != -1) - { - wrapindex = lastspaceindex; - outwidth = widthbeforelastspace; - } - break; - } - // Don't count trailing spaces in the output width. if (isWhitespace(g)) { - lastspaceindex = i; if (!isWhitespace(prevglyph)) widthbeforelastspace = w; } else + { + if (isWhitespace(prevglyph)) + firstindexafterspace = i; + + // Only wrap when there's a non-space character. + if (newwidth > wraplimit) + { + // If this is the first character, wrap from the next one instead of this one. + int wrapindex = i > (int)range.first ? i : (int)range.first + 1; + + // Rewind to after the last seen space when wrapping. + if (firstindexafterspace != -1) + { + wrapindex = firstindexafterspace; + outwidth = widthbeforelastspace; + } + + if (width) + *width = outwidth; + + return wrapindex; + } + outwidth = newwidth; + } w = newwidth; prevglyph = g; - wrapindex = i; } if (width) *width = outwidth; - return wrapindex; + // There wasn't any wrap in the middle of the range. + return range.last + 1; } } // font diff --git a/src/modules/font/TextShaper.cpp b/src/modules/font/TextShaper.cpp index 43854e719..8abf2b19c 100644 --- a/src/modules/font/TextShaper.cpp +++ b/src/modules/font/TextShaper.cpp @@ -303,10 +303,10 @@ void TextShaper::getWrap(const ColoredCodepoints &codepoints, float wraplimit, s float width = 0.0f; int wrapindex = computeWordWrapIndex(codepoints, r, wraplimit, &width); - if (wrapindex >= (int) i) + if (wrapindex > (int) i) { - r = Range(i, (size_t) wrapindex + 1 - i); - i = (size_t)wrapindex + 1; + r = Range(i, (size_t) wrapindex - i); + i = (size_t)wrapindex; } else { diff --git a/src/modules/font/freetype/HarfbuzzShaper.cpp b/src/modules/font/freetype/HarfbuzzShaper.cpp index b38859741..70767dada 100644 --- a/src/modules/font/freetype/HarfbuzzShaper.cpp +++ b/src/modules/font/freetype/HarfbuzzShaper.cpp @@ -335,8 +335,7 @@ int HarfbuzzShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ra float w = 0.0f; float outwidth = 0.0f; float widthbeforelastspace = 0.0f; - int wrapindex = -1; - int lastspaceindex = -1; + int firstindexafterspace = -1; uint32 prevcodepoint = 0; @@ -376,38 +375,49 @@ int HarfbuzzShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ra float newwidth = w + floorf((glyphpos.x_advance >> 6) / dpiScales[0] + 0.5f); - // Only wrap when there's a non-space character. - if (newwidth > wraplimit && !isWhitespace(clustercodepoint)) - { - // Rewind to the last seen space when wrapping. - if (lastspaceindex != -1) - { - wrapindex = lastspaceindex; - outwidth = widthbeforelastspace; - } - break; - } - // Don't count trailing spaces in the output width. if (isWhitespace(clustercodepoint)) { - lastspaceindex = info.cluster; if (!isWhitespace(prevcodepoint)) widthbeforelastspace = w; } else + { + if (isWhitespace(prevcodepoint)) + firstindexafterspace = info.cluster; + + // Only wrap when there's a non-space character. + if (newwidth > wraplimit) + { + // If this is the first character, wrap from the next one instead of this one. + int wrapindex = info.cluster > (int) range.first ? info.cluster : (int) range.first + 1; + + // Rewind to after the last seen space when wrapping. + if (firstindexafterspace != -1) + { + wrapindex = firstindexafterspace; + outwidth = widthbeforelastspace; + } + + if (width) + *width = outwidth; + + return wrapindex; + } + outwidth = newwidth; + } w = newwidth; prevcodepoint = clustercodepoint; - wrapindex = info.cluster; } } if (width) *width = outwidth; - return wrapindex; + // There wasn't any wrap in the middle of the range. + return (int) range.last + 1; } } // freetype From 96040b2b2ab883087d1c8adbab60967143f844e8 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 9 Sep 2023 13:22:45 -0300 Subject: [PATCH 002/409] Fix list of data types in the error message when using an invalid vertex data type in the deprecated type+component count vertex format declaration. --- src/modules/graphics/wrap_Graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 097c0534d..32c26821a 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1912,7 +1912,7 @@ static Mesh *newCustomMesh(lua_State *L) } if (decl.format == DATAFORMAT_MAX_ENUM) - luax_enumerror(L, "vertex data format", getConstants(decl.format), tname); + luax_enumerror(L, "vertex data type", {"float", "byte", "unorm8", "unorm16"}, tname); lua_pop(L, 3); From f43c6fedebdf0f0a241514271c141ac62e90ff6e Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Thu, 28 Sep 2023 15:54:36 +0800 Subject: [PATCH 003/409] Add physfs_platform_android.cpp as source files. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e5bc4fcd..644f71410 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1705,6 +1705,7 @@ set(LOVE_SRC_3P_PHYSFS src/libraries/physfs/physfs_internal.h src/libraries/physfs/physfs_lzmasdk.h src/libraries/physfs/physfs_miniz.h + src/libraries/physfs/physfs_platform_android.c src/libraries/physfs/physfs_platform_haiku.cpp src/libraries/physfs/physfs_platform_os2.c src/libraries/physfs/physfs_platform_posix.c From 2fd2930c24df263324cc0fa9a38feeff02c57e66 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Thu, 28 Sep 2023 16:53:59 +0800 Subject: [PATCH 004/409] Update lua-https to love2d/lua-https@0b2346f. --- .../luahttps/src/android/AndroidClient.cpp | 25 ++++++++++--------- src/libraries/luahttps/src/common/config.h | 11 ++++++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/libraries/luahttps/src/android/AndroidClient.cpp b/src/libraries/luahttps/src/android/AndroidClient.cpp index 24cbb1d0e..a5994e24b 100644 --- a/src/libraries/luahttps/src/android/AndroidClient.cpp +++ b/src/libraries/luahttps/src/android/AndroidClient.cpp @@ -7,6 +7,10 @@ #include +// We want std::string that contains null byte, hence length of 1. +// NOLINTNEXTLINE +static std::string null("", 1); + static std::string replace(const std::string &str, const std::string &from, const std::string &to) { std::stringstream ss; @@ -31,9 +35,6 @@ static std::string replace(const std::string &str, const std::string &from, cons static jstring newStringUTF(JNIEnv *env, const std::string &str) { - // We want std::string that contains null byte, hence length of 1. - static std::string null("", 1); - std::string newStr = replace(str, null, "\xC0\x80"); jstring jstr = env->NewStringUTF(newStr.c_str()); return jstr; @@ -41,9 +42,6 @@ static jstring newStringUTF(JNIEnv *env, const std::string &str) static std::string getStringUTF(JNIEnv *env, jstring str) { - // We want std::string that contains null byte, hence length of 1. - static std::string null("", 1); - const char *c = env->GetStringUTFChars(str, nullptr); std::string result = replace(c, "\xC0\x80", null); @@ -53,7 +51,6 @@ static std::string getStringUTF(JNIEnv *env, jstring str) AndroidClient::AndroidClient() : HTTPSClient() -, SDL_AndroidGetJNIEnv(nullptr) { // Look for SDL_AndroidGetJNIEnv SDL_AndroidGetJNIEnv = (decltype(SDL_AndroidGetJNIEnv)) dlsym(RTLD_DEFAULT, "SDL_AndroidGetJNIEnv"); @@ -116,12 +113,14 @@ HTTPSClient::Reply AndroidClient::request(const HTTPSClient::Request &req) env->DeleteLocalRef(method); // Set post data - if (req.postdata.size() > 0) + if (!req.postdata.empty()) { jmethodID setPostData = env->GetMethodID(httpsClass, "setPostData", "([B)V"); jbyteArray byteArray = env->NewByteArray((jsize) req.postdata.length()); jbyte *byteArrayData = env->GetByteArrayElements(byteArray, nullptr); + // The usage of memcpy is intentional. + // NOLINTNEXTLINE memcpy(byteArrayData, req.postdata.data(), req.postdata.length()); env->ReleaseByteArrayElements(byteArray, byteArrayData, 0); @@ -156,9 +155,9 @@ HTTPSClient::Reply AndroidClient::request(const HTTPSClient::Request &req) { // Get headers jobjectArray interleavedHeaders = (jobjectArray) env->CallObjectMethod(httpsObject, getInterleavedHeaders); - int len = env->GetArrayLength(interleavedHeaders); + int headerLen = env->GetArrayLength(interleavedHeaders); - for (int i = 0; i < len; i += 2) + for (int i = 0; i < headerLen; i += 2) { jstring key = (jstring) env->GetObjectArrayElement(interleavedHeaders, i); jstring value = (jstring) env->GetObjectArrayElement(interleavedHeaders, i + 1); @@ -176,15 +175,17 @@ HTTPSClient::Reply AndroidClient::request(const HTTPSClient::Request &req) if (responseData) { - int len = env->GetArrayLength(responseData); + int responseLen = env->GetArrayLength(responseData); jbyte *responseByte = env->GetByteArrayElements(responseData, nullptr); - response.body = std::string((char *) responseByte, len); + response.body = std::string((char *) responseByte, responseLen); env->DeleteLocalRef(responseData); } } + env->DeleteLocalRef(httpsObject); + return response; } diff --git a/src/libraries/luahttps/src/common/config.h b/src/libraries/luahttps/src/common/config.h index e55c3fe3f..4068e9b63 100644 --- a/src/libraries/luahttps/src/common/config.h +++ b/src/libraries/luahttps/src/common/config.h @@ -1,5 +1,10 @@ #pragma once +// MSVC warnings +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) + #define _CRT_SECURE_NO_WARNINGS +#endif + #if defined(HTTPS_HAVE_CONFIG_GENERATED_H) #include "common/config-generated.h" #elif defined(WIN32) || defined(_WIN32) @@ -10,6 +15,12 @@ // WinINet is only supported on desktop. #define HTTPS_BACKEND_WININET #endif + // Visual Studio 2017 supports __has_include + #if defined __has_include + #if __has_include() + #define HTTPS_BACKEND_CURL + #endif + #endif #elif defined(__ANDROID__) #define HTTPS_BACKEND_ANDROID #elif defined(__APPLE__) From 691d910c3ed3098cab63797f9a2f6b4826972ba7 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 30 Sep 2023 17:54:09 -0300 Subject: [PATCH 005/409] Improve error message when Mesh:setVertexMap is used with an empty array. --- src/modules/graphics/Mesh.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 78abd2d96..4db8cf316 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -320,6 +320,9 @@ static void copyToIndexBuffer(const std::vector &indices, void *data, si void Mesh::setVertexMap(const std::vector &map) { + if (map.empty()) + throw love::Exception("Vertex map array must not be empty."); + size_t maxval = getVertexCount(); IndexDataType datatype = getIndexDataTypeFromMax(maxval); From dbc7d7f3cad67af9b05050513fbd35b082a1383a Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 30 Sep 2023 20:12:43 -0300 Subject: [PATCH 006/409] Add love.graphics.newMesh variant to create a Mesh from existing Buffers. This allows a Mesh to be created that doesn't have its own internal vertex buffer and purely references other vertex buffers instead. The prototype looks like this: mesh = love.graphics.newMesh(attributelist, drawmode) where attributelist is an array of tables each with the following fields, similar to Mesh:attachAttribute: { buffer = vertexbuffer, name = "VertexPosition", -- the name this vertex attribute will use in a shader nameinbuffer = nil, -- the name of the attribute in the vertex buffer. Defaults to the name field. step = nil, -- vertex attribute step ("pervertex" or "perinstance"), defaults to "pervertex". startindex = nil, -- 1-based array index within the given vertex buffer where the attribute data will start being pulled from during rendering. Defaults to 1. } --- src/modules/graphics/Mesh.cpp | 48 ++++++++++------ src/modules/graphics/Mesh.h | 2 + src/modules/graphics/wrap_Graphics.cpp | 77 +++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/src/modules/graphics/Mesh.cpp b/src/modules/graphics/Mesh.cpp index 4db8cf316..f9c705e85 100644 --- a/src/modules/graphics/Mesh.cpp +++ b/src/modules/graphics/Mesh.cpp @@ -107,15 +107,18 @@ Mesh::Mesh(const std::vector &attributes, PrimitiveType d throw love::Exception("At least one buffer attribute must be specified in this constructor."); attachedAttributes = attributes; - vertexCount = attachedAttributes.size() > 0 ? LOVE_UINT32_MAX : 0; - for (const auto &attrib : attachedAttributes) - { - if ((attrib.buffer->getUsageFlags() & BUFFERUSAGEFLAG_VERTEX) == 0) - throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); + auto gfx = Module::getInstance(Module::M_GRAPHICS); - if (getAttachedAttributeIndex(attrib.name) != -1) + for (int i = 0; i < (int) attachedAttributes.size(); i++) + { + auto &attrib = attachedAttributes[i]; + + finalizeAttribute(gfx, attrib); + + int attributeIndex = getAttachedAttributeIndex(attrib.name); + if (attributeIndex != i && attributeIndex != -1) throw love::Exception("Duplicate vertex attribute name: %s", attrib.name.c_str()); vertexCount = std::min(vertexCount, attrib.buffer->getArrayLength()); @@ -140,7 +143,7 @@ void Mesh::setupAttachedAttributes() if (getAttachedAttributeIndex(name) != -1) throw love::Exception("Duplicate vertex attribute name: %s", name.c_str()); - attachedAttributes.push_back({name, vertexBuffer, nullptr, (int) i, 0, STEP_PER_VERTEX, true}); + attachedAttributes.push_back({name, vertexBuffer, nullptr, name, (int) i, 0, STEP_PER_VERTEX, true}); } } @@ -155,6 +158,24 @@ int Mesh::getAttachedAttributeIndex(const std::string &name) const return -1; } +void Mesh::finalizeAttribute(Graphics *gfx, BufferAttribute &attrib) const +{ + if ((attrib.buffer->getUsageFlags() & BUFFERUSAGEFLAG_VERTEX) == 0) + throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); + + if (attrib.step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING]) + throw love::Exception("Vertex attribute instancing is not supported on this system."); + + if (attrib.startArrayIndex < 0 || attrib.startArrayIndex >= (int)attrib.buffer->getArrayLength()) + throw love::Exception("Invalid start array index %d.", attrib.startArrayIndex + 1); + + int indexInBuffer = attrib.buffer->getDataMemberIndex(attrib.nameInBuffer); + if (indexInBuffer < 0) + throw love::Exception("Buffer does not have a vertex attribute with name '%s'.", attrib.nameInBuffer.c_str()); + + attrib.indexInBuffer = indexInBuffer; +} + void *Mesh::checkVertexDataOffset(size_t vertindex, size_t *byteoffset) { if (vertindex >= vertexCount) @@ -210,15 +231,7 @@ bool Mesh::isAttributeEnabled(const std::string &name) const void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, const std::string &attachname, int startindex, AttributeStep step) { - if ((buffer->getUsageFlags() & BUFFERUSAGEFLAG_VERTEX) == 0) - throw love::Exception("Buffer must be created with vertex buffer support to be used as a Mesh vertex attribute."); - auto gfx = Module::getInstance(Module::M_GRAPHICS); - if (step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING]) - throw love::Exception("Vertex attribute instancing is not supported on this system."); - - if (startindex < 0 || startindex >= (int) buffer->getArrayLength()) - throw love::Exception("Invalid start array index %d.", startindex + 1); BufferAttribute oldattrib = {}; BufferAttribute newattrib = {}; @@ -233,10 +246,13 @@ void Mesh::attachAttribute(const std::string &name, Buffer *buffer, Mesh *mesh, newattrib.buffer = buffer; newattrib.mesh = mesh; newattrib.enabled = oldattrib.buffer.get() ? oldattrib.enabled : true; - newattrib.indexInBuffer = buffer->getDataMemberIndex(attachname); + newattrib.nameInBuffer = attachname; + newattrib.indexInBuffer = -1; newattrib.startArrayIndex = startindex; newattrib.step = step; + finalizeAttribute(gfx, newattrib); + if (newattrib.indexInBuffer < 0) throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str()); diff --git a/src/modules/graphics/Mesh.h b/src/modules/graphics/Mesh.h index b164b7cfb..6002971a6 100644 --- a/src/modules/graphics/Mesh.h +++ b/src/modules/graphics/Mesh.h @@ -56,6 +56,7 @@ public: std::string name; StrongRef buffer; StrongRef mesh; + std::string nameInBuffer; int indexInBuffer; int startArrayIndex; AttributeStep step; @@ -186,6 +187,7 @@ private: void setupAttachedAttributes(); int getAttachedAttributeIndex(const std::string &name) const; + void finalizeAttribute(Graphics *gfx, BufferAttribute &attrib) const; void drawInternal(Graphics *gfx, const Matrix4 &m, int instancecount, Buffer *indirectargs, int argsindex); diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 32c26821a..3a2eb613a 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -1990,6 +1990,79 @@ static Mesh *newCustomMesh(lua_State *L) return t; } +static bool luax_isbufferattributetable(lua_State* L, int idx) +{ + if (lua_type(L, idx) != LUA_TTABLE) + return false; + + lua_rawgeti(L, idx, 1); + if (lua_type(L, -1) != LUA_TTABLE) + { + lua_pop(L, 1); + return false; + } + + lua_getfield(L, -1, "buffer"); + bool isbuffer = luax_istype(L, -1, Buffer::type); + lua_pop(L, 2); + return isbuffer; +} + +static Mesh::BufferAttribute luax_checkbufferattributetable(lua_State *L, int idx) +{ + Mesh::BufferAttribute attrib = {}; + + attrib.step = STEP_PER_VERTEX; + attrib.enabled = true; + + lua_getfield(L, idx, "buffer"); + attrib.buffer = luax_checkbuffer(L, -1); + lua_pop(L, 1); + + lua_getfield(L, idx, "name"); + attrib.name = luax_checkstring(L, -1); + lua_pop(L, 1); + + lua_getfield(L, idx, "step"); + if (!lua_isnoneornil(L, -1)) + { + const char *stepstr = luaL_checkstring(L, -1); + if (!getConstant(stepstr, attrib.step)) + luax_enumerror(L, "vertex attribute step", getConstants(attrib.step), stepstr); + } + lua_pop(L, 1); + + lua_getfield(L, idx, "nameinbuffer"); + if (!lua_isnoneornil(L, -1)) + attrib.nameInBuffer = luax_checkstring(L, -1); + else + attrib.nameInBuffer = attrib.name; + lua_pop(L, 1); + + lua_getfield(L, idx, "startindex"); + attrib.startArrayIndex = (int) luaL_optinteger(L, -1, 1) - 1; + lua_pop(L, 1); + + return attrib; +} + +static Mesh* newMeshFromBuffers(lua_State *L) +{ + std::vector attributes; + for (size_t i = 1; i <= luax_objlen(L, 1); i++) + { + lua_rawgeti(L, 1, i); + attributes.push_back(luax_checkbufferattributetable(L, -1)); + lua_pop(L, 1); + } + + PrimitiveType drawmode = luax_checkmeshdrawmode(L, 2); + + Mesh *t = nullptr; + luax_catchexcept(L, [&]() { t = instance()->newMesh(attributes, drawmode); }); + return t; +} + int w_newMesh(lua_State *L) { luax_checkgraphicscreated(L); @@ -2002,7 +2075,9 @@ int w_newMesh(lua_State *L) Mesh *t = nullptr; int arg2type = lua_type(L, 2); - if (arg1type == LUA_TTABLE && (arg2type == LUA_TTABLE || arg2type == LUA_TNUMBER || arg2type == LUA_TUSERDATA)) + if (luax_isbufferattributetable(L, 1)) + t = newMeshFromBuffers(L); + else if (arg1type == LUA_TTABLE && (arg2type == LUA_TTABLE || arg2type == LUA_TNUMBER || arg2type == LUA_TUSERDATA)) t = newCustomMesh(L); else t = newStandardMesh(L); From b1609ed83be598899dcf4e65cb03723edd8b43ff Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 1 Oct 2023 15:55:23 -0300 Subject: [PATCH 007/409] love.physics: simplify some internal bookkeeping code --- src/modules/physics/box2d/Body.cpp | 42 +++++++---------------- src/modules/physics/box2d/Body.h | 13 ++----- src/modules/physics/box2d/Contact.cpp | 5 +-- src/modules/physics/box2d/Fixture.cpp | 35 ++++++------------- src/modules/physics/box2d/Fixture.h | 16 ++------- src/modules/physics/box2d/GearJoint.cpp | 4 +-- src/modules/physics/box2d/Joint.cpp | 45 +++++++------------------ src/modules/physics/box2d/Joint.h | 13 ++----- src/modules/physics/box2d/World.cpp | 24 ++++++------- 9 files changed, 60 insertions(+), 137 deletions(-) diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index 0e846cdc3..a21f0be4d 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -39,29 +39,20 @@ namespace box2d Body::Body(World *world, b2Vec2 p, Body::Type type) : world(world) - , udata(nullptr) { - udata = new bodyudata(); - udata->ref = nullptr; b2BodyDef def; def.position = Physics::scaleDown(p); - def.userData.pointer = (uintptr_t)udata; + def.userData.pointer = (uintptr_t)this; body = world->world->CreateBody(&def); // Box2D body holds a reference to the love Body. this->retain(); this->setType(type); - world->registerObject(body, this); } Body::~Body() { - if (!udata) - return; - - if (udata->ref) - delete udata->ref; - - delete udata; + if (ref) + delete ref; } float Body::getX() @@ -479,7 +470,7 @@ int Body::getFixtures(lua_State *L) const { if (!f) break; - Fixture *fixture = (Fixture *)world->findObject(f); + Fixture *fixture = (Fixture *)(f->GetUserData().pointer); if (!fixture) throw love::Exception("A fixture has escaped Memoizer!"); luax_pushtype(L, fixture); @@ -501,7 +492,7 @@ int Body::getJoints(lua_State *L) const if (!je) break; - Joint *joint = (Joint *) world->findObject(je->joint); + Joint *joint = (Joint *) (je->joint->GetUserData().pointer); if (!joint) throw love::Exception("A joint has escaped Memoizer!"); @@ -550,12 +541,11 @@ void Body::destroy() } world->world->DestroyBody(body); - world->unregisterObject(body); - body = NULL; + body = nullptr; // Remove userdata reference to avoid it sticking around after GC - if (udata && udata->ref) - udata->ref->unref(); + if (ref) + ref->unref(); // Box2D body destroyed. Release its reference to the love Body. this->release(); @@ -565,24 +555,18 @@ int Body::setUserData(lua_State *L) { love::luax_assert_argc(L, 1, 1); - if (udata == nullptr) - { - udata = new bodyudata(); - body->GetUserData().pointer = (uintptr_t)udata; - } + if(!ref) + ref = new Reference(); - if(!udata->ref) - udata->ref = new Reference(); - - udata->ref->ref(L); + ref->ref(L); return 0; } int Body::getUserData(lua_State *L) { - if (udata != nullptr && udata->ref != nullptr) - udata->ref->push(L); + if (ref != nullptr) + ref->push(L); else lua_pushnil(L); diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index 95ae911e8..563812fe2 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -41,16 +41,6 @@ class World; class Shape; class Fixture; -/** - * This struct is stored in a void pointer in the Box2D Body class. For now, all - * we need is a Lua reference to arbitrary data, but we might need more later. - **/ -struct bodyudata -{ - // Reference to arbitrary data. - Reference *ref = nullptr; -}; - /** * A Body is an entity which has position and orientation * in world space. A Body does have collision geometry @@ -441,7 +431,8 @@ private: // unowned? World *world; - bodyudata *udata; + // Reference to arbitrary data. + Reference* ref = nullptr; }; // Body diff --git a/src/modules/physics/box2d/Contact.cpp b/src/modules/physics/box2d/Contact.cpp index 5b110dcc3..46e2b2a89 100644 --- a/src/modules/physics/box2d/Contact.cpp +++ b/src/modules/physics/box2d/Contact.cpp @@ -35,6 +35,7 @@ Contact::Contact(World *world, b2Contact *contact) : contact(contact) , world(world) { + //contact->user world->registerObject(contact, this); } @@ -145,8 +146,8 @@ void Contact::getChildren(int &childA, int &childB) void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB) { - fixtureA = (Fixture *) world->findObject(contact->GetFixtureA()); - fixtureB = (Fixture *) world->findObject(contact->GetFixtureB()); + fixtureA = (Fixture *) (contact->GetFixtureA()->GetUserData().pointer); + fixtureB = (Fixture *) (contact->GetFixtureB()->GetUserData().pointer); if (!fixtureA || !fixtureB) throw love::Exception("A fixture has escaped Memoizer!"); diff --git a/src/modules/physics/box2d/Fixture.cpp b/src/modules/physics/box2d/Fixture.cpp index a1d3dc994..12fc9b2d7 100644 --- a/src/modules/physics/box2d/Fixture.cpp +++ b/src/modules/physics/box2d/Fixture.cpp @@ -41,26 +41,18 @@ Fixture::Fixture(Body *body, Shape *shape, float density) : body(body) , fixture(nullptr) { - udata = new fixtureudata(); - udata->ref = nullptr; b2FixtureDef def; def.shape = shape->shape; - def.userData.pointer = (uintptr_t)udata; + def.userData.pointer = (uintptr_t)this; def.density = density; fixture = body->body->CreateFixture(&def); this->retain(); - body->world->registerObject(fixture, this); } Fixture::~Fixture() { - if (!udata) - return; - - if (udata->ref) - delete udata->ref; - - delete udata; + if (ref) + delete ref; } void Fixture::checkCreateShape() @@ -259,24 +251,18 @@ int Fixture::setUserData(lua_State *L) { love::luax_assert_argc(L, 1, 1); - if (udata == nullptr) - { - udata = new fixtureudata(); - fixture->GetUserData().pointer = (uintptr_t)udata; - } + if(!ref) + ref = new Reference(); - if(!udata->ref) - udata->ref = new Reference(); - - udata->ref->ref(L); + ref->ref(L); return 0; } int Fixture::getUserData(lua_State *L) { - if (udata->ref != nullptr) - udata->ref->push(L); + if (ref != nullptr) + ref->push(L); else lua_pushnil(L); @@ -348,12 +334,11 @@ void Fixture::destroy(bool implicit) if (!implicit && fixture != nullptr) body->body->DestroyFixture(fixture); - body->world->unregisterObject(fixture); fixture = nullptr; // Remove userdata reference to avoid it sticking around after GC - if (udata && udata->ref) - udata->ref->unref(); + if (ref) + ref->unref(); // Box2D fixture destroyed. Release its reference to the love Fixture. this->release(); diff --git a/src/modules/physics/box2d/Fixture.h b/src/modules/physics/box2d/Fixture.h index d4087c5c3..4f0d54e99 100644 --- a/src/modules/physics/box2d/Fixture.h +++ b/src/modules/physics/box2d/Fixture.h @@ -40,18 +40,6 @@ namespace box2d class World; -/** - * This struct is stored in a void pointer - * in the Box2D Fixture class. For now, all we - * need is a Lua reference to arbitrary data, - * but we might need more later. - **/ -struct fixtureudata -{ - // Reference to arbitrary data. - Reference *ref = nullptr; -}; - /** * A Fixture is used to attach a shape to a body for collision detection. * A Fixture inherits its transform from its parent. Fixtures hold @@ -212,9 +200,11 @@ protected: void checkCreateShape(); Body *body; - fixtureudata *udata; b2Fixture *fixture; + // Reference to arbitrary data. + Reference* ref = nullptr; + StrongRef shape; }; diff --git a/src/modules/physics/box2d/GearJoint.cpp b/src/modules/physics/box2d/GearJoint.cpp index 8f0968285..474e19448 100644 --- a/src/modules/physics/box2d/GearJoint.cpp +++ b/src/modules/physics/box2d/GearJoint.cpp @@ -69,7 +69,7 @@ Joint *GearJoint::getJointA() const if (b2joint == nullptr) return nullptr; - Joint *j = (Joint *) world->findObject(b2joint); + Joint *j = (Joint *) (b2joint->GetUserData().pointer); if (j == nullptr) throw love::Exception("A joint has escaped Memoizer!"); @@ -82,7 +82,7 @@ Joint *GearJoint::getJointB() const if (b2joint == nullptr) return nullptr; - Joint *j = (Joint *) world->findObject(b2joint); + Joint *j = (Joint *) (b2joint->GetUserData().pointer); if (j == nullptr) throw love::Exception("A joint has escaped Memoizer!"); diff --git a/src/modules/physics/box2d/Joint.cpp b/src/modules/physics/box2d/Joint.cpp index bb5cf8aba..d387b7ae2 100644 --- a/src/modules/physics/box2d/Joint.cpp +++ b/src/modules/physics/box2d/Joint.cpp @@ -38,33 +38,22 @@ namespace box2d Joint::Joint(Body *body1) : world(body1->world) - , udata(nullptr) , body1(body1) , body2(nullptr) { - udata = new jointudata(); - udata->ref = nullptr; } Joint::Joint(Body *body1, Body *body2) : world(body1->world) - , udata(nullptr) , body1(body1) , body2(body2) { - udata = new jointudata(); - udata->ref = nullptr; } Joint::~Joint() { - if (!udata) - return; - - if (udata->ref) - delete udata->ref; - - delete udata; + if (ref) + delete ref; } Joint::Type Joint::getType() const @@ -104,7 +93,7 @@ Body *Joint::getBodyA() const if (b2body == nullptr) return nullptr; - Body *body = (Body *) world->findObject(b2body); + Body *body = (Body *) (b2body->GetUserData().pointer); if (body == nullptr) throw love::Exception("A body has escaped Memoizer!"); @@ -117,7 +106,7 @@ Body *Joint::getBodyB() const if (b2body == nullptr) return nullptr; - Body *body = (Body *) world->findObject(b2body); + Body *body = (Body *) (b2body->GetUserData().pointer); if (body == nullptr) throw love::Exception("A body has escaped Memoizer!"); @@ -154,9 +143,8 @@ float Joint::getReactionTorque(float dt) b2Joint *Joint::createJoint(b2JointDef *def) { - def->userData.pointer = (uintptr_t)udata; + def->userData.pointer = (uintptr_t)this; joint = world->world->CreateJoint(def); - world->registerObject(joint, this); // Box2D joint has a reference to this love Joint. this->retain(); return joint; @@ -174,12 +162,11 @@ void Joint::destroyJoint(bool implicit) if (!implicit && joint != nullptr) world->world->DestroyJoint(joint); - world->unregisterObject(joint); - joint = NULL; + joint = nullptr; // Remove userdata reference to avoid it sticking around after GC - if (udata && udata->ref) - udata->ref->unref(); + if (ref) + ref->unref(); // Release the reference of the Box2D joint. this->release(); @@ -199,24 +186,18 @@ int Joint::setUserData(lua_State *L) { love::luax_assert_argc(L, 1, 1); - if (udata == nullptr) - { - udata = new jointudata(); - joint->GetUserData().pointer = (uintptr_t)udata; - } + if(!ref) + ref = new Reference(); - if(!udata->ref) - udata->ref = new Reference(); - - udata->ref->ref(L); + ref->ref(L); return 0; } int Joint::getUserData(lua_State *L) { - if (udata != nullptr && udata->ref != nullptr) - udata->ref->push(L); + if (ref != nullptr) + ref->push(L); else lua_pushnil(L); diff --git a/src/modules/physics/box2d/Joint.h b/src/modules/physics/box2d/Joint.h index 0ef205588..140842df4 100644 --- a/src/modules/physics/box2d/Joint.h +++ b/src/modules/physics/box2d/Joint.h @@ -39,16 +39,6 @@ namespace box2d class Body; class World; -/** - * This struct is stored in a void pointer in the Box2D Joint class. For now, all - * we need is a Lua reference to arbitrary data, but we might need more later. - **/ -struct jointudata -{ - // Reference to arbitrary data. - Reference *ref = nullptr; -}; - /** * A Joint acts as positioning constraints on Bodies. * A Joint can be used to prevent Bodies from going to @@ -140,7 +130,8 @@ protected: World *world; - jointudata *udata; + // Reference to arbitrary data. + Reference* ref = nullptr; private: diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 0538730a5..0b7ec8653 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -60,7 +60,7 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse // Push first fixture. { - Fixture *a = (Fixture *)world->findObject(contact->GetFixtureA()); + Fixture *a = (Fixture *)(contact->GetFixtureA()->GetUserData().pointer); if (a != nullptr) luax_pushtype(L, a); else @@ -69,7 +69,7 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse // Push second fixture. { - Fixture *b = (Fixture *)world->findObject(contact->GetFixtureB()); + Fixture *b = (Fixture *)(contact->GetFixtureB()->GetUserData().pointer); if (b != nullptr) luax_pushtype(L, b); else @@ -158,7 +158,7 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture) if (L != nullptr) { lua_pushvalue(L, funcidx); - Fixture *f = (Fixture *)world->findObject(fixture); + Fixture *f = (Fixture *)(fixture->GetUserData().pointer); if (!f) throw love::Exception("A fixture has escaped Memoizer!"); luax_pushtype(L, f); @@ -184,7 +184,7 @@ World::CollectCallback::~CollectCallback() bool World::CollectCallback::ReportFixture(b2Fixture *f) { - Fixture *fixture = (Fixture *)world->findObject(f); + Fixture *fixture = (Fixture *)(f->GetUserData().pointer); if (!fixture) throw love::Exception("A fixture has escaped Memoizer!"); luax_pushtype(L, fixture); @@ -210,7 +210,7 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po if (L != nullptr) { lua_pushvalue(L, funcidx); - Fixture *f = (Fixture *)world->findObject(fixture); + Fixture *f = (Fixture *)(fixture->GetUserData().pointer); if (!f) throw love::Exception("A fixture has escaped Memoizer!"); luax_pushtype(L, f); @@ -233,14 +233,14 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po void World::SayGoodbye(b2Fixture *fixture) { - Fixture *f = (Fixture *)findObject(fixture); + Fixture *f = (Fixture *)(fixture->GetUserData().pointer); // Hint implicit destruction with true. if (f) f->destroy(true); } void World::SayGoodbye(b2Joint *joint) { - Joint *j = (Joint *)findObject(joint); + Joint *j = (Joint *)(joint->GetUserData().pointer); // Hint implicit destruction with true. if (j) j->destroyJoint(true); } @@ -351,8 +351,8 @@ void World::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse) bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB) { // Fixtures should be memoized, if we created them - Fixture *a = (Fixture *)findObject(fixtureA); - Fixture *b = (Fixture *)findObject(fixtureB); + Fixture *a = (Fixture *)(fixtureA->GetUserData().pointer); + Fixture *b = (Fixture *)(fixtureB->GetUserData().pointer); if (!a || !b) throw love::Exception("A fixture has escaped Memoizer!"); return filter.process(a, b); @@ -507,7 +507,7 @@ int World::getBodies(lua_State *L) const break; if (b == groundBody) continue; - Body *body = (Body *)findObject(b); + Body *body = (Body *)(b->GetUserData().pointer); if (!body) throw love::Exception("A body has escaped Memoizer!"); luax_pushtype(L, body); @@ -526,7 +526,7 @@ int World::getJoints(lua_State *L) const do { if (!j) break; - Joint *joint = (Joint *)findObject(j); + Joint *joint = (Joint *)(j->GetUserData().pointer); if (!joint) throw love::Exception("A joint has escaped Memoizer!"); luax_pushjoint(L, joint); lua_rawseti(L, -2, i); @@ -635,7 +635,7 @@ void World::destroy() b = b->GetNext(); if (t == groundBody) continue; - Body *body = (Body *)findObject(t); + Body *body = (Body *)(t->GetUserData().pointer); if (!body) throw love::Exception("A body has escaped Memoizer!"); body->destroy(); From d24ccde864168eda66b093cdadcee197f10c4456 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 2 Oct 2023 11:00:02 -0300 Subject: [PATCH 008/409] World:rayCast and World:queryBoundingBox have user args passed through to the callback function. Fixes #1194 --- src/modules/physics/box2d/World.cpp | 10 ++++++++-- src/modules/physics/box2d/World.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 0b7ec8653..bdda75ccd 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -147,6 +147,7 @@ World::QueryCallback::QueryCallback(World *world, lua_State *L, int idx) , funcidx(idx) { luaL_checktype(L, funcidx, LUA_TFUNCTION); + userargs = lua_gettop(L) - funcidx; } World::QueryCallback::~QueryCallback() @@ -162,7 +163,9 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture) if (!f) throw love::Exception("A fixture has escaped Memoizer!"); luax_pushtype(L, f); - lua_call(L, 1, 1); + for (int i = 1; i <= userargs; i++) + lua_pushvalue(L, funcidx + i); + lua_call(L, 1 + userargs, 1); bool cont = luax_toboolean(L, -1); lua_pop(L, 1); return cont; @@ -199,6 +202,7 @@ World::RayCastCallback::RayCastCallback(World *world, lua_State *L, int idx) , funcidx(idx) { luaL_checktype(L, funcidx, LUA_TFUNCTION); + userargs = lua_gettop(L) - funcidx; } World::RayCastCallback::~RayCastCallback() @@ -220,7 +224,9 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po lua_pushnumber(L, normal.x); lua_pushnumber(L, normal.y); lua_pushnumber(L, fraction); - lua_call(L, 6, 1); + for (int i = 1; i <= userargs; i++) + lua_pushvalue(L, funcidx + i); + lua_call(L, 6 + userargs, 1); if (!lua_isnumber(L, -1)) luaL_error(L, "Raycast callback didn't return a number!"); float fraction = (float) lua_tonumber(L, -1); diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index ff81271ec..669e39921 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -100,6 +100,7 @@ public: World *world; lua_State *L; int funcidx; + int userargs; }; class CollectCallback : public b2QueryCallback @@ -124,6 +125,7 @@ public: World *world; lua_State *L; int funcidx; + int userargs; }; /** From c3847d5f04c2667dcb3f17416c2ee93e846587e8 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 2 Oct 2023 11:06:15 -0300 Subject: [PATCH 009/409] Rename World:queryBoundingBox to World:queryFixturesInArea. Matches the new World:getFixturesInArea function. --- src/modules/physics/box2d/World.cpp | 2 +- src/modules/physics/box2d/World.h | 2 +- src/modules/physics/box2d/wrap_World.cpp | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index bdda75ccd..0aff2ff5b 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -569,7 +569,7 @@ b2Body *World::getGroundBody() const return groundBody; } -int World::queryBoundingBox(lua_State *L) +int World::queryFixturesInArea(lua_State *L) { b2AABB box; float lx = (float)luaL_checknumber(L, 1); diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 669e39921..208b202ea 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -286,7 +286,7 @@ public: /** * Calls a callback on all fixtures that overlap a given bounding box. **/ - int queryBoundingBox(lua_State *L); + int queryFixturesInArea(lua_State *L); /** * Gets all fixtures that overlap a given bounding box. diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index 68305b9ae..87080dc20 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -178,11 +178,17 @@ int w_World_getContacts(lua_State *L) return ret; } -int w_World_queryBoundingBox(lua_State *L) +int w_World_queryFixturesInArea(lua_State *L) { World *t = luax_checkworld(L, 1); lua_remove(L, 1); - return t->queryBoundingBox(L); + return t->queryFixturesInArea(L); +} + +int w_World_queryBoundingBox(lua_State* L) +{ + luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryFixturesInArea"); + return w_World_queryFixturesInArea(L); } int w_World_getFixturesInArea(lua_State *L) @@ -236,12 +242,15 @@ static const luaL_Reg w_World_functions[] = { "getBodies", w_World_getBodies }, { "getJoints", w_World_getJoints }, { "getContacts", w_World_getContacts }, - { "queryBoundingBox", w_World_queryBoundingBox }, + { "queryFixturesInArea", w_World_queryFixturesInArea }, { "getFixturesInArea", w_World_getFixturesInArea }, { "rayCast", w_World_rayCast }, { "destroy", w_World_destroy }, { "isDestroyed", w_World_isDestroyed }, + // Deprecated + { "queryBoundingBox", w_World_queryBoundingBox }, + { 0, 0 } }; From 28a898df1f1958b2b320a791db4db1e424651cf2 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 2 Oct 2023 12:11:35 -0300 Subject: [PATCH 010/409] Add World:rayCastAny and World:rayCastClosest. They return hit position, normal, and ray fraction (if there is a hit), and also take an optional fixture category bitmask parameter. --- src/modules/physics/box2d/World.cpp | 72 ++++++++++++++++++++++++ src/modules/physics/box2d/World.h | 32 +++++++++-- src/modules/physics/box2d/wrap_World.cpp | 22 +++++++- 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 0aff2ff5b..27b41dd8e 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -237,6 +237,30 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po return 0; } +World::RayCastOneCallback::RayCastOneCallback(uint16 categoryMask, bool any) + : hit(false) + , hitPoint() + , hitNormal() + , hitFraction(1.0f) + , categoryMask(categoryMask) + , any(any) +{ +} + +float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction) +{ + if (categoryMask != 0xFFFF && (categoryMask & fixture->GetFilterData().categoryBits) == 0) + return -1; + + hit = true; + hitPoint = point; + hitNormal = normal; + hitFraction = fraction; + + // Returning the fraction makes sure it doesn't process anything farther away in subsequent iterations. + return any ? 0 : fraction; +} + void World::SayGoodbye(b2Fixture *fixture) { Fixture *f = (Fixture *)(fixture->GetUserData().pointer); @@ -612,6 +636,54 @@ int World::rayCast(lua_State *L) return 0; } +int World::rayCastAny(lua_State *L) +{ + float x1 = (float)luaL_checknumber(L, 1); + float y1 = (float)luaL_checknumber(L, 2); + float x2 = (float)luaL_checknumber(L, 3); + float y2 = (float)luaL_checknumber(L, 4); + uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF); + b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1)); + b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2)); + RayCastOneCallback raycast(categoryMaskBits, true); + world->RayCast(&raycast, v1, v2); + if (raycast.hit) + { + b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint); + lua_pushnumber(L, hitPoint.x); + lua_pushnumber(L, hitPoint.y); + lua_pushnumber(L, raycast.hitNormal.x); + lua_pushnumber(L, raycast.hitNormal.y); + lua_pushnumber(L, raycast.hitFraction); + return 5; + } + return 0; +} + +int World::rayCastClosest(lua_State *L) +{ + float x1 = (float)luaL_checknumber(L, 1); + float y1 = (float)luaL_checknumber(L, 2); + float x2 = (float)luaL_checknumber(L, 3); + float y2 = (float)luaL_checknumber(L, 4); + uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF); + b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1)); + b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2)); + RayCastOneCallback raycast(categoryMaskBits, false); + world->RayCast(&raycast, v1, v2); + if (raycast.hit) + { + b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint); + lua_pushnumber(L, hitPoint.x); + lua_pushnumber(L, hitPoint.y); + lua_pushnumber(L, raycast.hitNormal.x); + lua_pushnumber(L, raycast.hitNormal.y); + lua_pushnumber(L, raycast.hitFraction); + return 5; + } + return 0; +} + void World::destroy() { if (world == nullptr) diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 208b202ea..75c62bb29 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -94,8 +94,8 @@ public: { public: QueryCallback(World *world, lua_State *L, int idx); - ~QueryCallback(); - virtual bool ReportFixture(b2Fixture *fixture); + virtual ~QueryCallback(); + bool ReportFixture(b2Fixture *fixture) override; private: World *world; lua_State *L; @@ -107,8 +107,8 @@ public: { public: CollectCallback(World *world, lua_State *L); - ~CollectCallback(); - virtual bool ReportFixture(b2Fixture *fixture); + virtual ~CollectCallback(); + bool ReportFixture(b2Fixture *fixture) override; private: World *world; lua_State *L; @@ -119,8 +119,8 @@ public: { public: RayCastCallback(World *world, lua_State *L, int idx); - ~RayCastCallback(); - virtual float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction); + virtual ~RayCastCallback(); + float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction) override; private: World *world; lua_State *L; @@ -128,6 +128,23 @@ public: int userargs; }; + class RayCastOneCallback : public b2RayCastCallback + { + public: + RayCastOneCallback(uint16 categoryMask, bool any); + virtual ~RayCastOneCallback() {}; + float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override; + + bool hit; + b2Vec2 hitPoint; + b2Vec2 hitNormal; + float hitFraction; + + private: + uint16 categoryMask; + bool any; + }; + /** * Creates a new world. **/ @@ -298,6 +315,9 @@ public: **/ int rayCast(lua_State *L); + int rayCastAny(lua_State *L); + int rayCastClosest(lua_State *L); + /** * Destroy this world. **/ diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index 87080dc20..b80b9ae65 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -185,7 +185,7 @@ int w_World_queryFixturesInArea(lua_State *L) return t->queryFixturesInArea(L); } -int w_World_queryBoundingBox(lua_State* L) +int w_World_queryBoundingBox(lua_State *L) { luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryFixturesInArea"); return w_World_queryFixturesInArea(L); @@ -209,6 +209,24 @@ int w_World_rayCast(lua_State *L) return ret; } +int w_World_rayCastAny(lua_State *L) +{ + World *t = luax_checkworld(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->rayCastAny(L); }); + return ret; +} + +int w_World_rayCastClosest(lua_State *L) +{ + World *t = luax_checkworld(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->rayCastClosest(L); }); + return ret; +} + int w_World_destroy(lua_State *L) { World *t = luax_checkworld(L, 1); @@ -245,6 +263,8 @@ static const luaL_Reg w_World_functions[] = { "queryFixturesInArea", w_World_queryFixturesInArea }, { "getFixturesInArea", w_World_getFixturesInArea }, { "rayCast", w_World_rayCast }, + { "rayCastAny", w_World_rayCastAny }, + { "rayCastClosest", w_World_rayCastClosest }, { "destroy", w_World_destroy }, { "isDestroyed", w_World_isDestroyed }, From 6cb0287500a98400b0cb709bcaa963a3e7031cdb Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 2 Oct 2023 12:15:26 -0300 Subject: [PATCH 011/409] Add optional category bit mask to World:getFixturesInArea. --- src/modules/physics/box2d/World.cpp | 9 +++++++-- src/modules/physics/box2d/World.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 27b41dd8e..4e79a1cd4 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -174,8 +174,9 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture) return true; } -World::CollectCallback::CollectCallback(World *world, lua_State *L) +World::CollectCallback::CollectCallback(World *world, uint16 categoryMask, lua_State *L) : world(world) + , categoryMask(categoryMask) , L(L) { lua_newtable(L); @@ -187,6 +188,9 @@ World::CollectCallback::~CollectCallback() bool World::CollectCallback::ReportFixture(b2Fixture *f) { + if (categoryMask != 0xFFFF && (categoryMask & f->GetFilterData().categoryBits) == 0) + return true; + Fixture *fixture = (Fixture *)(f->GetUserData().pointer); if (!fixture) throw love::Exception("A fixture has escaped Memoizer!"); @@ -614,10 +618,11 @@ int World::getFixturesInArea(lua_State *L) float ly = (float)luaL_checknumber(L, 2); float ux = (float)luaL_checknumber(L, 3); float uy = (float)luaL_checknumber(L, 4); + uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF); b2AABB box; box.lowerBound = Physics::scaleDown(b2Vec2(lx, ly)); box.upperBound = Physics::scaleDown(b2Vec2(ux, uy)); - CollectCallback query(this, L); + CollectCallback query(this, categoryMaskBits, L); world->QueryAABB(&query, box); return 1; } diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 75c62bb29..cd214835b 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -106,11 +106,12 @@ public: class CollectCallback : public b2QueryCallback { public: - CollectCallback(World *world, lua_State *L); + CollectCallback(World *world, uint16 categoryMask, lua_State *L); virtual ~CollectCallback(); bool ReportFixture(b2Fixture *fixture) override; private: World *world; + uint16 categoryMask; lua_State *L; int i = 1; }; From da430d514538c6ebf46c2442a5ab6123b2f11797 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 2 Oct 2023 14:05:54 -0300 Subject: [PATCH 012/409] World:rayCastAny and rayCastClosest also return the fixture they hit. --- src/modules/physics/box2d/World.cpp | 18 ++++++++++++++---- src/modules/physics/box2d/World.h | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 4e79a1cd4..db30fcfec 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -242,7 +242,7 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po } World::RayCastOneCallback::RayCastOneCallback(uint16 categoryMask, bool any) - : hit(false) + : hitFixture(nullptr) , hitPoint() , hitNormal() , hitFraction(1.0f) @@ -256,7 +256,7 @@ float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 if (categoryMask != 0xFFFF && (categoryMask & fixture->GetFilterData().categoryBits) == 0) return -1; - hit = true; + hitFixture = fixture; hitPoint = point; hitNormal = normal; hitFraction = fraction; @@ -652,8 +652,13 @@ int World::rayCastAny(lua_State *L) b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2)); RayCastOneCallback raycast(categoryMaskBits, true); world->RayCast(&raycast, v1, v2); - if (raycast.hit) + if (raycast.hitFixture) { + Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer); + if (f == nullptr) + return luaL_error(L, "A fixture has escaped Memoizer!"); + luax_pushtype(L, f); + b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint); lua_pushnumber(L, hitPoint.x); lua_pushnumber(L, hitPoint.y); @@ -676,8 +681,13 @@ int World::rayCastClosest(lua_State *L) b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2)); RayCastOneCallback raycast(categoryMaskBits, false); world->RayCast(&raycast, v1, v2); - if (raycast.hit) + if (raycast.hitFixture) { + Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer); + if (f == nullptr) + return luaL_error(L, "A fixture has escaped Memoizer!"); + luax_pushtype(L, f); + b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint); lua_pushnumber(L, hitPoint.x); lua_pushnumber(L, hitPoint.y); diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index cd214835b..94d2a1e09 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -136,7 +136,7 @@ public: virtual ~RayCastOneCallback() {}; float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override; - bool hit; + b2Fixture *hitFixture; b2Vec2 hitPoint; b2Vec2 hitNormal; float hitFraction; From 03b6b9ff1388cb9da33af41262f7ee537790cd31 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 2 Oct 2023 14:08:21 -0300 Subject: [PATCH 013/409] Fix return value counts... --- src/modules/physics/box2d/World.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index db30fcfec..8e37940c7 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -665,7 +665,7 @@ int World::rayCastAny(lua_State *L) lua_pushnumber(L, raycast.hitNormal.x); lua_pushnumber(L, raycast.hitNormal.y); lua_pushnumber(L, raycast.hitFraction); - return 5; + return 6; } return 0; } @@ -694,7 +694,7 @@ int World::rayCastClosest(lua_State *L) lua_pushnumber(L, raycast.hitNormal.x); lua_pushnumber(L, raycast.hitNormal.y); lua_pushnumber(L, raycast.hitFraction); - return 5; + return 6; } return 0; } From 19df8040df98cdf4912aef110d1e99903616df14 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Wed, 4 Oct 2023 14:43:44 +0100 Subject: [PATCH 014/409] 0.1 Initial commit of a basic test framework, see readme.md for more Most modules are covered with basic unit tests, and there's an example test for a graphics draw (rectangle) and object (File) - for object tests doing more scenario based so we can check multiple things together --- testing/classes/TestMethod.lua | 359 ++++++++++++++++ testing/classes/TestModule.lua | 114 ++++++ testing/classes/TestSuite.lua | 159 ++++++++ testing/conf.lua | 24 ++ testing/main.lua | 172 ++++++++ testing/output/lovetest_runAllTests.html | 1 + testing/output/lovetest_runAllTests.xml | 385 ++++++++++++++++++ testing/readme.md | 139 +++++++ testing/resources/click.ogg | Bin 0 -> 7824 bytes testing/resources/font.ttf | Bin 0 -> 10390 bytes testing/resources/love.dxt1 | Bin 0 -> 2872 bytes testing/resources/love.png | Bin 0 -> 680 bytes .../love_test_graphics_rectangle_expected.png | Bin 0 -> 135 bytes testing/resources/sample.ogv | Bin 0 -> 23845 bytes testing/resources/test.txt | 1 + testing/resources/test.zip | Bin 0 -> 150 bytes testing/tests/audio.lua | 296 ++++++++++++++ testing/tests/data.lua | 182 +++++++++ testing/tests/event.lua | 73 ++++ testing/tests/filesystem.lua | 354 ++++++++++++++++ testing/tests/font.lua | 54 +++ testing/tests/graphics.lua | 158 +++++++ testing/tests/image.lua | 31 ++ testing/tests/math.lua | 178 ++++++++ testing/tests/objects.lua | 175 ++++++++ testing/tests/physics.lua | 306 ++++++++++++++ testing/tests/sound.lua | 19 + testing/tests/system.lua | 68 ++++ testing/tests/thread.lua | 28 ++ testing/tests/timer.lua | 45 ++ testing/tests/video.lua | 10 + testing/tests/window.lua | 336 +++++++++++++++ 32 files changed, 3667 insertions(+) create mode 100644 testing/classes/TestMethod.lua create mode 100644 testing/classes/TestModule.lua create mode 100644 testing/classes/TestSuite.lua create mode 100644 testing/conf.lua create mode 100644 testing/main.lua create mode 100644 testing/output/lovetest_runAllTests.html create mode 100644 testing/output/lovetest_runAllTests.xml create mode 100644 testing/readme.md create mode 100644 testing/resources/click.ogg create mode 100644 testing/resources/font.ttf create mode 100644 testing/resources/love.dxt1 create mode 100644 testing/resources/love.png create mode 100644 testing/resources/love_test_graphics_rectangle_expected.png create mode 100644 testing/resources/sample.ogv create mode 100644 testing/resources/test.txt create mode 100644 testing/resources/test.zip create mode 100644 testing/tests/audio.lua create mode 100644 testing/tests/data.lua create mode 100644 testing/tests/event.lua create mode 100644 testing/tests/filesystem.lua create mode 100644 testing/tests/font.lua create mode 100644 testing/tests/graphics.lua create mode 100644 testing/tests/image.lua create mode 100644 testing/tests/math.lua create mode 100644 testing/tests/objects.lua create mode 100644 testing/tests/physics.lua create mode 100644 testing/tests/sound.lua create mode 100644 testing/tests/system.lua create mode 100644 testing/tests/thread.lua create mode 100644 testing/tests/timer.lua create mode 100644 testing/tests/video.lua create mode 100644 testing/tests/window.lua diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua new file mode 100644 index 000000000..b0c763082 --- /dev/null +++ b/testing/classes/TestMethod.lua @@ -0,0 +1,359 @@ +-- @class - TestMethod +-- @desc - used to run a specific method from a module's /test/ suite +-- each assertion is tracked and then printed to output +TestMethod = { + + + -- @method - TestMethod:new() + -- @desc - create a new TestMethod object + -- @param {string} method - string of method name to run + -- @param {TestMethod} testmethod - parent testmethod this test belongs to + -- @return {table} - returns the new Test object + new = function(self, method, testmodule) + local test = { + testmodule = testmodule, + method = method, + asserts = {}, + start = love.timer.getTime(), + finish = 0, + count = 0, + passed = false, + skipped = false, + skipreason = '', + fatal = '', + message = nil, + result = {}, + colors = { + red = {1, 0, 0, 1}, + green = {0, 1, 0, 1}, + blue = {0, 0, 1, 1}, + black = {0, 0, 0, 1}, + white = {1, 1, 1, 1} + } + } + setmetatable(test, self) + self.__index = self + return test + end, + + + -- @method - TestMethod:assertEquals() + -- @desc - used to assert two values are equals + -- @param {any} expected - expected value of the test + -- @param {any} actual - actual value of the test + -- @param {string} label - label for this test to use in exports + -- @return {nil} + assertEquals = function(self, expected, actual, label) + self.count = self.count + 1 + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = expected == actual, + message = 'expected \'' .. tostring(expected) .. '\' got \'' .. + tostring(actual) .. '\'', + test = label + }) + end, + + + -- @method - TestMethod:assertPixels() + -- @desc - checks a list of coloured pixels agaisnt given imgdata + -- @param {ImageData} imgdata - image data to check + -- @param {table} pixels - map of colors to list of pixel coords, i.e. + -- { blue = { {1, 1}, {2, 2}, {3, 4} } } + -- @return {nil} + assertPixels = function(self, imgdata, pixels, label) + for i, v in pairs(pixels) do + local col = self.colors[i] + local pixels = v + for p=1,#pixels do + local coord = pixels[p] + local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2]) + local compare_id = tostring(coord[1]) .. ',' .. tostring(coord[2]) + -- @TODO add some sort pixel tolerance to the coords + self:assertEquals(col[1], tr, 'check pixel r for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') + self:assertEquals(col[2], tg, 'check pixel g for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') + self:assertEquals(col[3], tb, 'check pixel b for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') + self:assertEquals(col[4], ta, 'check pixel a for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') + end + end + end, + + + -- @method - TestMethod:assertNotEquals() + -- @desc - used to assert two values are not equal + -- @param {any} expected - expected value of the test + -- @param {any} actual - actual value of the test + -- @param {string} label - label for this test to use in exports + -- @return {nil} + assertNotEquals = function(self, expected, actual, label) + self.count = self.count + 1 + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = expected ~= actual, + message = 'avoiding \'' .. tostring(expected) .. '\' got \'' .. + tostring(actual) .. '\'', + test = label + }) + end, + + + -- @method - TestMethod:assertRange() + -- @desc - used to check a value is within an expected range + -- @param {number} actual - actual value of the test + -- @param {number} min - minimum value the actual should be >= to + -- @param {number} max - maximum value the actual should be <= to + -- @param {string} label - label for this test to use in exports + -- @return {nil} + assertRange = function(self, actual, min, max, label) + self.count = self.count + 1 + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = actual >= min and actual <= max, + message = 'value \'' .. tostring(actual) .. '\' out of range \'' .. + tostring(min) .. '-' .. tostring(max) .. '\'', + test = label + }) + end, + + + -- @method - TestMethod:assertMatch() + -- @desc - used to check a value is within a list of values + -- @param {number} list - list of valid values for the test + -- @param {number} actual - actual value of the test to check is in the list + -- @param {string} label - label for this test to use in exports + -- @return {nil} + assertMatch = function(self, list, actual, label) + self.count = self.count + 1 + local found = false + for l=1,#list do + if list[l] == actual then found = true end; + end + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = found == true, + message = 'value \'' .. tostring(actual) .. '\' not found in \'' .. + table.concat(list, ',') .. '\'', + test = label + }) + end, + + + -- @method - TestMethod:assertGreaterEqual() + -- @desc - used to check a value is >= than a certain target value + -- @param {any} target - value to check the test agaisnt + -- @param {any} actual - actual value of the test + -- @param {string} label - label for this test to use in exports + -- @return {nil} + assertGreaterEqual = function(self, target, actual, label) + self.count = self.count + 1 + local passing = false + if target ~= nil and actual ~= nil then + passing = actual >= target + end + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = passing, + message = 'value \'' .. tostring(actual) .. '\' not >= \'' .. + tostring(target) .. '\'', + test = label + }) + end, + + + -- @method - TestMethod:assertLessEqual() + -- @desc - used to check a value is <= than a certain target value + -- @param {any} target - value to check the test agaisnt + -- @param {any} actual - actual value of the test + -- @param {string} label - label for this test to use in exports + -- @return {nil} + assertLessEqual = function(self, target, actual, label) + self.count = self.count + 1 + local passing = false + if target ~= nil and actual ~= nil then + passing = actual <= target + end + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = passing, + message = 'value \'' .. tostring(actual) .. '\' not <= \'' .. + tostring(target) .. '\'', + test = label + }) + end, + + + -- @method - TestMethod:assertObject() + -- @desc - used to check a table is a love object, this runs 3 seperate + -- tests to check table has the basic properties of an object + -- @note - actual object functionality tests are done in the objects module + -- @param {table} obj - table to check is a valid love object + -- @return {nil} + assertObject = function(self, obj) + self:assertNotEquals(nil, obj, 'check not nill') + self:assertEquals('userdata', type(obj), 'check is userdata') + if obj ~= nil then + self:assertNotEquals(nil, obj:type(), 'check has :type()') + end + end, + + + + -- @method - TestMethod:skipTest() + -- @desc - used to mark this test as skipped for a specific reason + -- @param {string} reason - reason why method is being skipped + -- @return {nil} + skipTest = function(self, reason) + self.skipped = true + self.skipreason = reason + end, + + + -- @method - TestMethod:evaluateTest() + -- @desc - evaluates the results of all assertions for a final restult + -- @return {nil} + evaluateTest = function(self) + local failure = '' + local failures = 0 + for a=1,#self.asserts do + -- @TODO just return first failed assertion msg? or all? + -- currently just shows the first assert that failed + if self.asserts[a].passed == false and self.skipped == false then + if failure == '' then failure = self.asserts[a] end + failures = failures + 1 + end + end + if self.fatal ~= '' then failure = self.fatal end + local passed = tostring(#self.asserts - failures) + local total = '(' .. passed .. '/' .. tostring(#self.asserts) .. ')' + if self.skipped == true then + self.testmodule.skipped = self.testmodule.skipped + 1 + love.test.totals[3] = love.test.totals[3] + 1 + self.result = { + total = '', + result = "SKIP", + passed = false, + message = '(0/0) - method skipped [' .. self.skipreason .. ']' + } + else + if failure == '' and #self.asserts > 0 then + self.passed = true + self.testmodule.passed = self.testmodule.passed + 1 + love.test.totals[1] = love.test.totals[1] + 1 + self.result = { + total = total, + result = 'PASS', + passed = true, + message = nil + } + else + self.passed = false + self.testmodule.failed = self.testmodule.failed + 1 + love.test.totals[2] = love.test.totals[2] + 1 + if #self.asserts == 0 then + local msg = 'no asserts defined' + if self.fatal ~= '' then msg = self.fatal end + self.result = { + total = total, + result = 'FAIL', + passed = false, + key = 'test', + message = msg + } + else + local key = failure['key'] + if failure['test'] ~= nil then + key = key .. ' [' .. failure['test'] .. ']' + end + self.result = { + total = total, + result = 'FAIL', + passed = false, + key = key, + message = failure['message'] + } + end + end + end + self:printResult() + end, + + + -- @method - TestMethod:printResult() + -- @desc - prints the result of the test to the console as well as appends + -- the XML + HTML for the test to the testsuite output + -- @return {nil} + printResult = function(self) + + -- get total timestamp + -- @TODO make nicer, just need a 3DP ms value + self.finish = love.timer.getTime() - self.start + love.test.time = love.test.time + self.finish + self.testmodule.time = self.testmodule.time + self.finish + local endtime = tostring(math.floor((love.timer.getTime() - self.start)*1000)) + if string.len(endtime) == 1 then endtime = ' ' .. endtime end + if string.len(endtime) == 2 then endtime = ' ' .. endtime end + if string.len(endtime) == 3 then endtime = ' ' .. endtime end + + -- get failure/skip message for output (if any) + local failure = '' + local output = '' + if self.passed == false and self.skipped == false then + failure = '\t\t\t\n' + output = self.result.key .. ' ' .. self.result.message + end + if output == '' and self.skipped == true then + output = self.skipreason + end + + -- append XML for the test class result + self.testmodule.xml = self.testmodule.xml .. '\t\t\n' .. + failure .. '\t\t\n' + + -- unused currently, adds a preview image for certain graphics methods to the output + local preview = '' + -- if self.testmodule.module == 'graphics' then + -- local filename = 'love_test_graphics_rectangle' + -- preview = '
' .. '

Expected

' .. + -- '

Actual

' + -- end + + -- append HTML for the test class result + local status = '🔴' + local cls = 'red' + if self.passed == true then status = '🟢'; cls = '' end + if self.skipped == true then status = '🟡'; cls = '' end + self.testmodule.html = self.testmodule.html .. + '' .. + '' .. status .. '' .. + '' .. self.method .. '' .. + '' .. tostring(self.finish*1000) .. 'ms' .. + '' .. output .. preview .. '' .. + '' + + -- add message if assert failed + local msg = '' + if self.result.message ~= nil and self.skipped == false then + msg = ' - ' .. self.result.key .. + ' failed - (' .. self.result.message .. ')' + end + if self.skipped == true then + msg = self.result.message + end + + -- log final test result to console + -- i know its hacky but its neat soz + local tested = 'love.' .. self.testmodule.module .. '.' .. self.method .. '()' + local matching = string.sub(self.testmodule.spacer, string.len(tested), 40) + self.testmodule:log( + self.testmodule.colors[self.result.result], + ' ' .. tested .. matching, + ' ==> ' .. self.result.result .. ' - ' .. endtime .. 'ms ' .. + self.result.total .. msg + ) + end + + +} \ No newline at end of file diff --git a/testing/classes/TestModule.lua b/testing/classes/TestModule.lua new file mode 100644 index 000000000..379aac360 --- /dev/null +++ b/testing/classes/TestModule.lua @@ -0,0 +1,114 @@ +-- @class - TestModule +-- @desc - used to run tests for a given module, each test method will spawn +-- a love.test.Test object +TestModule = { + + + -- @method - TestModule:new() + -- @desc - create a new Suite object + -- @param {string} module - string of love module the suite is for + -- @return {table} - returns the new Suite object + new = function(self, module, method) + local testmodule = { + timer = 0, + time = 0, + delay = 0.1, + spacer = ' ', + colors = { + PASS = 'green', FAIL = 'red', SKIP = 'grey' + }, + colormap = { + grey = '\27[37m', + green = '\27[32m', + red = '\27[31m', + yellow = '\27[33m' + }, + xml = '', + html = '', + tests = {}, + running = {}, + called = {}, + passed = 0, + failed = 0, + skipped = 0, + module = module, + method = method, + index = 1, + start = false, + } + setmetatable(testmodule, self) + self.__index = self + return testmodule + end, + + + -- @method - TestModule:log() + -- @desc - log to console with specific colors, split out to make it easier + -- to adjust all console output across the tests + -- @param {string} color - color key to use for the log + -- @param {string} line - main message to write (LHS) + -- @param {string} result - result message to write (RHS) + -- @return {nil} + log = function(self, color, line, result) + if result == nil then result = '' end + print(self.colormap[color] .. line .. result) + end, + + + -- @method - TestModule:runTests() + -- @desc - starts the running of tests and sets up the list of methods to test + -- @param {string} module - module to set for the test suite + -- @param {string} method - specific method to test, if nil all methods tested + -- @return {nil} + runTests = function(self) + self.running = {} + self.passed = 0 + self.failed = 0 + if self.method ~= nil then + table.insert(self.running, self.method) + else + for i,_ in pairs(love.test[self.module]) do + table.insert(self.running, i) + end + table.sort(self.running) + end + self.index = 1 + self.start = true + self:log('yellow', '\nlove.' .. self.module .. '.testmodule.start') + end, + + + -- @method - TestModule:printResult() + -- @desc - prints the result of the module to the console as well as appends + -- the XML + HTML for the test to the testsuite output + -- @return {nil} + printResult = function(self) + -- add xml to main output + love.test.xml = love.test.xml .. '\t\n' .. self.xml .. '\t\n' + -- add html to main output + local status = '🔴' + if self.failed == 0 then status = '🟢' end + love.test.html = love.test.html .. '

' .. status .. ' love.' .. self.module .. '

    ' .. + '
  • 🟢 ' .. tostring(self.passed) .. ' Tests
  • ' .. + '
  • 🔴 ' .. tostring(self.failed) .. ' Failures
  • ' .. + '
  • 🟡 ' .. tostring(self.skipped) .. ' Skipped
  • ' .. + '
  • ' .. tostring(self.time*1000) .. 'ms
  • ' .. '


      ' .. + '' .. + self.html .. '
      MethodTimeDetails
      ' + -- print module results to console + self:log('yellow', 'love.' .. self.module .. '.testmodule.end') + local failedcol = '\27[31m' + if self.failed == 0 then failedcol = '\27[37m' end + self:log('green', tostring(self.passed) .. ' PASSED' .. ' || ' .. + failedcol .. tostring(self.failed) .. ' FAILED || \27[37m' .. + tostring(self.skipped) .. ' SKIPPED') + self.start = false + self.fakequit = false + end + + +} \ No newline at end of file diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua new file mode 100644 index 000000000..234019c8f --- /dev/null +++ b/testing/classes/TestSuite.lua @@ -0,0 +1,159 @@ +TestSuite = { + + + -- @method - TestSuite:new() + -- @desc - creates a new TestSuite object that handles all the tests + -- @return {table} - returns the new TestSuite object + new = function(self) + local test = { + + -- testsuite internals + modules = {}, + module = nil, + testcanvas = love.graphics.newCanvas(16, 16), + current = 1, + output = '', + totals = {0, 0, 0}, + time = 0, + xml = '', + html = '', + fakequit = false, + windowmode = true, + + -- love modules to test + audio = {}, + data = {}, + event = {}, + filesystem = {}, + font = {}, + graphics = {}, + image = {}, + joystick = {}, + math = {}, + mouse = {}, + objects = {}, -- special for all object class contructor tests + physics = {}, + sound = {}, + system = {}, + thread = {}, + timer = {}, + touch = {}, + video = {}, + window = {} + + } + setmetatable(test, self) + self.__index = self + return test + end, + + + -- @method - TestSuite:runSuite() + -- @desc - called in love.update, runs through every method or every module + -- @param {number} delta - delta from love.update to track time elapsed + -- @return {nil} + runSuite = function(self, delta) + + -- stagger 0.1s between tests + if self.module ~= nil then + self.module.timer = self.module.timer + delta + if self.module.timer >= self.module.delay then + self.module.timer = self.module.timer - self.module.delay + if self.module.start == true then + + -- work through each test method 1 by 1 + if self.module.index <= #self.module.running then + + -- run method once + if self.module.called[self.module.index] == nil then + self.module.called[self.module.index] = true + local method = self.module.running[self.module.index] + local test = TestMethod:new(method, self.module) + + -- check method exists in love first + if self.module.module ~= 'objects' and (love[self.module.module] == nil or love[self.module.module][method] == nil) then + local tested = 'love.' .. self.module.module .. '.' .. method .. '()' + local matching = string.sub(self.module.spacer, string.len(tested), 40) + self.module:log(self.module.colors['FAIL'], + tested .. matching, + ' ==> FAIL (0/0) - call failed - method does not exist' + ) + -- otherwise run the test method then eval the asserts + else + local ok, chunk, err = pcall(self[self.module.module][method], test) + if ok == false then + print("FATAL", chunk, err) + test.fatal = tostring(chunk) .. tostring(err) + end + local ok, chunk, err = pcall(test.evaluateTest, test) + if ok == false then + print("FATAL", chunk, err) + test.fatal = tostring(chunk) .. tostring(err) + end + end + -- move onto the next test + self.module.index = self.module.index + 1 + end + + else + + -- print module results and add to output + self.module:printResult() + + -- if we have more modules to go run the next one + self.current = self.current + 1 + if #self.modules >= self.current then + self.module = self.modules[self.current] + self.module:runTests() + + -- otherwise print the final results and export output + else + self:printResult() + love.event.quit(0) + end + + end + end + end + end + end, + + + -- @method - TestSuite:printResult() + -- @desc - prints the result of the whole test suite as well as writes + -- the XML + HTML of the testsuite output + -- @return {nil} + printResult = function(self) + local finaltime = tostring(math.floor(self.time*1000)) + if string.len(finaltime) == 1 then finaltime = ' ' .. finaltime end + if string.len(finaltime) == 2 then finaltime = ' ' .. finaltime end + if string.len(finaltime) == 3 then finaltime = ' ' .. finaltime end + + local xml = '\n' + + local status = '🔴' + if self.totals[2] == 0 then status = '🟢' end + local html = '

      ' .. status .. ' love.test

        ' + html = html .. + '
      • 🟢 ' .. tostring(self.totals[1]) .. ' Tests
      • ' .. + '
      • 🔴 ' .. tostring(self.totals[2]) .. ' Failures
      • ' .. + '
      • 🟡 ' .. tostring(self.totals[3]) .. ' Skipped
      • ' .. + '
      • ' .. tostring(self.time*1000) .. 'ms


      ' + + -- @TODO use mountFullPath to write output to src? + love.filesystem.createDirectory('output') + love.filesystem.write('output/' .. self.output .. '.xml', xml .. self.xml .. '') + love.filesystem.write('output/' .. self.output .. '.html', html .. self.html .. '
      ') + + self.module:log('grey', '\nFINISHED - ' .. finaltime .. 'ms\n') + local failedcol = '\27[31m' + if self.totals[2] == 0 then failedcol = '\27[37m' end + self.module:log('green', tostring(self.totals[1]) .. ' PASSED' .. ' || ' .. failedcol .. tostring(self.totals[2]) .. ' FAILED || \27[37m' .. tostring(self.totals[3]) .. ' SKIPPED') + + end + + +} \ No newline at end of file diff --git a/testing/conf.lua b/testing/conf.lua new file mode 100644 index 000000000..9f1ba5789 --- /dev/null +++ b/testing/conf.lua @@ -0,0 +1,24 @@ +function love.conf(t) + t.console = true + t.window.name = 'love.test' + t.window.width = 256 + t.window.height = 256 + t.window.resizable = true + t.renderers = {"opengl"} + t.modules.audio = true + t.modules.data = true + t.modules.event = true + t.modules.filesystem = true + t.modules.font = true + t.modules.graphics = true + t.modules.image = true + t.modules.math = true + t.modules.objects = true + t.modules.physics = true + t.modules.sound = true + t.modules.system = true + t.modules.thread = true + t.modules.timer = true + t.modules.video = true + t.modules.window = true +end \ No newline at end of file diff --git a/testing/main.lua b/testing/main.lua new file mode 100644 index 000000000..205f0b786 --- /dev/null +++ b/testing/main.lua @@ -0,0 +1,172 @@ +-- & 'c:\Program Files\LOVE\love.exe' ./ --console +-- /Applications/love.app/Contents/MacOS/love ./ + +-- load test objs +require('classes.TestSuite') +require('classes.TestModule') +require('classes.TestMethod') + +-- create testsuite obj +love.test = TestSuite:new() + +-- load test scripts if module is active +if love.audio ~= nil then require('tests.audio') end +if love.data ~= nil then require('tests.data') end +if love.event ~= nil then require('tests.event') end +if love.filesystem ~= nil then require('tests.filesystem') end +if love.font ~= nil then require('tests.font') end +if love.graphics ~= nil then require('tests.graphics') end +if love.image ~= nil then require('tests.image') end +if love.math ~= nil then require('tests.math') end +if love.physics ~= nil then require('tests.physics') end +if love.sound ~= nil then require('tests.sound') end +if love.system ~= nil then require('tests.system') end +if love.thread ~= nil then require('tests.thread') end +if love.timer ~= nil then require('tests.timer') end +if love.video ~= nil then require('tests.video') end +if love.window ~= nil then require('tests.window') end +require('tests.objects') + +-- love.load +-- load given arguments and run the test suite +love.load = function(args) + + -- setup basic img to display + if love.window ~= nil then + love.window.setMode(256, 256, { + fullscreen = false, + resizable = true, + centered = true + }) + if love.graphics ~= nil then + love.graphics.setDefaultFilter("nearest", "nearest") + love.graphics.setLineStyle('rough') + love.graphics.setLineWidth(1) + Logo = { + texture = love.graphics.newImage('resources/love.png'), + img = nil + } + Logo.img = love.graphics.newQuad(0, 0, 64, 64, Logo.texture) + end + end + + -- get all args with any comma lists split out as seperate + local arglist = {} + for a=1,#args do + local splits = UtilStringSplit(args[a], '([^,]+)') + for s=1,#splits do + table.insert(arglist, splits[s]) + end + end + + -- convert args to the cmd to run, modules, method (if any) and disabled + local testcmd = '--runAllTests' + local module = '' + local method = '' + local modules = { + 'audio', 'data', 'event', 'filesystem', 'font', 'graphics', + 'image', 'math', 'objects', 'physics', 'sound', 'system', + 'thread', 'timer', 'video', 'window' + } + for a=1,#arglist do + if testcmd == '--runSpecificMethod' then + if module == '' and love[ arglist[a] ] ~= nil then + module = arglist[a] + table.insert(modules, module) + end + if module ~= '' and love[module][ arglist[a] ] ~= nil and method == '' then + method = arglist[a] + end + end + if testcmd == '--runSpecificModules' then + if love[ arglist[a] ] ~= nil or arglist[a] == 'objects' then + table.insert(modules, arglist[a]) + end + end + if arglist[a] == '--runSpecificMethod' then + testcmd = arglist[a] + modules = {} + end + if arglist[a] == '--runSpecificModules' then + testcmd = arglist[a] + modules = {} + end + end + + -- runSpecificMethod uses the module + method given + if testcmd == '--runSpecificMethod' then + local testmodule = TestModule:new(module, method) + table.insert(love.test.modules, testmodule) + love.test.module = testmodule + love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"') + love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method + end + + -- runSpecificModules runs all methods for all the modules given + if testcmd == '--runSpecificModules' then + local modulelist = {} + for m=1,#modules do + local testmodule = TestModule:new(modules[m]) + table.insert(love.test.modules, testmodule) + table.insert(modulelist, modules[m]) + end + + love.test.module = love.test.modules[1] + love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"') + love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_') + end + + -- otherwise default runs all methods for all modules + if arglist[1] == nil or arglist[1] == '' or arglist[1] == '--runAllTests' then + for m=1,#modules do + local testmodule = TestModule:new(modules[m]) + table.insert(love.test.modules, testmodule) + end + love.test.module = love.test.modules[1] + love.test.module:log('grey', '--runAllTests') + love.test.output = 'lovetest_runAllTests' + end + + -- invalid command + if love.test.module == nil then + print("Wrong flags used") + end + + -- start first module + love.test.module:runTests() + +end + +-- love.update +-- run test suite logic +love.update = function(delta) + love.test:runSuite(delta) +end + + +-- love.draw +-- draw a little logo to the screen +love.draw = function() + love.graphics.draw(Logo.texture, Logo.img, 64, 64, 0, 2, 2) +end + + +-- love.quit +-- add a hook to allow test modules to fake quit +love.quit = function() + if love.test.module ~= nil and love.test.module.fakequit == true then + return true + else + return false + end +end + + +-- string split helper +function UtilStringSplit(str, splitter) + local splits = {} + for word in string.gmatch(str, splitter) do + table.insert(splits, word) + end + return splits +end \ No newline at end of file diff --git a/testing/output/lovetest_runAllTests.html b/testing/output/lovetest_runAllTests.html new file mode 100644 index 000000000..164ade985 --- /dev/null +++ b/testing/output/lovetest_runAllTests.html @@ -0,0 +1 @@ +

      🔴 love.test

      • 🟢 157 Tests
      • 🔴 5 Failures
      • 🟡 11 Skipped
      • 7341.71ms


      🟢 love.audio

      • 🟢 26 Tests
      • 🔴 0 Failures
      • 🟡 0 Skipped
      • 0.40991666666712ms


        • MethodTimeDetails
          🟢getActiveEffects0.045083333333418ms
          🟢getActiveSourceCount1.1385ms
          🟢getDistanceModel0.018125000000202ms
          🟢getDopplerScale0.012208333333374ms
          🟢getEffect0.035250000000042ms
          🟢getMaxSceneEffects0.0089583333331422ms
          🟢getMaxSourceEffects0.022874999999978ms
          🟢getOrientation0.037541666666696ms
          🟢getPosition0.024500000000316ms
          🟢getRecordingDevices0.039250000000157ms
          🟢getVelocity0.021333333333207ms
          🟢getVolume0.046083333333335ms
          🟢isEffectsSupported0.016749999999899ms
          🟢newQueueableSource0.041958333333314ms
          🟢newSource2.8378333333332ms
          🟢pause2.6265416666664ms
          🟢play1.7924166666665ms
          🟢setDistanceModel0.023249999999919ms
          🟢setDopplerScale0.094375000000646ms
          🟢setEffect0.024166666666936ms
          🟢setMixWithSystem0.0052083333330621ms
          🟢setOrientation0.017000000000156ms
          🟢setPosition0.0091666666666157ms
          🟢setVelocity0.0070416666657636ms
          🟢setVolume0.0075833333332831ms
          🟢stop1.787666666667ms

          🟢 love.data

          • 🟢 7 Tests
          • 🔴 0 Failures
          • 🟡 3 Skipped
          • 0.34008333333449ms


            • MethodTimeDetails
              🟢compress0.39495833333403ms
              🟢decode0.027791666666666ms
              🟢decompress0.28366666666635ms
              🟢encode0.044000000000377ms
              🟡getPackedSize0.0069999999996462msdont understand lua packing types
              🟢hash0.12045833333341ms
              🟢newByteData0.021916666666844ms
              🟢newDataView0.025416666666889ms
              🟡pack0.0070833333332132msdont understand lua packing types
              🟡unpack0.0091250000000542msdont understand lua packing types

              🟢 love.event

              • 🟢 4 Tests
              • 🔴 0 Failures
              • 🟡 2 Skipped
              • 0.47999999999884ms


                • MethodTimeDetails
                  🟢clear0.028666666666233ms
                  🟢poll0.022374999999464ms
                  🟡pump0.0079583333327804msnot sure we can test when its internal?
                  🟢push0.022500000000036ms
                  🟢quit0.014125000000753ms
                  🟡wait0.0069166666669673msnot sure on best way to test this

                  🔴 love.filesystem

                  • 🟢 26 Tests
                  • 🔴 1 Failures
                  • 🟡 2 Skipped
                  • 1.0150000000023ms


                    • MethodTimeDetails
                      🟢append1.3135833333333ms
                      🟢areSymlinksEnabled0.01433333333356ms
                      🟢createDirectory0.39929166666663ms
                      🟢getAppdataDirectory0.014166666668203ms
                      🟢getCRequirePath0.015749999999315ms
                      🟢getDirectoryItems1.0962083333332ms
                      🟢getIdentity0.10579166666691ms
                      🟢getInfo0.9892916666665ms
                      🟢getRealDirectory0.98024999999957ms
                      🟢getRequirePath0.097583333333873ms
                      🟢getSaveDirectory0.01891666666598ms
                      🟡getSource0.020666666666003msnot sure we can test when its internal?
                      🟢getSourceBaseDirectory0.015083333334331ms
                      🟢getUserDirectory0.043666666666553ms
                      🟢getWorkingDirectory0.018791666667184ms
                      🟢isFused0.017999999998963ms
                      🟢lines13.630166666666ms
                      🟢load7.9870833333331ms
                      🟢mount0.48216666666789ms
                      🔴newFile0.37395833333331msassert #2 [check file made] avoiding 'nil' got 'nil'
                      🟢newFileData0.030666666666512ms
                      🟢read0.19545833333368ms
                      🟢remove0.81487500000055ms
                      🟢setCRequirePath0.017416666667103ms
                      🟢setIdentity0.086666666666346ms
                      🟢setRequirePath0.014500000001583ms
                      🟡setSource0.0082916666652721msnot sure we can test when its internal?
                      🟢unmount1.1363333333341ms
                      🟢write1.0965416666666ms

                      🟢 love.font

                      • 🟢 4 Tests
                      • 🔴 0 Failures
                      • 🟡 1 Skipped
                      • 0.11233333333444ms


                        • MethodTimeDetails
                          🟡newBMFontRasterizer0.007625000002065mswiki and source dont match, not sure expected usage
                          🟢newGlyphData0.28787499999972ms
                          🟢newImageRasterizer0.22408333333424ms
                          🟢newRasterizer0.18954166666596ms
                          🟢newTrueTypeRasterizer0.18991666666501ms

                          🔴 love.graphics

                          • 🟢 0 Tests
                          • 🔴 1 Failures
                          • 🟡 0 Skipped
                          • 0.94387500000009ms


                            • MethodTimeDetails
                              🔴rectangle3.7313333333344msassert #2 [check 0x,0y G] expected '1' got '0'

                              🟢 love.image

                              • 🟢 3 Tests
                              • 🔴 0 Failures
                              • 🟡 0 Skipped
                              • 1.2476249999999ms


                                • MethodTimeDetails
                                  🟢isCompressed0.21679166666644ms
                                  🟢newCompressedData0.19920833333309ms
                                  🟢newImageData0.40049999999958ms

                                  🟢 love.math

                                  • 🟢 16 Tests
                                  • 🔴 0 Failures
                                  • 🟡 0 Skipped
                                  • 0.062999999998231ms


                                    • MethodTimeDetails
                                      🟢colorFromBytes0.29325000000036ms
                                      🟢colorToBytes0.27899999999903ms
                                      🟢gammaToLinear0.021624999998693ms
                                      🟢getRandomSeed0.014708333333502ms
                                      🟢getRandomState0.071791666666599ms
                                      🟢isConvex0.056666666665706ms
                                      🟢linearToGamma0.01791666666584ms
                                      🟢newBezierCurve0.053125000000875ms
                                      🟢newRandomGenerator0.019874999999558ms
                                      🟢newTransform0.02287499999909ms
                                      🟢noise0.076916666666094ms
                                      🟢random0.17783333333377ms
                                      🟢randomNormal0.020458333334972ms
                                      🟢setRandomSeed0.019541666667067ms
                                      🟢setRandomState0.053750000001074ms
                                      🟢triangulate0.023874999998341ms

                                      🟢 love.objects

                                      • 🟢 0 Tests
                                      • 🔴 0 Failures
                                      • 🟡 0 Skipped
                                      • 1.6546249999983ms


                                        • MethodTimeDetails

                                          🔴 love.physics

                                          • 🟢 21 Tests
                                          • 🔴 1 Failures
                                          • 🟡 0 Skipped
                                          • 0.014583333332624ms


                                            • MethodTimeDetails
                                              🟢getDistance0.075333333334981ms
                                              🟢getMeter0.015125000000893ms
                                              🟢newBody0.03362500000037ms
                                              🟢newChainShape0.028624999998783ms
                                              🟢newCircleShape0.020624999999441ms
                                              🟢newDistanceJoint0.037833333333737ms
                                              🟢newEdgeShape0.020624999999441ms
                                              🟢newFixture0.077750000000876ms
                                              🟢newFrictionJoint0.031708333333214ms
                                              🔴newGearJoint0.12670833333139mstest tests/physics.lua:134: Box2D assertion failed: m_bodyA->m_type == b2_dynamicBody
                                              🟢newMotorJoint0.092416666667816ms
                                              🟢newMouseJoint0.050208333334467ms
                                              🟢newPolygonShape0.025333333333322ms
                                              🟢newPrismaticJoint0.034124999999108ms
                                              🟢newPulleyJoint0.035041666665236ms
                                              🟢newRectangleShape0.077833333332222ms
                                              🟢newRevoluteJoint0.040416666667653ms
                                              🟢newRopeJoint0.03037500000147ms
                                              🟢newWeldJoint0.074916666664038ms
                                              🟢newWheelJoint0.1102083333322ms
                                              🟢newWorld0.075416666666328ms
                                              🟢setMeter0.031208333336252ms

                                              🟢 love.sound

                                              • 🟢 2 Tests
                                              • 🔴 0 Failures
                                              • 🟡 0 Skipped
                                              • 0.93524999999842ms


                                                • MethodTimeDetails
                                                  🟢newDecoder0.31383333333501ms
                                                  🟢newSoundData1.1787083333292ms

                                                  🟢 love.system

                                                  • 🟢 6 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 2 Skipped
                                                  • 1.3057500000059ms


                                                    • MethodTimeDetails
                                                      🟢getClipboardText1.6217916666665ms
                                                      🟢getOS0.034041666669538ms
                                                      🟢getPowerInfo0.080041666665309ms
                                                      🟢getProcessorCount0.017791666669709ms
                                                      🟢hasBackgroundMusic0.086708333334684ms
                                                      🟡openURL0.016333333334728msgets annoying to test everytime
                                                      🟢setClipboardText0.59291666666716ms
                                                      🟡vibrate0.0090416666651549mscant really test this

                                                      🟢 love.thread

                                                      • 🟢 3 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 0 Skipped
                                                      • 0.96195833333323ms


                                                        • MethodTimeDetails
                                                          🟢getChannel0.47320833333231ms
                                                          🟢newChannel0.028374999999414ms
                                                          🟢newThread0.2556250000012ms

                                                          🟢 love.timer

                                                          • 🟢 6 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 0 Skipped
                                                          • 3713.5796666667ms


                                                            • MethodTimeDetails
                                                              🟢getAverageDelta0.023208333331581ms
                                                              🟢getDelta0.015708333332753ms
                                                              🟢getFPS0.011125000000334ms
                                                              🟢getTime1001.1531666667ms
                                                              🟢sleep1000.4330833333ms
                                                              🟢step0.032958333331834ms

                                                              🟢 love.video

                                                              • 🟢 1 Tests
                                                              • 🔴 0 Failures
                                                              • 🟡 0 Skipped
                                                              • 0.67754166666772ms


                                                                • MethodTimeDetails
                                                                  🟢newVideoStream3.4201249999981ms

                                                                  🔴 love.window

                                                                  • 🟢 32 Tests
                                                                  • 🔴 2 Failures
                                                                  • 🟡 1 Skipped
                                                                  • 7985.3964583333ms


                                                                    • MethodTimeDetails
                                                                      🟢close11.641583333336ms
                                                                      🟢fromPixels0.015333333330148ms
                                                                      🟢getDPIScale0.014499999998918ms
                                                                      🟢getDesktopDimensions0.015083333330779ms
                                                                      🟢getDisplayCount0.010291666665552ms
                                                                      🟢getDisplayName0.014875000001524ms
                                                                      🟢getDisplayOrientation0.016250000001605ms
                                                                      🟢getFullscreen1305.7451666667ms
                                                                      🟢getFullscreenModes0.48033333332853ms
                                                                      🟢getIcon2.0577083333322ms
                                                                      🟢getMode0.10416666667012ms
                                                                      🟢getPosition4.9660833333327ms
                                                                      🟢getSafeArea0.067875000002715ms
                                                                      🟢getTitle0.55745833333276ms
                                                                      🟢getVSync0.095124999997864ms
                                                                      🟢hasFocus0.055624999998116ms
                                                                      🟢hasMouseFocus0.022541666666598ms
                                                                      🟢isDisplaySleepEnabled0.14775000000355ms
                                                                      🔴isMaximized642.02083333333msassert #2 [check window not maximized] expected 'true' got 'false'
                                                                      🟢isMinimized641.41475ms
                                                                      🟢isOpen25.519625000001ms
                                                                      🟢isVisible18.191791666666ms
                                                                      🔴maximize0.23570833333508msassert #1 [check window maximized] expected 'true' got 'false'
                                                                      🟢minimize640.26066666666ms
                                                                      🟢restore643.01916666667ms
                                                                      🟢setDisplaySleepEnabled0.59508333333014ms
                                                                      🟢setFullscreen1329.778375ms
                                                                      🟢setIcon2.0223750000028ms
                                                                      🟢setMode4.5707499999992ms
                                                                      🟢setPosition0.16512499999521ms
                                                                      🟢setTitle0.47262500000045ms
                                                                      🟢setVSync0.022583333333159ms
                                                                      🟡showMessageBox0.068958333333313msskipping cos annoying to test with
                                                                      🟢toPixels0.067666666666355ms
                                                                      🟢updateMode6.8227083333348ms
      \ No newline at end of file diff --git a/testing/output/lovetest_runAllTests.xml b/testing/output/lovetest_runAllTests.xml new file mode 100644 index 000000000..a30afbbc2 --- /dev/null +++ b/testing/output/lovetest_runAllTests.xml @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/readme.md b/testing/readme.md new file mode 100644 index 000000000..4533e8c45 --- /dev/null +++ b/testing/readme.md @@ -0,0 +1,139 @@ +# löve.test +Basic testing suite for the löve APIs, based off of [this issue](https://github.com/love2d/love/issues/1745) + +Currently written for löve 12 + +--- + +## Primary Goals +- [x] Simple pass/fail tests in Lua with minimal setup +- [x] Ability to run all tests with a simple command. +- [x] Ability to see how many tests are passing/failing +- [x] No platform-specific dependencies / scripts +- [x] Ability to run a subset of tests +- [x] Ability to easily run an individual test. + +--- + +## Running Tests +The initial pass is to keep things as simple as possible, and just run all the tests inside Löve to match how they'd be used by developers in-engine. +To run the tests, download the repo and then run the main.lua as you would a löve game, i.e: + +WINDOWS: `& 'c:\Program Files\LOVE\love.exe' PATH_TO_TESTING_FOLDER --console` +MACOS: `/Applications/love.app/Contents/MacOS/love PATH_TO_TESTING_FOLDER` + +By default all tests will be run for all modules. + +If you want to specify a module you can add: +`--runSpecificModules filesystem` +For multiple modules, provide a comma seperate list: +`--runSpecificModules filesystem,audio,data"` + +If you want to specify only 1 specific method only you can use: +`--runSpecificMethod filesystem write` + +All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level. + +An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in your save directory, along with a `HTML` file with a summary of all tests (including visuals for love.graphics tests). +> Note that this can only be viewed properly locally as the generated images are written to the save directory. +> An example of both types of output can be found in the `/output` folder + +--- + +## Architecture +Each method has it's own test method written in `/tests` under the matching module name. + +When you run the tests, a single TestSuite object is created which handles the progress + totals for all the tests. +Each module has a TestModule object created, and each test method has a TestMethod object created which keeps track of assertions for that method. You can currently do the following assertions: +- **assertEquals**(expected, actual) +- **assertNotEquals**(expected, actual) +- **assertRange**(actual, min, max) +- **assertMatch**({option1, option2, option3 ...}, actual) +- **assertGreaterEqual**(expected, actual) +- **assertLessEqual**(expected, actual) +- **assertObject**(table) + +Example test method: +```lua +-- love.filesystem.read test method +-- all methods should be put under love.test.MODULE.METHOD, matching the API +love.test.filesystem.read = function(test) + -- setup any data needed then run any asserts using the passed test object + local content, size = love.filesystem.read('resources/test.txt') + test:assertNotEquals(nil, content, 'check not nil') + test:assertEquals('helloworld', content, 'check content match') + test:assertEquals(10, size, 'check size match') + content, size = love.filesystem.read('resources/test.txt', 5) + test:assertNotEquals(nil, content, 'check not nil') + test:assertEquals('hello', content, 'check content match') + test:assertEquals(5, size, 'check size match') + -- no need to return anything just cleanup any objs if needed +end +``` + +After each test method is ran, the assertions are totalled up, printed, and we move onto the next method! Once all methods in the suite are run a total pass/fail/skip is given for that module and we move onto the next module (if any) + +For sanity-checking, if it's currently not covered or we're not sure how to test yet we can set the test to be skipped with `test:skipTest(reason)` - this way we still see the method listed in the tests without it affected the pass/fail totals + +--- + +## Coverage +This is the status of all module tests currently. +"objects" is a special module to cover any object specific tests, i.e. testing a File object functions as expected +```lua +-- [x] audio 26 PASSED | 0 FAILED | 0 SKIPPED +-- [x] data 7 PASSED | 0 FAILED | 3 SKIPPED [SEE BELOW] +-- [x] event 4 PASSED | 0 FAILED | 2 SKIPPED [SEE BELOW] +-- [x] filesystem 26 PASSED | 1 FAILED | 2 SKIPPED [SEE BELOW] +-- [x] font 4 PASSED | 0 FAILED | 1 SKIPPED [SEE BELOW] +-- [ ] graphics STILL TO BE DONE +-- [x] image 3 PASSED | 0 FAILED | 0 SKIPPED +-- [x] math 16 PASSED | 0 FAILED | 0 SKIPPED [SEE BELOW] +-- [x] physics 21 PASSED | 1 FAILED | 0 SKIPPED [SEE BELOW] +-- [x] sound 2 PASSED | 0 FAILED | 0 SKIPPED +-- [x] system 7 PASSED | 0 FAILED | 1 SKIPPED +-- [ ] thread 3 PASSED | 0 FAILED | 0 SKIPPED +-- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED [SEE BELOW] +-- [x] video 1 PASSED | 0 FAILED | 0 SKIPPED +-- [x] window 32 PASSED | 2 FAILED | 1 SKIPPED [SEE BELOW] +-- [ ] objects STILL TO BE DONE +``` + +The following modules are not covered as we can't really emulate input nicely: +`joystick`, `keyboard`, `mouse`, and `touch` + +--- + +## Todo / Skipped +Modules with some small bits needed or needing sense checking: +- **love.data** - packing methods need writing cos i dont really get what they are +- **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check +- **love.filesystem** - getSource() / setSource() dont think we can test +- **love.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected +- **love.timer** - couple methods I don't know if you could reliably test specific values +- **love.image** - ideally isCompressed should have an example of all compressed files love can take +- **love.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back +- **love.window** - couple stuff just nil checked as I think it's hardware dependent, needs checking + +Modules still to be completed or barely started +- **love.graphics** - done 1 as an example of how we can test the drawing but not really started +- **love.objects** - done 1 as an example of how we can test objs with mini scenarios + +--- + +## Failures +- **love.window.isMaximized()** - returns false after calling love.window.maximize? +- **love.window.maximize()** - same as above +- **love.filesystem.newFile()** - something changed in 12 +- **love.physics.newGearJoint()** - something changed in 12 + +--- + +## Stretch Goals +- [ ] Tests can compare visual results to a reference image +- [ ] Ability to see all visual results at a glance +- [ ] Automatic testing that happens after every commit +- [ ] Ability to test loading different combinations of modules +- [ ] Performance tests + +There is some unused code in the Test.lua class to add preview vs actual images to the HTML output \ No newline at end of file diff --git a/testing/resources/click.ogg b/testing/resources/click.ogg new file mode 100644 index 0000000000000000000000000000000000000000..49707b3e817594afb36299302c2b80821a0d7f02 GIT binary patch literal 7824 zcmcgxc|6oz+y7By-=cs9n2&O z7%bebx}Gugb>Z=Fvo|Bn&!fX5DFK(1kd!#bBW&pD<#yHA$VmOCRQeFiQeK}PXwQnd?aWDphLgX{5NQLhtCA&3crt_X-Qq&Vw{6ruBl zgVWL4#2Qv2IvpL2g*n8*alZ>5DMvO4It-zNsS_T|>$vyJyTF7JeDmbp4CG39j>H&! zkf(mOamvA~xV{+a)h{AQMQ=#~0D)Asc_Ud7#KJy`_YMpccR78#c}uckF?o}w1eIGmA6Btw}_b}Iu99?$1k5YD^kG6QSec|;84V! zN92$r5fUEiWImDP2Rg;h?v-wtjjrX5o;|fno+@C)MSr2(p&H`b)H4-?|>-ZzT}b z4neALPOJ~-OMnJKeArjo+)ruDPk#(RK}6)gr&}a@0fO*mJEys$sLmzYkzhfAX<_+P z7w8UF0t`|4pLj5@F>8JD44ApRQr67jr_m;vLM^4~nIsK*^s~eZ&|2>A3 zJb1TAAy<5Yrf%u&iwJh1BL8rb)qgJ9tXoRjv(Sb(+rSdo?o~L9dImw-L-&Z0f zz$^Z#xbFf3%qIu`kq3To8nFn1JSZt{d``*K#MC^{)AD}6L{p^Ac);{n$n;pe?eRPR zZdiYL4g{Pgg5;BE`#5-4)@=hd>H`J;_8cG9t|ZQvNdkY?3g{1s^{q-7u1O6Z)i9FM zH)gXLWD6KR=432mGc4^iZ0a-;==8SH=~7dOW#cc0IdGflv4DSg4$(#U@vlTQVwxkO`1GjbM73uyk$b6jIe(ql@ZViuwjgrn2kqA_JH1s<;| zmsLew2v4e z#77X)BM5O*6Q%#|F`#!uN`F`i0GkRy?7)7oNAlwkEGciSmY-V0z^RHT=irg7x6>lJ z($!uW85B6s@Xkq;49VY#OL}KdlOd^Q`9mo%j`yw-EL-if043P=4nsx|M5)84Bk*!n zu|R8GY+yE8ks0+VSSo%&Cr4{7hzrtL58~2KQA}DGlmf>B83TBZspa#ElB49vpjd%m zE}d1yWH3OVl{Y4>IGStVs7B7I81-SPd`wz#FdrZ>LNR(q(sr1f&l#tN{Y{HY%d9Qa zc-wM>FsFu1YyjzKp2ph)++NJ^oIb`mMygLLy1?z3lz1N?PhozON=7Ecv3ka)EtN~p z0+a?#Obh-d!MADWI1`!OFd{4(!x3&)7?%Uml|)`I{#>RvY?@I}hOilnT)JLR+6tzM zE-v#m1td6#U+WD9L>H8^XqY--DrrVW)Q182g+!LonzET12WAv6N$QUkl~vNdWz!!? z{YAD`(wb9(uO}tcLriV2l+As&)-xjkHqDi;Wxq-DR6s%yitGr4f{wmY1rU;Q(V@1MoNE8-H27+*wp6uFU~KmwRDPxq^7X|VnpyS3GB<9a$wJcofl#^J!bcS z`ZyQrw?U!cQE+U!9gVJtpj6Cx5kWMSns#X+T1Q*FVN_CB1Z-G>MfGM@uL=uC5y%Ym z8!Kc51XUk80v_6Yl3ZL6bUP723>GxBMQ|{`1inI6hd6mHW<(5pA?pG9G#2L9Z={=Q zA1A*cT%-%frTd`~AhPI{*DXcI!RI-_hDZ!Fz^({Fj#Ciy@Cg~j^F%YLk6JUFhTf7I zDkO*GIJ*GO!$3yCt{O1_6ab~iN34egM2eFeK%IzV&k#`u0L0=&5`te^O-6`ln~wYg z6*A}pH3OtdA@eBVDnja*g=@Di#B&Hj!6|ti>D0Pm5yY?}f{6u!BtC#B>53Y=u#}@9 zlt=@q!XB_X^y}!9N@|KM@SumRoDvcJ=Y@+JoJESVZYLvPSiE+8VMpymls7daFRL5TnBBT@(ZL84jh6+5}brY5=2wPVIU|WCmQ$(4H+RA^=YDvOkm4^JxBWip#)QD zcyT=bL@7+E05lQcJHch!_{J&@F00KH7DPfQ5k%BPkB8OYAsMp_(u| z=s0rF5phv>@vjc>?L+blJik<}CQ?L{=NBJB_je7<0*sSn4Wt5`+rLKu7!bPDzeX^r z2^XPRe(?!{g+Le$#^w{5^NGhjK#y23frY?)!lVx31b}2wBXtlLB9aHIk!qlbxCkcw z-61R(!9rY!$VcipScvo)VDWsQPvDm*i2tV)q0@(N_Q`i;iGC_<7Bw~Z zjr|u^$*A-0rT%p6hXrva3XycTtsO-39T=?2Yl>JDz}*AI13giV=siqMaq$Y+XBn7S z3L(@p@(W#8nVAy*>=u>~<~-W3Q$i1^GVz^L=d*`v>pi55iCKiM_}t>w%8@`;6UU3TKMoId(3JLLTQ zid?qH)_+lA_4s2PVK-srRM|;!?ykNoMjqj3>D@nR^ZDRZCvzs}dq&@@K6VO}^f&k! zV^`5+UE-B&tJsd%Wa+qUcgj9I(fU&(0e_2@9&&trQ~$l7sn{)J#%XSuDfRHI4hzg? zddc9F$BVb=0e*oKos)0c2~Urjb^bW(dvpJK$oLmpj+2bIs^;L;A^C0NC9?X7{XKjJ zx!zvDLUj%q)m*prP0zi>u!aC~RsE3-*;Zzouaa{0H(&T)=s4BK?Gwv*-ch$lbaFi2 z?Zla=?>VZf<0xcEWfL>yopzP?U)F9%91ZXp4tw>op-Up`dElrUKl76rZFw=;mw1^B(#!oD5F_-<_<7pA(Grp%mKrXxHr(c4PPR+vV8(92LLR zxiyjY{DCB_6PHo?+X;W<(*8qZ^4-{uvDuw4g<<;&^QmN%x_q20kjRrObtl9fBwyEfPIFFy!0LpgA8u?U=%mXf{7f6-%OQ$DaK zud;H~0-Jj6*ov_cnv9W7gk6-s}>sTpGVl4S#e&mNBhcW&=EcmVQY}Lfu zw{Ml(_m>>6NEqUijL4(5S9f0+e&Hs3KO1)b5abbFEz*#NDGjJ<5%&{iag+)Qm#vv~ zcpcO*JQ?EGTaQoKl5|sAO-X=DCsqE$G!5(x5vt57rfxiIP{?xVPQK70X0)efvH5wn z0j- zoJ#1*2TLuPj*#KePP_{K+kofzgbl||t2ORt#E6oal@QhGFluT6#_ckWXdvyW**2^Ogb7n zt1PE};Y{pk_|_ubt3)|e8`kRVdWc?U6&N1GoPq-u~#D4NW6C+Z0<4j-^WkQtQohd*oLjX3p!~T)zJ~s61u%}KXWXz z<6B3ga<4?qL;Mn9z1(N&#`ibIP2Vi*HtbdC3)o&0u+G-d&jf2Qm<9}-(V>llB6 zBI@SXo#pe(O8w^jQ?8KeRc?dlYmGYQ{y_tmY+ILWx5)!d;$wTnB;4#<+yhl{fl_lyRz=YD+i z*^PyJ&gO<-NeHyODmJ?7yASsl%( z;_Mp?{7pcd+V&!z6;+6e8|SX0wGg_BM5gn_NqvGhyD zih*dCBa{i9xhEYsjJG0kzjc4BNd)O(J`gc6bRPgs~`}9)wWY|XlDJG9{AL-KY5!EYS7mnX52LR-7uscri5adcZN zyGb+6jDaew8FnU_E2|+Xp0mN50c#sU4RM)k7n&}~prCQZTI_uD02St8w7B;J(JljP z3muO)U2cYx)dlqThH7qf+|}tA|KrEt+cKOJf9%h12gA>{8iuG%UX~X7~KdUdD z&`k40EMQDnv^1Qvua(}Uw7)ONy;8ImlYl5zSU<+VzefGOuBPpp@-2*cvi#>*&Ce}O zWGE}>4PDs93HCLtV_)hv`Iq>xI#I!}!WD)+ z2SNP1GC#AlN)}PwCi71BAzJ+1E&j2Xhdo6Dq4$EKPHnRuO1X#4hZochU!aG2zlREq zefV)lg4y_dbKZSPxIB7LXGZ?w;} zO;hJTXmH(ZnCN<|(Ej~KUDVqE#e_6!qtL|lGLPNe&083Ij@vHRB|RB*Uk%D8^Nl_(_lT}>x8h$ZXzwpu$_VtS9>1jx zU1{oxiyAo$T`_kVYhxPPir{Ns44zZoQr7mf9L_p^qs*)6nKK3+EkkAh)17l*@RP>0 zSJlvLxtYPfRTQ{#QES-2G{`;|(AGC!UV1adxN~TD=z8kjie@c{C$={RtLAL_@!kRK zOV1wf6idFU7K)YR;}TP%)5025KaAp-vvVlhj>XiD){kpoPov!AUd7p2h(l12XI#Zq zL#aCaGJTK5_4N<#M?$CMJ~o*n=7nP7T~Ah4;QakXF1-3-ZLML`|LCb**|&DducuCL z$#~oCcYdJ+VYeWUDrJNg6X#(vaLnb%O=UZsn!sHToe8|n^tpyxo~iH(?f;alCA;Qo+*xR=`|h3V=WAydTs_5R?r4MG zj+7!eVBJABH;?`-y~20c(Zkw4|AlB)?<*YzYoWImT%6Y&%_z@{tt6Its)TMa4tjUA zBOQ(srZ<*CiuXO6*6L=0Mjp>p5!k8%Z-uyxeVv*6V~M+mRi=x+9LDc{MOu%H3VPvg zL{=T!JDz@r8bbBOYH9LHr~g6w?VFkQB4tr|WBtiskJlPC>J(LP$`Srn2C?=01~(+K z`wZ*7O52q5DV{P3LNE~eqvW(cf$Id5nt-YV-pY@z_ zy$7?ixnB41%r%|kA;&k55PnQnr`i21ne7bnO{OiL3T>{bDWuyk(?lcB^;E&%)Z&=R zHO^~z!^wv2g(i#L)5)Qr_0JX;;-3A%5UTL*M*f(U&DB4Z5xDkT(Jck)DZ9+rsc*QO zr>mz2pULKzQwybZ=}o^S)YLV85ELbc(j;{5>yRIMd5byt>B~*ZR^v-e_=z?SOzFc9 zH;tDTg6|cvR+V6)onS*OQw z#|bvCzdNgJJNCYF>5{a4n}O%n`3|n{N`bs_bo3hId7=RWfs2Zasnws-rI>!2n<$Gj zQ?eyIJfiF!@W^d94ncZ8R>6WdS21& Mi>!|s@_-or2aq-L^8f$< literal 0 HcmV?d00001 diff --git a/testing/resources/font.ttf b/testing/resources/font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0ff4bf7d387cf3eb60bc34fcfb3298c8a181b4a2 GIT binary patch literal 10390 zcmd^FO^jSe5w4l-@&EcKcKj1N_*pT*7M5`w1Qv<}z8T38B#z=ZvVhHc>@}L*Sdf!)@VA0NdAib?F-5DdEc0n+d{z|Huf$bIsd z9F(ufSLH>yHe?ADzjB?n9CFPoe)tWCL_>3=w-^HO8rlo-o7c z5bJUWofyTE52s^*64{&ioWBVr;zwmV%(Ao8Qo3s?xuD1NrWL1jNU1K-H5e{o;p7yg z1^TI8idr)yM$dc9xq=^H7>o6FuON+-5%LuJ9Mq;+EJ6T2pDZuwcR4OM#FAelUXceM za7{({G19hVmufe!L0QgH98@c0YTjEsSL=Cic*(PuMyoxEx<$}u(kSee1cA+XHV0{ z`^-zlO885?7OP>ro2=KGMBGA5){zQh^$CEjw4Re#nPZHGK%`i1k%z~|Fp|@`DbaJK zcIleeO5m!P9!823PDNOif>|i_^Mo3^Yplj7S1XrhN9q_C32L6`d8gDnmGtfaW=!)q zLn5@Q1*+YxfHIxm9kEZ`5<)$FNQp5!Te4EmR;}p{-ovMxwq)MB)E~)b*4T;9d}x#@ z5uHsT@4yFEhwh(icK;n8V(E`+cZ<{-tSQ7}1iqS&)mjJtaX#`svAS%Ht%|CCJ+Fv} z7O9j6&j(zicerut_esih;^Vqt&Mev?n1iQmWT1WaxZU?Xos}uhMFbBp4FRF#rH3I&p=3&-M|#5`peaAi zcObQ(Jn_Io$#-JFh!UDH5=~B$g)jM>X!E5iX=SAKJa5Ky!i`X`n;ccVDZmi5FXFy} zo%P$P8d>!K)LwBK-3jp^9VI%wWhMaQmGvRUrV~`vc#Mo~St!WXEypadzH0BQD>6E6KTSHF^!$K$%}73zM!!9P&UcAr z8Vs=(za)vPJe{~Z&~i=Y@0ySC9&0-BjMS}fw9te-tMi~w(dH)wW1F}XU#q{EysyT1 zT6k{l@+us)b*w5q9$p~^JuaA;^oDJWi*t~o8ZTc1iDl&h$Iq+5aMCVRsjToracF9W-SdZlJn7aJ|SeHS_M!9G_ zJ?eX9%y%?sV_mk*p;YmV3fBXktRdK-5Fp2f6SR-38?la*;yT@i0BqGy%Mui#sm@sH z=8fI-+fM(-ay~pSqaZ}8v>a=jyDe^;L&u|jYkYw-p*02pnzq_}6dt$=-zSsH2p#C$ zcWjL~IzH>R@2M^Ltw^mlt1(P<9$6uf4VZK3@iNFNO7CD88D+8oQ?;c56E597xFx3W zb+=`dExwD*0@keinZIaw%eWRl8EHk$5*V3kY2;l%+ANtqd(8x__!-9dQWHH+vF?~$ z^}*jzM#j`V0l!Ld`4FXZKL={wV1-sur*}c)7;U0YCVzCqLbUe*_u4EdeY%glm^ZYM zGN_Fhi)7UkwHOp0Nf4SBNmpPEjD7FnZ*0k%wCULRO)m6B&VxQhn`>g8+&-0pIa=VO z&2LrS;bS$sFQz%4+7>I+;0Rw`qrQtos6lsYDmfeRokU8D9lh}i2^D@u74zePp*w+WgTCs`)2Ue`7oT-%>Cx34cQ2F~!LpIKdBwfrq#KE*7UO?qrky@xB zt#YKArK9^sLPYfKOLgK|M1Gf{zj?(xpGW0dvLayB{bJ<(yA{LIZ>^j(2Y}hAvKS)& z;+xMwT~N*S=aX{a|c0nu5%@ zK8xQ9Z6J--lRo9nzb|z?T%~W-7$qIqr?GV~ZhuVL7aB>JM$KBx7Ppb-ver82SefL@ zyTa`^ELI>4L9r^omt5{G)lY7d?RlVF{bmLQBgj>@Wc4Q+ca2E-z6VP@?&IF~V%>Jn z2C$L-=`Dte@mSH1q+=Y+=kdhfAJuCsNu@Qa*S}!`XGy0=niQThEV&&yuI6*Co{Vz@%K>B3%9oz=QC=VJ%(Ik0%rQNs zH+)Xv$Hr~kk*m^}*y%J5uyk`8cQD?a#;ZW{cp9&jjrbogCTE=-k}s$6G~WGZ(|D_F zkZaTyP(9G}qcm<|{7M?PA?K%QJO%vgX&hv`{4$L@7~f3eRiJq*jn~Q^xs}H2O{FGr$P{iZpw^J6O8dUnrh9d<57t{Y!_6{`q3I ze`&DPJ$1R;T`tb|7nYZb<$lrY&b-_$u41XU+#d`sc9)8mx^ov7&JhRBVvg&}bKPRG zJD9(?M7bxryPM?UMtD%t2X}1vx6uN>?t(CF#kG3=+;(ipJXWpd82&{)bv0 zoP|6ghvi7(I0M`zM85z$kLRq;N!^uGav9GqC=0BScNzEs&pw_#tjx&EcouRsaTVa` zL)QShx=Q;J;2dTPa;~H^odxjDzl<^EEaEwkdC)K6$Lu`;Tn|6gd0M6SAZs78W9>Zu J-`%Ix{tX`1!SMh9 literal 0 HcmV?d00001 diff --git a/testing/resources/love.dxt1 b/testing/resources/love.dxt1 new file mode 100644 index 0000000000000000000000000000000000000000..88cb9e6890bafb1574f69e997c51c811386fa3c9 GIT binary patch literal 2872 zcmcIl&ubJh6wd4zY!`$=8N7(};zjh}e-Lp+iU@&D+R~x2N9kWsw1@c%ym?YeK?-)I zmpyp1%+33h?Mc|Pc-K7$@qGzzcN_P|bh-vIA9=}p-qe<(QR@5YOEnBw~!Wbz$>RK`CIDs#bk?8+^ zP*`e=u%}wp30cW!8ZYxRE?P%bUgl@Ku8z9ABmT@#H7k6taxT+&t?ibE&K-zTc4G?c zkO~4Av7PFmTV_V<)C~H6R#7MObj;#SB;s3(LaC0KNwrqY&lu`(yhOlx3(@T>ifZvI zYRns=(?J5kFJ+R1ygc^&QdZwL=P5HvX&v(N82ofTDRPPi9U_wd=m39`7z4zL`8p6; zP+d^|Q!_mOabBVHkeAk8YO{36#Pob6P0}&qrLwy+?&Gq+D_`~nc{+<(&11< ziAR+>r0Hw(hC1A?=v+8|Rncc-dY(g`dE=@&7R?*#nx^A_^G?(ujd8r%pyn6SPD z36P#!SBF}8B>T*JGw#Rl2P5Jk&c%Bde;6m^>(f0q=G{HqcVk``9#3Ou?_CVAU&H}I z59?$eYgf;g<2bhV(9$w`uMe&NFTB}p7e&GK%W>e3hiBy9E#qjJ`1u`U%uJ!$+vEOp zFWvi@kPwc8dz$C%m+qZtJnT8l_qXnTqxXo`x$`1FAjV)vLtYTa&qtDZ7^nGp@6i|Q z#^cQM3-gaL^84kZ&+j>nQ3viEe#8xH%hLSJ^K93z!#whb`9^%}EB2cg`&-N#?u+d} x?7vTc)#H;+6S%Y2IYPFZ_fL+2N1yg~Ts~hNY;JzP^LFsd+B19m!{<(?^B2-vj_CjZ literal 0 HcmV?d00001 diff --git a/testing/resources/love.png b/testing/resources/love.png new file mode 100644 index 0000000000000000000000000000000000000000..e2612a857c850afa83db824f1b5a30d226508df0 GIT binary patch literal 680 zcmV;Z0$2TsP)Px%Vo5|nRCt{2o7+*tFc3vAv;sfS2Mqv2C;^I~4k&>z&<^}SE%3o?#!>9(vG=YF z@%7T0>Fr z7M27`Bhl~{h6Hy5z2Gfg3CEs;d&2|3)$^z89GV5p0p8+~&{RHifq%HX*n0hTds@v? zT>*1}A4^LmR2gf5KU?2z{{C1!(T+*4{xCI_Q2fPO_#s4^DX5xb_6Y#WB@}&$32#Y( zYL3alTS_Ekzo3A(7*NeI*XysE)5%KM`=Juv6Q+d859SJQVM!Pr2IoA~wPtFF+_B;v z>LOEH1;B14Y*oO2yz*(%N^so_{fBG>9KzMN469(NfZiw2I|nadYe?|?ADH_Op<#wY z;ZgzV8-Jk+SXUnyseoQfRU$HWKR~+~vZ$+|_3BUE3{h`~Eh-6Yct9{AVqr^AzyqQw zF$+tA3LX$nidwu9l<8FF4Q!4>;Ecn1otzc3R;9!U75J^LcMP@BnFvOfLyuc!0P_ zDp~>q9w0B1i;}>C2LuZx)e@NSfM}_#N&*`m5H6NxOHjZA;^p!z2`YFXV8eu0f)XAG z+A`BBK@ATCZkno<5CIPaZ<{NX5Cso(*f^P!5D5=-+&Y_zhz4J>->J_%yrIpE}d|2Foco8b{xYy z{RSv1U>DyD7Yp%rv~%;cA}52x_+bJt_*)qKBa9AY^MMci`vrsDYdY~uD{30lc~C2# zPa`GZd~jbkPivePBp^Fh41;Y02m2FF3~S)Tnou6mLH&b46ozg+6gVK^xa*_uR8y%FAKX^zU zEw^8a=**x7oUL3Pe5@Solzd!mxj@>{%GK7{&hw0`6{u^1v$b>6B1t$vrmvl=t()f= zoUM|%l*Nw=(t(|;jhn5VrxLgyoA37{;Eb~--6<0&;bL_TRJHa5ttq*<%N%5eWH?tK z^R@Hz0=KJl2z^ix2yNV4+`;`@JKK>;dl8G{yxb0gw$Y#}I*in6W1r|oZJ!foWg$kJ z$t!&kjmIYDB52TfYo-VUjWTG83qUKIP_c*jVT6@@fo`sOc} zcE#S1_I$Z9>RJpkjEm-iB5xd3j!H{*huE!JQ|-pC&Rg`%{ogtUPF)x z2%0+2O0dy{hbrHD`|rA@rgsPx75%}%Ic9``f%5DuNE#UE&%v3|AT)q8L%x9lf|xQe zAf<>Rq6cd#gR3NzHG%pFgGZ0<%?^R&qeo41aI{s~(9k1hG)T?O4XK2dJsJWb@Ie3~ zz(E1*UKTtoTzasnX%3x})8Y>5hlM8^hRiWrjU4hJpF>z1=4y<34~0p4Q*vBlZ(*ZY z@b$YMWfa-=QG`mv7ya)#1i~O83pj*|6%=F{SP_$1B%dhyFFj_2)q7P{RTYFvm>?8d zg|UD@RpmXD`sYrC84>pJ@ZrN~gh8$_6o%$Rf#C4LKcUn=cj$ju;(r!H00nr2CY0?2 zk4ULULqs946_f{pp`Bokl$x6(3V{KcnVD5QvYO$ffDA!QkqH_=LNYSQPC)?&c_5&GlL9I-Vv34pC!m2{usrP@WclpP z(F3LT_S%bFh~$3sgf-B!SN%cUk*44UmSYW%$_SsIU}bts+r}ekJ0Gp^>Rj))s=UL1 zFT&Pu`R(pfh{mN@TrQ(Hkf0fLN8j1DKG<{B`lM!szXH#H5~2AqG=S}0S#OcyVBYmOH@zA z#c)@}dC6Jn*DpCtD9miSlAtWw62AI3RFBoS$;UT?Xlo)i%l)LS#w z3PFx7KWoqvzJ89O|GpK=<0HGo8IHE`X$HF&5fUkfZrZlyoQX`j+|`x$RP$zy7tI)H>f?x94d~B+%zhX78#VZs@bh@m`?bksh|_X%941S{n>@b0k$>US7Qs!nqi+m zO0m9p=Ja%bdb31{7kp0KI;Mf3w9EA2oU!2bRyTz&H`^U0*q=>>oYQg9Ebn5~yKE{K z(f&Eo2wyAT&-%rckvXD`q4J}JLYYM__w{}je-3^cF|5YgF13#+#S)vCj{VtcUhchn z^(W8RUl;$zR+DbsmyNWI7+xvqIC67q_VbgZuxR&fkL&tIVz~;Aw0Tc;9T(@)k2L*J z@#O=L#VHg2h?U;5S*)NwL;iJBnaGQp)V1d;S{gM+#nBG@FKAcY^i3_a{b*N(DEca| zV-7|>y4c7V$u;+MCQirt8{Ak#Q0Iot3#!%K))hYQ_jpBj!>jJ&_WPB7wX-hLGHJNw zNxeIVZ~s?22le;9FRY?vT#6^Ub3`MJs^MuGPZ#jjLA2zTBHys-eu{0wDaf0B^u7=+ zhMf&SbD!(V_qMv|%bjIXsnqKDfbY0K+IB7V?n6^biy}zf+fh_Lmr=$EUTOtaGUb8% zOXFtzOq(s-z12q*H1A4Z7C-Iyib?o7PAP{h6+c^H)=0j@U!Bgt#==sScIHC!tmd8z z3#NA3r|$dET8y9{`s{rPdNi5%4q-g);C5Y znAfU#l5W=3hWH@ZhpGfO0 zWX175h%IkD$|s~m*xE=~KE#9ofeX^)JsC%JCDnyxnBkvGNZi7CGPl zQGv*LI7mN4^)y#^f5O5mJG*ID)U)--hj0%4DR}qWcwKQ9?|w!8IvW)`+qHn(*iY74 zho6XJ?srF<*Z8~)w%RNH<>c90Nq6d0^r!QrsGYKBs|%*1k9X1cRca4A-luA4mRr;FkW301*fklW zGjD^J$LP^2wJx!p{^`bA8d};oX&0~T4GDL|`mAsFffc?F?au>?Pr~TX5C8nql%I8O z4KC0-Z2z<;nOSJHx#B>8?3PFEU~3mT-=#81gZ6-CcWU(RKZ@_&s;=gEdy!4ZL-Cee zj4_ht#Kns8vKfOKI&v3NnE?*g1IcSt^M5Xff@)G($w&H-j*KVlKC=`ZJ0V$OHFKJV zMK&?AYwYW)F~-hT)oZS*h|{vBha+W6y2pmv@|||UXjlkjiQIlge?;Sp-Bb7Mm~Qp3 zuc8XcFX>-peP7yihId9%|E$(N9J;D@0k1n<_r*|uZONobN$7G?QiiMQmj)p!As0Jg zT*gV(p(az)J^F>Wg)Y?8A56*jyi(ag%Ttm~-Zy=9X)WYRx8}&_qJ)R>Oo@KXZL!TS z?zE>=J#Mx?we6--Zy7eW?bi{R6lUBaVP@}AWWQ%X6D2R8Nmrz8kXH9vkW7<{QO ze5;G|E;?nnTiqN3b8il@V?*$!r{;sZPRAtbx!l=~I#tp8V06!iSFBwKCdEo!6^8zc zB2q|JFnvuuJL>2*=!DcS_VWfXKGf4 z${JY+Q7|cVgzc_uxbknb#ddx3VbXvnOG<-9vTODFpWB}0m4|39giNuhb2PXwm%Zvz z9oY;g-u&X8f$5iGsPoU854jS)M6!jS??Oa}xXaVKJ0v(Suj+gn)7D7-5n!(8??~RSF%p;=&;Y}~mk22Kn->sFNx8Pstj{7Q6 z@}j7a9qWGUHk{?H&WN;&UAKm;+Vk$V`o=#kCV2T*ciBYc9XS0k)ATfTT4WbJCq5sS zQdK^4l=`CJ%iT*$-Nq8d{04hU=9JyFEEB;XF)22YQ#s~?rl#FvBcC+pL|ncKsCow{ zN~I)=_er~yJU*76eXTR}&p&iP^g}6!{<+2_*Xul`T$-4o=pvrc_6Jx1F6lsR-&SeSN>rDCxhj-mj-M z=$r?g)+qh$kFsoiKd5~V70F2lzyJ7wjTLnH%Yn_%+s@O@?SFPuBi-YF_^1Y_BsGgt zRWpIZzzH=(P=~WMWH8}=SW4h+4m$rcz5#pa7O2LqyOL2R|5U~ga# zka-En*s{Z56tEB!O{(Xt>g$FLKCVS(gS}!MP%JV=Dv>KvDe0-%GUD1Z)z?Z(d^8NE zlrV6bSEfNkuwk_jk>5R3-VN(mRQ?U?Zd3t}S1-ClAe>SDW$rb7Ra#W8zP4ClZX#A& za@5RgwSjudYfa^oKm?O2Xym&`9ESk77a+7H3Za%s?U9Bh01E+TfngHZddhhEhIsnk z@eDBUGho>_bWm~xd&p2)$=FE!iIMS1V+#vEmnXh1Pm*26Oo$N^7t<=2$zLzx&;{VI zOd&af5Q-p(BFxJYC?cYY$zZmSN-{-b=VjwwXvOWr5$yew9b!^%r=-3t%%CF{0dRr> zx*OQ+`PilNaSr|jqMurTOU?gRFJ;G0F_<#YWrqh3>C*H>QWG`Y2?I7&#v(gBB{aQc zI=mD$y^nQx>vSa=byc3;_1y>%n1I2QStZmB6+5me4zL~?7?J5?)isdO9r+h7L$*-j zd;tSN+_Xbue|kPmVElA+wMzZRAmmQJP3? z;f*w}ez~P|=YFpFbgzC?cS>7k%3!KjKZZUvj}-G~Nuw?)90oG3rF6!2E-O$DH=Igc zIB^QpH62V{yj{x%VljznB9*m9r1pr7di57truRRRn*%jso~Aj~(prGnrfvFaA1x#U z{qA_Q#Ob39>}EC2*?u!jASjN?nhlYUxW?ywmGN38x)YVlcO_0kyD(fI%O#TM9Y!3v z01Otv^z$r6L~&Y2BMQBMg55@N-=Mep|>?2&-H;+B5-<$EnmYV_!eVQq;+PfTpC zR4!(CmC9*3;pgC}30p+jtc!F5>!#y5R{{MP?Y?&xU)89AM@h`so^Y z#{(uaX+9Gtv++q^7t`xLlhu(H<32NEK{I1l&g_Y@Gfn>GA`Kmk1O_c9;&M#1#-lsZ z!}U~YNe13oIhr199SJ;L3CQE+NZnzHzV|XG)@6oR)xmTzWVaY%_Zi`^GdyfDa>#DP z*zSq1-9(k0d3BI!RnW}FPuG~w&npKk8$r3ad97bpPTX_ZI3WxHX-W_#uAIV@j8}!( ze_1)1j;7X>Jm}ccD!C(Q|#}%l!7S_%QU^0QC?TvN&i~` zQkPt20J?Ts0Ue!SgM*8dZhEiS#H!T9s{U_vvQwGoFMWX#fsO`PclrV&0v-K_`ub1Y z@9#GLpVk1Fc5p`U;ZV&&h?9lL!eN(?Dg*({piGFZ>7b0`UL95eQw|x1RH_lu;~mn5 z@_UdW!;noAFS9$9N;h2e$B!8>0UXFkr81z?|zONxrYfy(Zo5mmlN2WLuA*#w| zmHPLJ4S~Tz;MA}X7;Crkk9*2K1-6>91RGPZzmO%^!C@hGrrF?WpPUy1k^Fzlh5Xtf zJVX=*y97FP=jkDfvoTdBNbEXm3hN_x+^ft6hYFKHcgHQWkAqrN#&#c!i4r!e&(N|F7!vv79ra9T<1^?`q{@ISHMcp0}J?qB|*mMnzjg#gblb2$$MN{*Oio`%i1H?y^ zv9X0?>W=uqe#L>E(iVF%mi)6tWAh7(N_QEsse_FV_yQlJ1dRew(d!4wkPL_{_C%AK zEL|qsDU@Upf-5R20?!*VBT!(>$Bru#s!}T60~_0T^|JWjB)DP*&O z_Be?IG}!3qX}`JwWFmRCy+C#iD-UgcFsM9lPz3C)RbTRWgZ;-%FGf{3OqrzZSZ6&c z79*m%*RJBl%@qe9-MnJ&iR01|sP7F4{12LARVkk+J{YO0$n1F92d6QlQ z!yTb?wkwnzd&^m1G}OSND$(edNU)!aWU?8=XysLMibrsU>uYP5RNhcr;)%eTos(>T zA-5!u``8SR79Im5$xF7rTvo%ODu${YwJz@BOv0X%tm1T9X}g`MeH`7+=_J*@2o)YR zyNs5vW;u>Wx0^*Ux3_WF6jzQ3;+f0ahRsSUsci6NwUy)N`f53a@THQKCQf~nup5f9 zFy(#YvMt)frgM(&;9CM7@(dipz$CGO<^nJ|O(7O92W|`;oU#(JSmNvfyFqtLMfz{TQ1Wk#8rl4}b->CtTg?WiP zH9$3xj${IT5XB`M#?pF0t&{8k;+v(Hgf{algi;rKu6lBBvSL>Yd4e}rX0eY#9>{)b&@Ysh>lA* zlQ{QmVKDlfL@Y*9Jxnln>XxUO;h}C7}s8I+@3vyb|JeS)GRC0sL-e~T_zV5fK!V+d)vyL z;U3QF9jnbtJkN!Y!@w>N$*p|sn2Z+>FCV`ELQn{~PgsQX*qNmQzm&r;bWF_5eLR|% zI;gdxJ83X6U9{RTm;m^?298Dm27X6^Vj++R-}wbx8A<>L{Q?d>!Sv5{&9Q$+DL;pj z5|2911g-_GHEc9)OmEHnThTw3{`VGYHyZy&`rqp9!yoT9uGR<5ukoMX>X^16tUPyx+VzPtJNPD3 zKc5%md&;*!?PhtOmWTu5;FCuRVb%0!FJsJj)9sv2)73Lc%3gL}sbBd zNn`apr2a9qyz$1Oo@!cc;RK{_l07-;`&wRX6r%_o*&WX;qEJs>OziC zeRSwqm%-yWJj z-r^TGE4fI6!_mF{qI6#GUF4iXyMPIKz0G;OG0<7)_-?z1+fn_;gweEdC!>-Up`hY! zc~faH-L0_L@!Jw#KFrp&!%WB~tj;0sC(z1|Mq?UT~Uq)xGsXk>(ha&&mg;ZsN_7xPG|YV&i?Ai}^9e%t4(nl^dC#^$ZQXa1kJZ*I;$3tpi2)ZIN8d}*!y zEc#+oaB#@|r3|^R{hW(7%k@$3>$+#ZemuPOHkj(`o0{wIG@r{I9dz2w_C;CXIkPyu z|C#0baDUS+@^l`19*2aC;L}=st!J(^mV8WjF;n|R$fxI>lx)kph=WoaCFC;FG5%uEu|W~0}p_<9XLWM`vCco)RYuyqzQYrT8+e5Gm-NB6ehkUHBTqck)0 zK8pUp<+jE3^YxYo_N4WJh>kETE%Ms&xE8DOapx*?hU6amb^rQlR@!ULHf7_G{i1;6 zeEsxpRAS%rcm6v0hA3e6vWYjo3QAG8cqKkTO(k|ayuSgO0uei@8#?dB{OpPVeZ z`uJsCSl+pP0f&tFqpt++Z5(<)*<-o&rq*+g{g#sH>)W|wNf}1TUn-uMtecn*TrdkL z8ptSqBHWiItdq9~jm8Y~dn&gd74A!YSDt9ls`(eSXIZyhmjCZM4sQul@Mg}hZZI0( zd-JsqdFNS}<%Fa#Ej|m|pyzj6vD$Uo_wg?Os@e6%&#J7FlhrA%Q%+{sq&#u$;mf0y zIgc($|KWRCe*p6oTbU=EGjz{SKztO6D<(N;XG0PJrS;;pkQupK`J#-=ev@2*su;NhH#-EXg{YBAYhOM z8J?hx3;eM7Pz(h#jUdj@>@gSNkf$!{7>tG@o;78x6;=_7jAwySl>JjljTGXXni`Wv(6HE~@ZfE3YjDcG#p~=-KJO&N)A>w;^DK`)^NVJdOFR)$ zEyt{)6q3Xx%?7=>O-jrv&po+glAzA!GF}E|1Bb*ZAjmaP=k{Hhgan|3uFRTcJ+1PU4^0p(CK zC{Vk;pC|f9YDf5YfiZz773)GYUE2Rs1InS4reft4~# zuLf;QwGvd2Okm!qvjwh|uAZ*7qF_;BGt{hLQkNM7GxJoLXIoD)OHC>+Ka4|vt#L$! zLSe1(Nck`K#CW>K^ZOA0ZZyB<{cl48s$sz(2`93Kv?h)boIm!qZlJH@gTx@GrWR(VdsMGJcMR@E65Q&*v@!c~a+7jne!jvWpA}J|pGBZJ-)VNYox7N4?U2^?_{a#@F13}=I>GX}6 zAW{^YJn4ecHg|qfHR)2-hXvkK>{D!FRbrk7K2N-YhA!3U@%Poq>oaCW^N74O(}#>& zADXe$7Rs-Q1|#}DKa5SOOEfQC>KlDkQPN^&d;pbUmnkfLu=0&zQ}$7Q>idr}e{^GS1y1xEt~sFm8s03)>0#6JP{$i?*-dZQ-0dVkykB;_W;_jd zuQN(!S$K?_b^c0BRkd(Zh%|Sc;(DCyJor9}lU+FXWLbXxs_c3{_;vyU#re_)>jSdT zbrniN!v6Z@yK)v!pFH#E;PYQfC;B{|wr<;7RFBs50?%?MR54fG1O!j>(+D{OdbN?i zT2IK2vwe>rX9s#rU%+R~f~WzX$BYj`AJgy>N6hQ9L{bd!UsGH9lb6=75A3XM`Oq;7 zpQU)kW$0eym+wDWDkvzZ;(GOJ^VO^QBS#dSOiH%Du0D&OU)%mB)pFtDyKAhhit_K2d%?@>((PB?bBT1YX*c5sjJ{^K#?mcH=qEDAGWt5 zitsiT6a9g8_cKa?B1qnw4L^sv#^As@mnz+=XV%fG9Pf-1{S`+ioujYVA*=Cy;QeIg z0dmeIxn7&St1A@)e%Dj{!2{ke*(-hGdK9|PKT2+0n*OZKjU}lH-#D*Z(g#-uQsV0> zl3d!QlPBAyCQF1l?`hFqrkhMyA}WvPG+Ok4Q@bO zvTQb8UE<T3O;`KDtqIr6q9s14skUEpQ^Y$k=2=^2G>FA}>9cU_4q>yo^D{f2ewj zsZuBjh@&pbq{_F~R}v;j%S?hAYfv*_a&43>n?nr-j&3x7_CY5BpgYiKWrJG)Gzp>J zfwxf)rU*J_q`={i%V@k4XL}F}QGs5mbc_v-qN1YmAC||!clB)r-{r}>dQpV>aM;<$YdFR-a?MDet>7&a))jtc$$n zlAEh@T;%5|>2=pcWb>fI=K504pIR8y`cjp0sA>fGrqa(M24Fcx(6K?ONID<{PZByd zQDu-v$0VwsMMeoyAdixUNtC#7p%hpvAP6PfyS1?zd~thwyPB8T=IWAES)c66|WwcVFya!1*XKF{l2!j%p zz#@E0>|6c@;djNRsbnJAJ z=nVST!DIX=HT?nrkM8%peuKyVBzXKL<-_>!Hcr|5+qU#(-PNOK)*mWzUwxJphspZ9 zd+_V0UaAA1b`K14Tv+coTHC_Y8{`*1ebWCle`EVh@b0FWhU+ZfM89Z?d}gqEek+=S zM|GdoRq?NW@owTr&w7R9Tk!9t2YO=2$1lJ4d(t?pn6_~=!nHP7n3^+KDoTTI)+6Jh zkkq{51xK5^&rjK6J{5BazLwtnpsXDNk;OozTSWX=1rTGhsW*=)i8?~~5#(j`03vA< z4c;%4=#~aR5@M8A_r_hpc?+Dlf{*e8uz0T>@J4}VDZCI(vs5C5wKu1k41iu=g1PCf zL0RX+3IIRu6^;XlaxL(%^H^DLifMT7nqQ4W#|as&Rgt~2gNEX!*QoB{v<(@I%dR`G zslO`NvxjXv<9ue~dKVc}`m<-x51l>@c+iaHnF~RGiZvIDK0oAR)gi7Sgr~Y6TO?a^ z=fLY@fG!5q7UMIdpUh8WG*C)75f}goJu8dmdjp`PE?XNj5+l|VAg>S@@ZW`9Kb2P? zRo)4H$^cPf%goFvxk3jIGDX t3#NCinwTS%D6GI62Y@o*k)V9v z?E4g*X$Ude9ZUgM=gsJ_xj&A3H#|UWN+KQm_iaYlBmuD|I5#;r%!*zJ&A{YG2C?c&YXeON%_ zY`YD-SlMnOHjwl-@0};^a--CFj*)ct52XRlbpJ0f@}DNN98}wG^8VG)ME7=07w9WS z!6;VJ**<9m-Lcj zCHs6-`2=p=GDQ5hD3fy>>zpu9_q1p^m=9cMA)%nbt=1%t%T@chCMwbmdT z|H2}Frj8Ji1eA3D>0gAJ=QaK7{{kyDrH@qA)jV_ENDBI7!#O<%ekjLVF@NG?#%n|m z;SuEU4!)B~^f`Riu5^3`QG55x&bRt|4zEien;34nQ#u#ld&Kq?iv@D<1{Qr~YRc;% zQ>d_9LT9^tgjM)en$~6`>Zo#b@0C`oD0oK#pAJIQqf?DuMuXF)7F+(Lgj$729Ra_< zu^DJgLDX@FH3B3B4hnTU7;;4K!*Ul;I6#hTGY+#swncLaM5TM;nY_#UT?4aHXE1p@$HxmnOB4mjk6FA)aY&;F}84LOds91?b z(Zw?wV{_+H3(j3Lxw|nOa7cHrj0FmVj6tT=)z@uJI2wG>-3@T4?gpUQ$IrxW3p9TF z)?-o<{O#Mfj$a4C*?tfJkLPMv`4qLlh<z$tWZMVM?fs$9yXYWZ%uNOjf%_ z0ythh2KeIga?6LgwVCDR>MM`_<&;tA&*_1*;Bn5YGbGYRy5e z-!n09dgDF`M4EGRgM%h1L)#GIUKVe*_HPtTJ^uk6AzH`+r(z=)k&9k zmwDOQ_j*=Mx^80r;7)j_k>-N@)JFH@&dIxHT<^94o;G&qj!CXn)KW&!>d}s{hIc2n zGA^K+3K|9!zv$~5KF@foS?B#WGcyaE;NNBzR8Lh_2LZ@P;*9=8j07koKq*^m033j5 zH(-r`?75^u;BlhJ+@)$#+gux)Je+uYC^64B6mF=U`h7VP=@zE|Ky8^jz;XHZ4se6) z1f)A9Lke$0=7k$t#L}qm%xog3Bg;=ZG-mPe(L)hVnGs9N_GHb1bUt8#Jd~bSdL7X| z6WWFV6n6)`Ss;R9RJUPb9?I|jo4V;YKASL``AaP>`7MH+BgJW_k908nr=cTb%e^<; z)D3bgA+8$Z8c%%_s<>`mO86$z)S?r3_tMHp^i(@K5`21n0BiIC{81UgiNCN|e-fw# zK0u8b%FA~Z*E>m*oiP)zK>ruJiNvq}!J7~MuU@@ci3$h^4hT5k*Eg{D$(@Vafz?P^ z@JC>HsTuw+wymvAEetI@!4PzWpidxCJCL3hu0kOIS?mG0yZ6+9hi1%rbR6FpV9kk>T}ui_%2w8aB?EEl z9WMir$L`eBYw7PgxaNUyyRgjQ2>xJ?-d})WA^<%o+&^*WA6NY9@=)4;11$H5JYPrc zvoyv?e7CV-vBz87Z0h`){EzC_Uv{0BZHW~^)^qCgtJB-a zwWGnUGqs{=I#nT_D7b{Ta*)I9yA;tz5gAo}&5d@KY5t_`e(A0&2KprAXm7tm9)F^c zW4>M)t8bR>!~sPRy*j0-iPg1R8DOPebE)Rc2HQ9E}#-pkS|?m}-1C+DJEuOx3y`ciLi-Tg(|{VV&-J@5-v z@9>A0G5G|0LiZ`%+!4&-QA3?+Pl9$8fPqA8Ob_ z_Z$^zW>U?qJ3d= zB_41_@NKgL5y6tkB8w!Z0E%RT9wmT5LVytvNq`#xk%Ty-Dg^+OAP+*3q(DG9s`2aA zty|mMU$?~jciZGN#eej+29MCSM*kAG0BGQz7-TBY3}l0bt{wWs-!C!#|ML>#ZkV&_?spEW{JO9;%}Dtnvw95nqO+5Wn}2PNDZA1r^E);c&+P1-#_h+W-In literal 0 HcmV?d00001 diff --git a/testing/resources/test.txt b/testing/resources/test.txt new file mode 100644 index 000000000..620ffd0fd --- /dev/null +++ b/testing/resources/test.txt @@ -0,0 +1 @@ +helloworld \ No newline at end of file diff --git a/testing/resources/test.zip b/testing/resources/test.zip new file mode 100644 index 0000000000000000000000000000000000000000..46cfaba9798cb68e849b069e89f9d12887c24f17 GIT binary patch literal 150 zcmWIWW@h1H0D%p8=HXxll;8l;C8@ Date: Wed, 4 Oct 2023 21:59:31 +0100 Subject: [PATCH 015/409] Update readme.md --- testing/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/readme.md b/testing/readme.md index 4533e8c45..5740a6b4e 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -124,8 +124,8 @@ Modules still to be completed or barely started ## Failures - **love.window.isMaximized()** - returns false after calling love.window.maximize? - **love.window.maximize()** - same as above -- **love.filesystem.newFile()** - something changed in 12 - **love.physics.newGearJoint()** - something changed in 12 +- **love.objects.File()** - dont think I understand the buffering system --- From 51b439822b33269e687cc4bd8c5a56e0884d36f6 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Wed, 4 Oct 2023 19:56:22 -0300 Subject: [PATCH 016/409] Add convenience functions for creating a Body+Shape+Fixture all at once. #1130. - Add love.physics.newCircleBody(world, bodytype, x, y, radius) - Add love.physics.newRectangleBody(world, bodytype, x, y, w, h [, angle]) - Add love.physics.newPolygonBody(world, bodytype, coords) - Add love.physics.newEdgeBody(world, bodytype, x1, y1, x2, y2 [, onesided]) - Add love.physics.newChainBody(world, bodytype, loop, coords) All new functions return a Body object. The body's world position is at the center of the given coordinates, and the shape's local origin is at its center. --- src/modules/physics/box2d/Physics.cpp | 176 ++++++-------- src/modules/physics/box2d/Physics.h | 36 +-- src/modules/physics/box2d/wrap_Physics.cpp | 267 ++++++++++++++++++++- 3 files changed, 350 insertions(+), 129 deletions(-) diff --git a/src/modules/physics/box2d/Physics.cpp b/src/modules/physics/box2d/Physics.cpp index abf26e2da..5c3a134f9 100644 --- a/src/modules/physics/box2d/Physics.cpp +++ b/src/modules/physics/box2d/Physics.cpp @@ -63,9 +63,69 @@ Body *Physics::newBody(World *world, Body::Type type) return new Body(world, b2Vec2(0, 0), type); } -CircleShape *Physics::newCircleShape(float radius) +Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, float radius) { - return newCircleShape(0, 0, radius); + StrongRef body(newBody(world, x, y, type), Acquire::NORETAIN); + StrongRef shape(newCircleShape(0, 0, radius), Acquire::NORETAIN); + StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + body->retain(); + return body.get(); +} + +Body *Physics::newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle) +{ + StrongRef body(newBody(world, x, y, type), Acquire::NORETAIN); + StrongRef shape(newRectangleShape(0, 0, w, h, angle), Acquire::NORETAIN); + StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + body->retain(); + return body.get(); +} + +Body *Physics::newPolygonBody(World *world, Body::Type type, const Vector2 *coords, int count) +{ + Vector2 origin(0, 0); + + for (int i = 0; i < count; i++) + origin += coords[i] / count; + + std::vector localcoords; + for (int i = 0; i < count; i++) + localcoords.push_back(coords[i] - origin); + + StrongRef body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN); + StrongRef shape(newPolygonShape(localcoords.data(), count), Acquire::NORETAIN); + StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + body->retain(); + return body.get(); +} + +Body *Physics::newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided) +{ + float wx = (x2 - x1) / 2.0f; + float wy = (y2 - y1) / 2.0f; + StrongRef body(newBody(world, wx, wy, type), Acquire::NORETAIN); + StrongRef shape(newEdgeShape(x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN); + StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + body->retain(); + return body.get(); +} + +Body *Physics::newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count) +{ + Vector2 origin(0, 0); + + for (int i = 0; i < count; i++) + origin += coords[i] / count; + + std::vector localcoords; + for (int i = 0; i < count; i++) + localcoords.push_back(coords[i] - origin); + + StrongRef body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN); + StrongRef shape(newChainShape(loop, localcoords.data(), count), Acquire::NORETAIN); + StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + body->retain(); + return body.get(); } CircleShape *Physics::newCircleShape(float x, float y, float radius) @@ -76,16 +136,6 @@ CircleShape *Physics::newCircleShape(float x, float y, float radius) return new CircleShape(s); } -PolygonShape *Physics::newRectangleShape(float w, float h) -{ - return newRectangleShape(0, 0, w, h, 0); -} - -PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h) -{ - return newRectangleShape(x, y, w, h, 0); -} - PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h, float angle) { b2PolygonShape *s = new b2PolygonShape(); @@ -109,54 +159,24 @@ EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2, bool on return new EdgeShape(s); } -int Physics::newPolygonShape(lua_State *L) +PolygonShape *Physics::newPolygonShape(const Vector2 *coords, int count) { - int argc = lua_gettop(L); - - bool istable = lua_istable(L, 1); - - if (istable) - argc = (int) luax_objlen(L, 1); - - if (argc % 2 != 0) - return luaL_error(L, "Number of vertex components must be a multiple of two."); - // 3 to 8 (b2_maxPolygonVertices) vertices - int vcount = argc / 2; - if (vcount < 3) - return luaL_error(L, "Expected a minimum of 3 vertices, got %d.", vcount); - else if (vcount > b2_maxPolygonVertices) - return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount); + if (count < 3) + throw love::Exception("Expected a minimum of 3 vertices, got %d.", count); + else if (count > b2_maxPolygonVertices) + throw love::Exception("Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, count); b2Vec2 vecs[b2_maxPolygonVertices]; - if (istable) - { - for (int i = 0; i < vcount; i++) - { - lua_rawgeti(L, 1, 1 + i * 2); - lua_rawgeti(L, 1, 2 + i * 2); - float x = (float)luaL_checknumber(L, -2); - float y = (float)luaL_checknumber(L, -1); - vecs[i] = Physics::scaleDown(b2Vec2(x, y)); - lua_pop(L, 2); - } - } - else - { - for (int i = 0; i < vcount; i++) - { - float x = (float)luaL_checknumber(L, 1 + i * 2); - float y = (float)luaL_checknumber(L, 2 + i * 2); - vecs[i] = Physics::scaleDown(b2Vec2(x, y)); - } - } + for (int i = 0; i < count; i++) + vecs[i] = Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y)); b2PolygonShape *s = new b2PolygonShape(); try { - s->Set(vecs, vcount); + s->Set(vecs, count); } catch (love::Exception &) { @@ -164,72 +184,32 @@ int Physics::newPolygonShape(lua_State *L) throw; } - PolygonShape *p = new PolygonShape(s); - luax_pushtype(L, p); - p->release(); - return 1; + return new PolygonShape(s); } -int Physics::newChainShape(lua_State *L) +ChainShape *Physics::newChainShape(bool loop, const Vector2 *coords, int count) { - int argc = lua_gettop(L)-1; // first argument is looping + std::vector vecs; - bool istable = lua_istable(L, 2); - - if (istable) - argc = (int) luax_objlen(L, 2); - - if (argc == 0 || argc % 2 != 0) - return luaL_error(L, "Number of vertex components must be a multiple of two."); - - int vcount = argc/2; - bool loop = luax_checkboolean(L, 1); - b2Vec2 *vecs = new b2Vec2[vcount]; - - if (istable) - { - for (int i = 0; i < vcount; i++) - { - lua_rawgeti(L, 2, 1 + i * 2); - lua_rawgeti(L, 2, 2 + i * 2); - float x = (float)lua_tonumber(L, -2); - float y = (float)lua_tonumber(L, -1); - vecs[i] = Physics::scaleDown(b2Vec2(x, y)); - lua_pop(L, 2); - } - } - else - { - for (int i = 0; i < vcount; i++) - { - float x = (float)luaL_checknumber(L, 2 + i * 2); - float y = (float)luaL_checknumber(L, 3 + i * 2); - vecs[i] = Physics::scaleDown(b2Vec2(x, y)); - } - } + for (int i = 0; i < count; i++) + vecs.push_back(Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y))); b2ChainShape *s = new b2ChainShape(); try { if (loop) - s->CreateLoop(vecs, vcount); + s->CreateLoop(vecs.data(), count); else - s->CreateChain(vecs, vcount, vecs[0], vecs[vcount-1]); + s->CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]); } catch (love::Exception &) { - delete[] vecs; delete s; throw; } - delete[] vecs; - - ChainShape *c = new ChainShape(s); - luax_pushtype(L, c); - c->release(); - return 1; + return new ChainShape(s); } DistanceJoint *Physics::newDistanceJoint(Body *body1, Body *body2, float x1, float y1, float x2, float y2, bool collideConnected) diff --git a/src/modules/physics/box2d/Physics.h b/src/modules/physics/box2d/Physics.h index 6d3305dcd..9c81ffe41 100644 --- a/src/modules/physics/box2d/Physics.h +++ b/src/modules/physics/box2d/Physics.h @@ -23,6 +23,8 @@ // LOVE #include "common/Module.h" +#include "common/Vector.h" + #include "World.h" #include "Contact.h" #include "Body.h" @@ -93,10 +95,15 @@ public: Body *newBody(World *world, Body::Type type); /** - * Creates a new CircleShape at (0, 0). - * @param radius The radius of the circle. + * Convenience functions for creating a Body, Shape, and Fixture all in one + * call. The body's world position is the center/average of the given + * coordinates, and the shape is centered at the local origin. **/ - CircleShape *newCircleShape(float radius); + Body *newCircleBody(World *world, Body::Type type, float x, float y, float radius); + Body *newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle); + Body *newPolygonBody(World *world, Body::Type type, const Vector2 *coords, int count); + Body *newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided); + Body *newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count); /** * Creates a new CircleShape at (x,y) in local coordinates. @@ -106,24 +113,6 @@ public: **/ CircleShape *newCircleShape(float x, float y, float radius); - /** - * Shorthand for creating rectangular PolygonShapes. The rectangle - * will be created at the local origin. - * @param w The width of the rectangle. - * @param h The height of the rectangle. - **/ - PolygonShape *newRectangleShape(float w, float h); - - /** - * Shorthand for creating rectangular PolygonShapes. The rectangle - * will be created at (x,y) in local coordinates. - * @param x The offset along the x-axis. - * @param y The offset along the y-axis. - * @param w The width of the rectangle. - * @param h The height of the rectangle. - **/ - PolygonShape *newRectangleShape(float x, float y, float w, float h); - /** * Shorthand for creating rectangular PolygonShapes. The rectangle * will be created at (x,y) in local coordinates. @@ -148,12 +137,13 @@ public: /** * Creates a new PolygonShape from a variable number of vertices. **/ - int newPolygonShape(lua_State *L); + //int newPolygonShape(lua_State *L); + PolygonShape *newPolygonShape(const Vector2 *coords, int count); /** * Creates a new ChainShape from a variable number of vertices. **/ - int newChainShape(lua_State *L); + ChainShape *newChainShape(bool loop, const Vector2 *coords, int count); /** * Creates a new DistanceJoint connecting body1 with body2. diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index 29c3e2e62..7b755f92e 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -83,6 +83,177 @@ int w_newBody(lua_State *L) return 1; } +int w_newCircleBody(lua_State *L) +{ + World *world = luax_checkworld(L, 1); + + const char *typestr = luaL_checkstring(L, 2); + Body::Type btype = Body::BODY_STATIC; + if (!Body::getConstant(typestr, btype)) + return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr); + + float x = (float)luaL_checknumber(L, 3); + float y = (float)luaL_checknumber(L, 4); + float radius = (float)luaL_checknumber(L, 5); + + Body *body = nullptr; + luax_catchexcept(L, [&]() { body = instance()->newCircleBody(world, btype, x, y, radius); }); + + luax_pushtype(L, body); + body->release(); + return 1; +} + +int w_newRectangleBody(lua_State *L) +{ + World *world = luax_checkworld(L, 1); + + const char *typestr = luaL_checkstring(L, 2); + Body::Type btype = Body::BODY_STATIC; + if (!Body::getConstant(typestr, btype)) + return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr); + + float x = (float)luaL_checknumber(L, 3); + float y = (float)luaL_checknumber(L, 4); + float w = (float)luaL_checknumber(L, 5); + float h = (float)luaL_checknumber(L, 6); + float angle = (float)luaL_optnumber(L, 7, 0.0); + + Body *body = nullptr; + luax_catchexcept(L, [&]() { body = instance()->newRectangleBody(world, btype, x, y, w, h, angle); }); + + luax_pushtype(L, body); + body->release(); + return 1; +} + +int w_newPolygonBody(lua_State *L) +{ + World *world = luax_checkworld(L, 1); + + const char *typestr = luaL_checkstring(L, 2); + Body::Type btype = Body::BODY_STATIC; + if (!Body::getConstant(typestr, btype)) + return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr); + + int argc = lua_gettop(L); + + bool istable = lua_istable(L, 3); + if (istable) + argc = (int)luax_objlen(L, 3); + + if (argc % 2 != 0) + return luaL_error(L, "Number of vertex components must be a multiple of two."); + + int vcount = argc / 2; + std::vector coords; + + if (istable) + { + for (int i = 0; i < vcount; i++) + { + lua_rawgeti(L, 3, 1 + i * 2); + lua_rawgeti(L, 3, 2 + i * 2); + float x = (float)luaL_checknumber(L, -2); + float y = (float)luaL_checknumber(L, -1); + coords.emplace_back(x, y); + lua_pop(L, 2); + } + } + else + { + for (int i = 0; i < vcount; i++) + { + float x = (float)luaL_checknumber(L, 3 + i * 2); + float y = (float)luaL_checknumber(L, 4 + i * 2); + coords.emplace_back(x, y); + } + } + + Body *body = nullptr; + luax_catchexcept(L, [&]() { body = instance()->newPolygonBody(world, btype, coords.data(), (int)coords.size()); }); + + luax_pushtype(L, body); + body->release(); + return 1; +} + +int w_newEdgeBody(lua_State *L) +{ + World *world = luax_checkworld(L, 1); + + const char *typestr = luaL_checkstring(L, 2); + Body::Type btype = Body::BODY_STATIC; + if (!Body::getConstant(typestr, btype)) + return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr); + + float x1 = (float)luaL_checknumber(L, 3); + float y1 = (float)luaL_checknumber(L, 4); + float x2 = (float)luaL_checknumber(L, 5); + float y2 = (float)luaL_checknumber(L, 6); + bool oneSided = luax_optboolean(L, 7, false); + + Body *body = nullptr; + luax_catchexcept(L, [&]() { body = instance()->newEdgeBody(world, btype, x1, y1, x2, y2, oneSided); }); + + luax_pushtype(L, body); + body->release(); + return 1; +} + +int w_newChainBody(lua_State *L) +{ + World *world = luax_checkworld(L, 1); + + const char *typestr = luaL_checkstring(L, 2); + Body::Type btype = Body::BODY_STATIC; + if (!Body::getConstant(typestr, btype)) + return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr); + + bool loop = luax_checkboolean(L, 3); + + int argc = lua_gettop(L) - 3; + + bool istable = lua_istable(L, 4); + if (istable) + argc = (int)luax_objlen(L, 4); + + if (argc == 0 || argc % 2 != 0) + return luaL_error(L, "Number of vertex components must be a multiple of two."); + + int vcount = argc / 2; + std::vector coords; + + if (istable) + { + for (int i = 0; i < vcount; i++) + { + lua_rawgeti(L, 4, 1 + i * 2); + lua_rawgeti(L, 4, 2 + i * 2); + float x = (float)lua_tonumber(L, -2); + float y = (float)lua_tonumber(L, -1); + coords.emplace_back(x, y); + lua_pop(L, 2); + } + } + else + { + for (int i = 0; i < vcount; i++) + { + float x = (float)luaL_checknumber(L, 4 + i * 2); + float y = (float)luaL_checknumber(L, 5 + i * 2); + coords.emplace_back(x, y); + } + } + + Body *body = nullptr; + luax_catchexcept(L, [&]() { body = instance()->newChainBody(world, btype, loop, coords.data(), (int)coords.size()); }); + + luax_pushtype(L, body); + body->release(); + return 1; +} + int w_newFixture(lua_State *L) { Body *body = luax_checkbody(L, 1); @@ -103,7 +274,7 @@ int w_newCircleShape(lua_State *L) { float radius = (float)luaL_checknumber(L, 1); CircleShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(radius); }); + luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(0, 0, radius); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -132,7 +303,7 @@ int w_newRectangleShape(lua_State *L) float w = (float)luaL_checknumber(L, 1); float h = (float)luaL_checknumber(L, 2); PolygonShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(w, h); }); + luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(0, 0, w, h, 0); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -170,16 +341,91 @@ int w_newEdgeShape(lua_State *L) int w_newPolygonShape(lua_State *L) { - int ret = 0; - luax_catchexcept(L, [&](){ ret = instance()->newPolygonShape(L); }); - return ret; + int argc = lua_gettop(L); + + bool istable = lua_istable(L, 1); + + if (istable) + argc = (int)luax_objlen(L, 1); + + if (argc % 2 != 0) + return luaL_error(L, "Number of vertex components must be a multiple of two."); + + int vcount = argc / 2; + std::vector coords; + + if (istable) + { + for (int i = 0; i < vcount; i++) + { + lua_rawgeti(L, 1, 1 + i * 2); + lua_rawgeti(L, 1, 2 + i * 2); + float x = (float)luaL_checknumber(L, -2); + float y = (float)luaL_checknumber(L, -1); + coords.emplace_back(x, y); + lua_pop(L, 2); + } + } + else + { + for (int i = 0; i < vcount; i++) + { + float x = (float)luaL_checknumber(L, 1 + i * 2); + float y = (float)luaL_checknumber(L, 2 + i * 2); + coords.emplace_back(x, y); + } + } + + PolygonShape *shape = nullptr; + luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(coords.data(), (int)coords.size()); }); + luax_pushtype(L, shape); + shape->release(); + return 1; } int w_newChainShape(lua_State *L) { - int ret = 0; - luax_catchexcept(L, [&](){ ret = instance()->newChainShape(L); }); - return ret; + int argc = lua_gettop(L) - 1; // first argument is looping + + bool istable = lua_istable(L, 2); + + if (istable) + argc = (int)luax_objlen(L, 2); + + if (argc == 0 || argc % 2 != 0) + return luaL_error(L, "Number of vertex components must be a multiple of two."); + + int vcount = argc / 2; + bool loop = luax_checkboolean(L, 1); + std::vector coords; + + if (istable) + { + for (int i = 0; i < vcount; i++) + { + lua_rawgeti(L, 2, 1 + i * 2); + lua_rawgeti(L, 2, 2 + i * 2); + float x = (float)lua_tonumber(L, -2); + float y = (float)lua_tonumber(L, -1); + coords.emplace_back(x, y); + lua_pop(L, 2); + } + } + else + { + for (int i = 0; i < vcount; i++) + { + float x = (float)luaL_checknumber(L, 2 + i * 2); + float y = (float)luaL_checknumber(L, 3 + i * 2); + coords.emplace_back(x, y); + } + } + + ChainShape *shape = nullptr; + luax_catchexcept(L, [&]() { shape = instance()->newChainShape(loop, coords.data(), coords.size()); }); + luax_pushtype(L, shape); + shape->release(); + return 1; } int w_newDistanceJoint(lua_State *L) @@ -573,6 +819,11 @@ static const luaL_Reg functions[] = { { "newWorld", w_newWorld }, { "newBody", w_newBody }, + { "newCircleBody", w_newCircleBody }, + { "newRectangleBody", w_newRectangleBody }, + { "newPolygonBody", w_newPolygonBody }, + { "newEdgeBody", w_newEdgeBody }, + { "newChainBody", w_newChainBody }, { "newFixture", w_newFixture }, { "newCircleShape", w_newCircleShape }, { "newRectangleShape", w_newRectangleShape }, From 2702004bb2780ac89bda56a43b3dad0f659383dc Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Wed, 4 Oct 2023 20:00:44 -0300 Subject: [PATCH 017/409] Add Body:getFixture. Convenience method to get the first Fixture attached to the body. --- src/modules/physics/box2d/Body.cpp | 13 +++++++++++++ src/modules/physics/box2d/Body.h | 5 +++++ src/modules/physics/box2d/wrap_Body.cpp | 12 ++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index a21f0be4d..2c8acfd64 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -461,6 +461,19 @@ World *Body::getWorld() const return world; } +Fixture *Body::getFixture() const +{ + b2Fixture *f = body->GetFixtureList(); + if (f == nullptr) + return nullptr; + + Fixture *fixture = (Fixture *)(f->GetUserData().pointer); + if (!fixture) + throw love::Exception("A fixture has escaped Memoizer!"); + + return fixture; +} + int Body::getFixtures(lua_State *L) const { lua_newtable(L); diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index 563812fe2..0be88c6c7 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -390,6 +390,11 @@ public: */ World *getWorld() const; + /** + * Gets the first Fixture attached to this Body. + **/ + Fixture *getFixture() const; + /** * Get an array of all the Fixtures attached to this Body. * @return An array of Fixtures. diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index 479e5bc27..6ed39ef2e 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -599,6 +599,17 @@ int w_Body_getWorld(lua_State *L) return 1; } +int w_Body_getFixture(lua_State *L) +{ + Body *t = luax_checkbody(L, 1); + Fixture *f = t->getFixture(); + if (f) + luax_pushtype(L, f); + else + lua_pushnil(L); + return 1; +} + int w_Body_getFixtures(lua_State *L) { Body *t = luax_checkbody(L, 1); @@ -713,6 +724,7 @@ static const luaL_Reg w_Body_functions[] = { "isFixedRotation", w_Body_isFixedRotation }, { "isTouching", w_Body_isTouching }, { "getWorld", w_Body_getWorld }, + { "getFixture", w_Body_getFixture }, { "getFixtures", w_Body_getFixtures }, { "getJoints", w_Body_getJoints }, { "getContacts", w_Body_getContacts }, From e03b2db08bce57f276ce61fb4169e3cc84984348 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:03:32 +0100 Subject: [PATCH 018/409] 0.2 - Added tests for all obj creation, transformation, window + system info graphics methods - Added half the state methods for graphics + added placeholders for missing drawing methods - Added TestMethod:assertNotNil() for quick nil checking - Added time total to the end of each module summary in console log to match file output - Removed a bunch of unessecary nil checks - Removed :release() from test methods, collectgarbage("collect") is called between methods instead - Renamed /output to /examples to avoid confusion - Replaced love.filesystem.newFile with love.filesystem.openFile - Replaced love.math.noise with love.math.perlinNoise / love.math.simplexNoise - Fixed newGearJoint throwing an error in 12 as body needs to be dynamic not static now - Some general cleanup, incl. better comments and time format in file output --- testing/classes/TestMethod.lua | 26 +- testing/classes/TestModule.lua | 11 +- testing/classes/TestSuite.lua | 18 +- testing/conf.lua | 2 +- testing/examples/lovetest_runAllTests.html | 1 + testing/examples/lovetest_runAllTests.xml | 578 +++++++++++ testing/main.lua | 8 +- testing/output/lovetest_runAllTests.html | 1 - testing/output/lovetest_runAllTests.xml | 385 -------- testing/readme.md | 32 +- testing/resources/cubemap.png | Bin 0 -> 27634 bytes testing/resources/love2.png | Bin 0 -> 680 bytes testing/resources/love3.png | Bin 0 -> 680 bytes testing/tests/audio.lua | 109 +-- testing/tests/data.lua | 48 +- testing/tests/event.lua | 22 +- testing/tests/filesystem.lua | 121 ++- testing/tests/font.lua | 19 +- testing/tests/graphics.lua | 1034 +++++++++++++++++++- testing/tests/image.lua | 19 +- testing/tests/math.lua | 75 +- testing/tests/objects.lua | 26 +- testing/tests/physics.lua | 103 +- testing/tests/sound.lua | 11 +- testing/tests/system.lua | 32 +- testing/tests/thread.lua | 14 +- testing/tests/timer.lua | 10 +- testing/tests/video.lua | 6 +- testing/tests/window.lua | 111 ++- testing/todo.md | 26 + 30 files changed, 1982 insertions(+), 866 deletions(-) create mode 100644 testing/examples/lovetest_runAllTests.html create mode 100644 testing/examples/lovetest_runAllTests.xml delete mode 100644 testing/output/lovetest_runAllTests.html delete mode 100644 testing/output/lovetest_runAllTests.xml create mode 100644 testing/resources/cubemap.png create mode 100644 testing/resources/love2.png create mode 100644 testing/resources/love3.png create mode 100644 testing/todo.md diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index b0c763082..8fa55080f 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -189,14 +189,23 @@ TestMethod = { -- @param {table} obj - table to check is a valid love object -- @return {nil} assertObject = function(self, obj) - self:assertNotEquals(nil, obj, 'check not nill') + self:assertNotNil(obj) self:assertEquals('userdata', type(obj), 'check is userdata') - if obj ~= nil then + if obj ~= nil then self:assertNotEquals(nil, obj:type(), 'check has :type()') end end, + -- @method - TestMethod:assertNotNil() + -- @desc - quick assert for value not nil + -- @param {any} value - value to check not nil + -- @return {nil} + assertNotNil = function (self, value) + self:assertNotEquals(nil, value, 'check not nil') + end, + + -- @method - TestMethod:skipTest() -- @desc - used to mark this test as skipped for a specific reason @@ -289,10 +298,7 @@ TestMethod = { self.finish = love.timer.getTime() - self.start love.test.time = love.test.time + self.finish self.testmodule.time = self.testmodule.time + self.finish - local endtime = tostring(math.floor((love.timer.getTime() - self.start)*1000)) - if string.len(endtime) == 1 then endtime = ' ' .. endtime end - if string.len(endtime) == 2 then endtime = ' ' .. endtime end - if string.len(endtime) == 3 then endtime = ' ' .. endtime end + local endtime = UtilTimeFormat(love.timer.getTime() - self.start) -- get failure/skip message for output (if any) local failure = '' @@ -309,7 +315,7 @@ TestMethod = { -- append XML for the test class result self.testmodule.xml = self.testmodule.xml .. '\t\t\n' .. + '" time="' .. endtime .. '">\n' .. failure .. '\t\t\n' -- unused currently, adds a preview image for certain graphics methods to the output @@ -329,7 +335,7 @@ TestMethod = { '' .. '' .. status .. '' .. '' .. self.method .. '' .. - '' .. tostring(self.finish*1000) .. 'ms' .. + '' .. endtime .. 's' .. '' .. output .. preview .. '' .. '' @@ -350,10 +356,10 @@ TestMethod = { self.testmodule:log( self.testmodule.colors[self.result.result], ' ' .. tested .. matching, - ' ==> ' .. self.result.result .. ' - ' .. endtime .. 'ms ' .. + ' ==> ' .. self.result.result .. ' - ' .. endtime .. 's ' .. self.result.total .. msg ) end -} \ No newline at end of file +} diff --git a/testing/classes/TestModule.lua b/testing/classes/TestModule.lua index 379aac360..9ee6cd62e 100644 --- a/testing/classes/TestModule.lua +++ b/testing/classes/TestModule.lua @@ -83,12 +83,13 @@ TestModule = { -- the XML + HTML for the test to the testsuite output -- @return {nil} printResult = function(self) + local finaltime = UtilTimeFormat(self.time) -- add xml to main output love.test.xml = love.test.xml .. '\t\n' .. self.xml .. '\t\n' + '" time="' .. finaltime .. '">\n' .. self.xml .. '\t\n' -- add html to main output local status = '🔴' if self.failed == 0 then status = '🟢' end @@ -96,8 +97,8 @@ TestModule = { '
    • 🟢 ' .. tostring(self.passed) .. ' Tests
    • ' .. '
    • 🔴 ' .. tostring(self.failed) .. ' Failures
    • ' .. '
    • 🟡 ' .. tostring(self.skipped) .. ' Skipped
    • ' .. - '
    • ' .. tostring(self.time*1000) .. 'ms
    • ' .. '


        ' .. - '' .. + '
      • ' .. finaltime .. 's
      • ' .. '


          ' .. + '
        MethodTimeDetails
        ' .. self.html .. '
        MethodTimeDetails
        ' -- print module results to console self:log('yellow', 'love.' .. self.module .. '.testmodule.end') @@ -105,10 +106,10 @@ TestModule = { if self.failed == 0 then failedcol = '\27[37m' end self:log('green', tostring(self.passed) .. ' PASSED' .. ' || ' .. failedcol .. tostring(self.failed) .. ' FAILED || \27[37m' .. - tostring(self.skipped) .. ' SKIPPED') + tostring(self.skipped) .. ' SKIPPED || ' .. finaltime .. 's') self.start = false self.fakequit = false end -} \ No newline at end of file +} diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 234019c8f..9552b5aee 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -10,7 +10,7 @@ TestSuite = { -- testsuite internals modules = {}, module = nil, - testcanvas = love.graphics.newCanvas(16, 16), + testcanvas = nil, current = 1, output = '', totals = {0, 0, 0}, @@ -91,6 +91,9 @@ TestSuite = { test.fatal = tostring(chunk) .. tostring(err) end end + -- save having to :release() anything we made in the last test + -- 7251ms > 7543ms + collectgarbage("collect") -- move onto the next test self.module.index = self.module.index + 1 end @@ -124,15 +127,12 @@ TestSuite = { -- the XML + HTML of the testsuite output -- @return {nil} printResult = function(self) - local finaltime = tostring(math.floor(self.time*1000)) - if string.len(finaltime) == 1 then finaltime = ' ' .. finaltime end - if string.len(finaltime) == 2 then finaltime = ' ' .. finaltime end - if string.len(finaltime) == 3 then finaltime = ' ' .. finaltime end + local finaltime = UtilTimeFormat(self.time) local xml = '\n' + '" time="' .. finaltime .. '">\n' local status = '🔴' if self.totals[2] == 0 then status = '🟢' end @@ -141,14 +141,14 @@ TestSuite = { '
      • 🟢 ' .. tostring(self.totals[1]) .. ' Tests
      • ' .. '
      • 🔴 ' .. tostring(self.totals[2]) .. ' Failures
      • ' .. '
      • 🟡 ' .. tostring(self.totals[3]) .. ' Skipped
      • ' .. - '
      • ' .. tostring(self.time*1000) .. 'ms


      ' + '
    • ' .. finaltime .. 's


    ' -- @TODO use mountFullPath to write output to src? love.filesystem.createDirectory('output') love.filesystem.write('output/' .. self.output .. '.xml', xml .. self.xml .. '') love.filesystem.write('output/' .. self.output .. '.html', html .. self.html .. '') - self.module:log('grey', '\nFINISHED - ' .. finaltime .. 'ms\n') + self.module:log('grey', '\nFINISHED - ' .. finaltime .. 's\n') local failedcol = '\27[31m' if self.totals[2] == 0 then failedcol = '\27[37m' end self.module:log('green', tostring(self.totals[1]) .. ' PASSED' .. ' || ' .. failedcol .. tostring(self.totals[2]) .. ' FAILED || \27[37m' .. tostring(self.totals[3]) .. ' SKIPPED') @@ -156,4 +156,4 @@ TestSuite = { end -} \ No newline at end of file +} diff --git a/testing/conf.lua b/testing/conf.lua index 9f1ba5789..f04c2d90a 100644 --- a/testing/conf.lua +++ b/testing/conf.lua @@ -21,4 +21,4 @@ function love.conf(t) t.modules.timer = true t.modules.video = true t.modules.window = true -end \ No newline at end of file +end diff --git a/testing/examples/lovetest_runAllTests.html b/testing/examples/lovetest_runAllTests.html new file mode 100644 index 000000000..ac9b12d58 --- /dev/null +++ b/testing/examples/lovetest_runAllTests.html @@ -0,0 +1 @@ +

    🔴 love.test

    • 🟢 226 Tests
    • 🔴 2 Failures
    • 🟡 43 Skipped
    • 7.563s


    🟢 love.audio

    • 🟢 26 Tests
    • 🔴 0 Failures
    • 🟡 0 Skipped
    • 0.006s


      • MethodTimeDetails
        🟢getActiveEffects0.000s
        🟢getActiveSourceCount0.001s
        🟢getDistanceModel0.000s
        🟢getDopplerScale0.000s
        🟢getEffect0.000s
        🟢getMaxSceneEffects0.000s
        🟢getMaxSourceEffects0.000s
        🟢getOrientation0.000s
        🟢getPosition0.000s
        🟢getRecordingDevices0.000s
        🟢getVelocity0.000s
        🟢getVolume0.000s
        🟢isEffectsSupported0.000s
        🟢newQueueableSource0.000s
        🟢newSource0.001s
        🟢pause0.001s
        🟢play0.001s
        🟢setDistanceModel0.000s
        🟢setDopplerScale0.000s
        🟢setEffect0.000s
        🟢setMixWithSystem0.000s
        🟢setOrientation0.000s
        🟢setPosition0.000s
        🟢setVelocity0.000s
        🟢setVolume0.000s
        🟢stop0.001s

        🟢 love.data

        • 🟢 7 Tests
        • 🔴 0 Failures
        • 🟡 3 Skipped
        • 0.001s


          • MethodTimeDetails
            🟢compress0.000s
            🟢decode0.000s
            🟢decompress0.000s
            🟢encode0.000s
            🟡getPackedSize0.000stest method needs writing
            🟢hash0.000s
            🟢newByteData0.000s
            🟢newDataView0.000s
            🟡pack0.000stest method needs writing
            🟡unpack0.000stest method needs writing

            🟢 love.event

            • 🟢 4 Tests
            • 🔴 0 Failures
            • 🟡 2 Skipped
            • 0.000s


              • MethodTimeDetails
                🟢clear0.000s
                🟢poll0.000s
                🟡pump0.000snot sure can be tested as used internally
                🟢push0.000s
                🟢quit0.000s
                🟡wait0.000stest method needs writing

                🟢 love.filesystem

                • 🟢 27 Tests
                • 🔴 0 Failures
                • 🟡 2 Skipped
                • 0.018s


                  • MethodTimeDetails
                    🟢append0.002s
                    🟢areSymlinksEnabled0.000s
                    🟢createDirectory0.001s
                    🟢getAppdataDirectory0.000s
                    🟢getCRequirePath0.000s
                    🟢getDirectoryItems0.002s
                    🟢getIdentity0.000s
                    🟢getInfo0.002s
                    🟢getRealDirectory0.001s
                    🟢getRequirePath0.000s
                    🟢getSaveDirectory0.000s
                    🟡getSource0.000snot sure can be tested as used internally
                    🟢getSourceBaseDirectory0.000s
                    🟢getUserDirectory0.000s
                    🟢getWorkingDirectory0.000s
                    🟢isFused0.000s
                    🟢lines0.001s
                    🟢load0.001s
                    🟢mount0.002s
                    🟢newFileData0.000s
                    🟢openFile0.000s
                    🟢read0.000s
                    🟢remove0.002s
                    🟢setCRequirePath0.000s
                    🟢setIdentity0.000s
                    🟢setRequirePath0.000s
                    🟡setSource0.000snot sure can be tested as used internally
                    🟢unmount0.002s
                    🟢write0.002s

                    🟢 love.font

                    • 🟢 4 Tests
                    • 🔴 0 Failures
                    • 🟡 1 Skipped
                    • 0.002s


                      • MethodTimeDetails
                        🟡newBMFontRasterizer0.000swiki and source dont match, not sure expected usage
                        🟢newGlyphData0.001s
                        🟢newImageRasterizer0.000s
                        🟢newRasterizer0.000s
                        🟢newTrueTypeRasterizer0.000s

                        🟢 love.graphics

                        • 🟢 65 Tests
                        • 🔴 0 Failures
                        • 🟡 31 Skipped
                        • 0.079s


                          • MethodTimeDetails
                            🟢applyTransform0.002s
                            🟡arc0.000stest method needs writing
                            🟡captureScreenshot0.000scant test this worked (easily)
                            🟡circle0.000stest method needs writing
                            🟡clear0.000stest method needs writing
                            🟡discard0.000stest method needs writing
                            🟡draw0.000stest method needs writing
                            🟡drawInstanced0.000stest method needs writing
                            🟡drawLayer0.000stest method needs writing
                            🟡ellipse0.000stest method needs writing
                            🟡flushBatch0.000stest method needs writing
                            🟢getBackgroundColor0.000s
                            🟢getBlendMode0.000s
                            🟢getCanvas0.000s
                            🟢getColor0.000s
                            🟢getColorMask0.000s
                            🟢getDPIScale0.000s
                            🟢getDefaultFilter0.000s
                            🟢getDepthMode0.000s
                            🟢getDimensions0.000s
                            🟢getFont0.001s
                            🟢getFrontFaceWinding0.000s
                            🟢getHeight0.000s
                            🟢getLineJoin0.000s
                            🟢getLineStyle0.000s
                            🟢getLineWidth0.000s
                            🟢getMeshCullMode0.000s
                            🟢getPixelDimensions0.000s
                            🟢getPixelHeight0.000s
                            🟢getPixelWidth0.000s
                            🟢getPointSize0.000s
                            🟢getRendererInfo0.000s
                            🟢getScissor0.000s
                            🟢getShader0.000s
                            🟢getStackDepth0.000s
                            🟢getStats0.000s
                            🟢getStencilMode0.000s
                            🟢getSupported0.000s
                            🟢getSystemLimits0.000s
                            🟢getTextureFormats0.001s
                            🟢getTextureTypes0.000s
                            🟢getWidth0.000s
                            🟢intersectScissor0.003s
                            🟢inverseTransformPoint0.000s
                            🟢isActive0.000s
                            🟢isGammaCorrect0.000s
                            🟢isWireframe0.000s
                            🟡line0.000stest method needs writing
                            🟢newArrayImage0.002s
                            🟢newCanvas0.001s
                            🟢newCubeImage0.003s
                            🟢newFont0.001s
                            🟢newImage0.001s
                            🟢newImageFont0.001s
                            🟢newMesh0.000s
                            🟢newParticleSystem0.002s
                            🟢newQuad0.002s
                            🟢newShader0.015s
                            🟢newSpriteBatch0.001s
                            🟢newTextBatch0.002s
                            🟢newVideo0.004s
                            🟢newVolumeImage0.001s
                            🟢origin0.000s
                            🟡points0.000stest method needs writing
                            🟡polygon0.000stest method needs writing
                            🟢pop0.001s
                            🟡present0.000stest method needs writing
                            🟡print0.000stest method needs writing
                            🟡printf0.000stest method needs writing
                            🟢push0.002s
                            🟢rectangle0.007s
                            🟢replaceTransform0.002s
                            🟢reset0.001s
                            🟢rotate0.004s
                            🟢scale0.002s
                            🟢setBackgroundColor0.000s
                            🟡setBlendMode0.001stest method needs writing
                            🟡setCanvas0.000stest method needs writing
                            🟡setColor0.000stest method needs writing
                            🟡setColorMask0.000stest method needs writing
                            🟢setDefaultFilter0.000s
                            🟡setDepthMode0.000stest method needs writing
                            🟡setFont0.000stest method needs writing
                            🟡setFrontFaceWinding0.000stest method needs writing
                            🟡setLineJoin0.000stest method needs writing
                            🟡setLineStyle0.000stest method needs writing
                            🟡setLineWidth0.000stest method needs writing
                            🟡setMeshCullMode0.000stest method needs writing
                            🟡setScissor0.000stest method needs writing
                            🟡setShader0.000stest method needs writing
                            🟡setStencilMode0.000stest method needs writing
                            🟡setWireframe0.000stest method needs writing
                            🟢shear0.002s
                            🟢transformPoint0.000s
                            🟢translate0.001s
                            🟢validateShader0.010s

                            🟢 love.image

                            • 🟢 3 Tests
                            • 🔴 0 Failures
                            • 🟡 0 Skipped
                            • 0.002s


                              • MethodTimeDetails
                                🟢isCompressed0.001s
                                🟢newCompressedData0.001s
                                🟢newImageData0.000s

                                🟢 love.math

                                • 🟢 17 Tests
                                • 🔴 0 Failures
                                • 🟡 0 Skipped
                                • 0.003s


                                  • MethodTimeDetails
                                    🟢colorFromBytes0.000s
                                    🟢colorToBytes0.001s
                                    🟢gammaToLinear0.000s
                                    🟢getRandomSeed0.000s
                                    🟢getRandomState0.000s
                                    🟢isConvex0.000s
                                    🟢linearToGamma0.000s
                                    🟢newBezierCurve0.000s
                                    🟢newRandomGenerator0.000s
                                    🟢newTransform0.000s
                                    🟢perlinNoise0.000s
                                    🟢random0.000s
                                    🟢randomNormal0.000s
                                    🟢setRandomSeed0.000s
                                    🟢setRandomState0.000s
                                    🟢simplexNoise0.000s
                                    🟢triangulate0.000s

                                    🟢 love.objects

                                    • 🟢 1 Tests
                                    • 🔴 0 Failures
                                    • 🟡 0 Skipped
                                    • 0.008s


                                      • MethodTimeDetails
                                        🟢File0.008s

                                        🟢 love.physics

                                        • 🟢 22 Tests
                                        • 🔴 0 Failures
                                        • 🟡 0 Skipped
                                        • 0.005s


                                          • MethodTimeDetails
                                            🟢getDistance0.000s
                                            🟢getMeter0.000s
                                            🟢newBody0.000s
                                            🟢newChainShape0.000s
                                            🟢newCircleShape0.000s
                                            🟢newDistanceJoint0.000s
                                            🟢newEdgeShape0.000s
                                            🟢newFixture0.000s
                                            🟢newFrictionJoint0.000s
                                            🟢newGearJoint0.000s
                                            🟢newMotorJoint0.000s
                                            🟢newMouseJoint0.000s
                                            🟢newPolygonShape0.000s
                                            🟢newPrismaticJoint0.000s
                                            🟢newPulleyJoint0.000s
                                            🟢newRectangleShape0.001s
                                            🟢newRevoluteJoint0.000s
                                            🟢newRopeJoint0.000s
                                            🟢newWeldJoint0.000s
                                            🟢newWheelJoint0.001s
                                            🟢newWorld0.000s
                                            🟢setMeter0.000s

                                            🟢 love.sound

                                            • 🟢 2 Tests
                                            • 🔴 0 Failures
                                            • 🟡 0 Skipped
                                            • 0.004s


                                              • MethodTimeDetails
                                                🟢newDecoder0.001s
                                                🟢newSoundData0.003s

                                                🟢 love.system

                                                • 🟢 6 Tests
                                                • 🔴 0 Failures
                                                • 🟡 2 Skipped
                                                • 0.007s


                                                  • MethodTimeDetails
                                                    🟢getClipboardText0.006s
                                                    🟢getOS0.000s
                                                    🟢getPowerInfo0.000s
                                                    🟢getProcessorCount0.000s
                                                    🟢hasBackgroundMusic0.000s
                                                    🟡openURL0.000scant test this worked
                                                    🟢setClipboardText0.001s
                                                    🟡vibrate0.000scant test this worked

                                                    🟢 love.thread

                                                    • 🟢 3 Tests
                                                    • 🔴 0 Failures
                                                    • 🟡 0 Skipped
                                                    • 0.002s


                                                      • MethodTimeDetails
                                                        🟢getChannel0.000s
                                                        🟢newChannel0.000s
                                                        🟢newThread0.001s

                                                        🟢 love.timer

                                                        • 🟢 6 Tests
                                                        • 🔴 0 Failures
                                                        • 🟡 0 Skipped
                                                        • 2.002s


                                                          • MethodTimeDetails
                                                            🟢getAverageDelta0.000s
                                                            🟢getDelta0.000s
                                                            🟢getFPS0.000s
                                                            🟢getTime1.001s
                                                            🟢sleep1.001s
                                                            🟢step0.000s

                                                            🟢 love.video

                                                            • 🟢 1 Tests
                                                            • 🔴 0 Failures
                                                            • 🟡 0 Skipped
                                                            • 0.005s


                                                              • MethodTimeDetails
                                                                🟢newVideoStream0.005s

                                                                🔴 love.window

                                                                • 🟢 32 Tests
                                                                • 🔴 2 Failures
                                                                • 🟡 2 Skipped
                                                                • 5.419s


                                                                  • MethodTimeDetails
                                                                    🟢close0.037s
                                                                    🟢fromPixels0.000s
                                                                    🟢getDPIScale0.000s
                                                                    🟢getDesktopDimensions0.000s
                                                                    🟢getDisplayCount0.000s
                                                                    🟢getDisplayName0.000s
                                                                    🟢getDisplayOrientation0.000s
                                                                    🟢getFullscreen1.347s
                                                                    🟢getFullscreenModes0.001s
                                                                    🟢getIcon0.004s
                                                                    🟢getMode0.000s
                                                                    🟢getPosition0.001s
                                                                    🟢getSafeArea0.000s
                                                                    🟢getTitle0.001s
                                                                    🟢getVSync0.000s
                                                                    🟢hasFocus0.000s
                                                                    🟢hasMouseFocus0.000s
                                                                    🟢isDisplaySleepEnabled0.000s
                                                                    🔴isMaximized0.640sassert #2 [check window not maximized] expected 'true' got 'false'
                                                                    🟢isMinimized0.645s
                                                                    🟢isOpen0.036s
                                                                    🟢isVisible0.031s
                                                                    🔴maximize0.000sassert #1 [check window maximized] expected 'true' got 'false'
                                                                    🟢minimize0.646s
                                                                    🟡requestAttention0.000scant test this worked
                                                                    🟢restore0.642s
                                                                    🟢setDisplaySleepEnabled0.000s
                                                                    🟢setFullscreen1.370s
                                                                    🟢setIcon0.002s
                                                                    🟢setMode0.008s
                                                                    🟢setPosition0.001s
                                                                    🟢setTitle0.000s
                                                                    🟢setVSync0.000s
                                                                    🟡showMessageBox0.000scant test this worked
                                                                    🟢toPixels0.000s
                                                                    🟢updateMode0.006s
    \ No newline at end of file diff --git a/testing/examples/lovetest_runAllTests.xml b/testing/examples/lovetest_runAllTests.xml new file mode 100644 index 000000000..9c69661ed --- /dev/null +++ b/testing/examples/lovetest_runAllTests.xml @@ -0,0 +1,578 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/main.lua b/testing/main.lua index 205f0b786..c90040818 100644 --- a/testing/main.lua +++ b/testing/main.lua @@ -169,4 +169,10 @@ function UtilStringSplit(str, splitter) table.insert(splits, word) end return splits -end \ No newline at end of file +end + + +-- string time formatter +function UtilTimeFormat(seconds) + return string.format("%.3f", tostring(seconds)) +end diff --git a/testing/output/lovetest_runAllTests.html b/testing/output/lovetest_runAllTests.html deleted file mode 100644 index 164ade985..000000000 --- a/testing/output/lovetest_runAllTests.html +++ /dev/null @@ -1 +0,0 @@ -

    🔴 love.test

    • 🟢 157 Tests
    • 🔴 5 Failures
    • 🟡 11 Skipped
    • 7341.71ms


    🟢 love.audio

    • 🟢 26 Tests
    • 🔴 0 Failures
    • 🟡 0 Skipped
    • 0.40991666666712ms


      • MethodTimeDetails
        🟢getActiveEffects0.045083333333418ms
        🟢getActiveSourceCount1.1385ms
        🟢getDistanceModel0.018125000000202ms
        🟢getDopplerScale0.012208333333374ms
        🟢getEffect0.035250000000042ms
        🟢getMaxSceneEffects0.0089583333331422ms
        🟢getMaxSourceEffects0.022874999999978ms
        🟢getOrientation0.037541666666696ms
        🟢getPosition0.024500000000316ms
        🟢getRecordingDevices0.039250000000157ms
        🟢getVelocity0.021333333333207ms
        🟢getVolume0.046083333333335ms
        🟢isEffectsSupported0.016749999999899ms
        🟢newQueueableSource0.041958333333314ms
        🟢newSource2.8378333333332ms
        🟢pause2.6265416666664ms
        🟢play1.7924166666665ms
        🟢setDistanceModel0.023249999999919ms
        🟢setDopplerScale0.094375000000646ms
        🟢setEffect0.024166666666936ms
        🟢setMixWithSystem0.0052083333330621ms
        🟢setOrientation0.017000000000156ms
        🟢setPosition0.0091666666666157ms
        🟢setVelocity0.0070416666657636ms
        🟢setVolume0.0075833333332831ms
        🟢stop1.787666666667ms

        🟢 love.data

        • 🟢 7 Tests
        • 🔴 0 Failures
        • 🟡 3 Skipped
        • 0.34008333333449ms


          • MethodTimeDetails
            🟢compress0.39495833333403ms
            🟢decode0.027791666666666ms
            🟢decompress0.28366666666635ms
            🟢encode0.044000000000377ms
            🟡getPackedSize0.0069999999996462msdont understand lua packing types
            🟢hash0.12045833333341ms
            🟢newByteData0.021916666666844ms
            🟢newDataView0.025416666666889ms
            🟡pack0.0070833333332132msdont understand lua packing types
            🟡unpack0.0091250000000542msdont understand lua packing types

            🟢 love.event

            • 🟢 4 Tests
            • 🔴 0 Failures
            • 🟡 2 Skipped
            • 0.47999999999884ms


              • MethodTimeDetails
                🟢clear0.028666666666233ms
                🟢poll0.022374999999464ms
                🟡pump0.0079583333327804msnot sure we can test when its internal?
                🟢push0.022500000000036ms
                🟢quit0.014125000000753ms
                🟡wait0.0069166666669673msnot sure on best way to test this

                🔴 love.filesystem

                • 🟢 26 Tests
                • 🔴 1 Failures
                • 🟡 2 Skipped
                • 1.0150000000023ms


                  • MethodTimeDetails
                    🟢append1.3135833333333ms
                    🟢areSymlinksEnabled0.01433333333356ms
                    🟢createDirectory0.39929166666663ms
                    🟢getAppdataDirectory0.014166666668203ms
                    🟢getCRequirePath0.015749999999315ms
                    🟢getDirectoryItems1.0962083333332ms
                    🟢getIdentity0.10579166666691ms
                    🟢getInfo0.9892916666665ms
                    🟢getRealDirectory0.98024999999957ms
                    🟢getRequirePath0.097583333333873ms
                    🟢getSaveDirectory0.01891666666598ms
                    🟡getSource0.020666666666003msnot sure we can test when its internal?
                    🟢getSourceBaseDirectory0.015083333334331ms
                    🟢getUserDirectory0.043666666666553ms
                    🟢getWorkingDirectory0.018791666667184ms
                    🟢isFused0.017999999998963ms
                    🟢lines13.630166666666ms
                    🟢load7.9870833333331ms
                    🟢mount0.48216666666789ms
                    🔴newFile0.37395833333331msassert #2 [check file made] avoiding 'nil' got 'nil'
                    🟢newFileData0.030666666666512ms
                    🟢read0.19545833333368ms
                    🟢remove0.81487500000055ms
                    🟢setCRequirePath0.017416666667103ms
                    🟢setIdentity0.086666666666346ms
                    🟢setRequirePath0.014500000001583ms
                    🟡setSource0.0082916666652721msnot sure we can test when its internal?
                    🟢unmount1.1363333333341ms
                    🟢write1.0965416666666ms

                    🟢 love.font

                    • 🟢 4 Tests
                    • 🔴 0 Failures
                    • 🟡 1 Skipped
                    • 0.11233333333444ms


                      • MethodTimeDetails
                        🟡newBMFontRasterizer0.007625000002065mswiki and source dont match, not sure expected usage
                        🟢newGlyphData0.28787499999972ms
                        🟢newImageRasterizer0.22408333333424ms
                        🟢newRasterizer0.18954166666596ms
                        🟢newTrueTypeRasterizer0.18991666666501ms

                        🔴 love.graphics

                        • 🟢 0 Tests
                        • 🔴 1 Failures
                        • 🟡 0 Skipped
                        • 0.94387500000009ms


                          • MethodTimeDetails
                            🔴rectangle3.7313333333344msassert #2 [check 0x,0y G] expected '1' got '0'

                            🟢 love.image

                            • 🟢 3 Tests
                            • 🔴 0 Failures
                            • 🟡 0 Skipped
                            • 1.2476249999999ms


                              • MethodTimeDetails
                                🟢isCompressed0.21679166666644ms
                                🟢newCompressedData0.19920833333309ms
                                🟢newImageData0.40049999999958ms

                                🟢 love.math

                                • 🟢 16 Tests
                                • 🔴 0 Failures
                                • 🟡 0 Skipped
                                • 0.062999999998231ms


                                  • MethodTimeDetails
                                    🟢colorFromBytes0.29325000000036ms
                                    🟢colorToBytes0.27899999999903ms
                                    🟢gammaToLinear0.021624999998693ms
                                    🟢getRandomSeed0.014708333333502ms
                                    🟢getRandomState0.071791666666599ms
                                    🟢isConvex0.056666666665706ms
                                    🟢linearToGamma0.01791666666584ms
                                    🟢newBezierCurve0.053125000000875ms
                                    🟢newRandomGenerator0.019874999999558ms
                                    🟢newTransform0.02287499999909ms
                                    🟢noise0.076916666666094ms
                                    🟢random0.17783333333377ms
                                    🟢randomNormal0.020458333334972ms
                                    🟢setRandomSeed0.019541666667067ms
                                    🟢setRandomState0.053750000001074ms
                                    🟢triangulate0.023874999998341ms

                                    🟢 love.objects

                                    • 🟢 0 Tests
                                    • 🔴 0 Failures
                                    • 🟡 0 Skipped
                                    • 1.6546249999983ms


                                      • MethodTimeDetails

                                        🔴 love.physics

                                        • 🟢 21 Tests
                                        • 🔴 1 Failures
                                        • 🟡 0 Skipped
                                        • 0.014583333332624ms


                                          • MethodTimeDetails
                                            🟢getDistance0.075333333334981ms
                                            🟢getMeter0.015125000000893ms
                                            🟢newBody0.03362500000037ms
                                            🟢newChainShape0.028624999998783ms
                                            🟢newCircleShape0.020624999999441ms
                                            🟢newDistanceJoint0.037833333333737ms
                                            🟢newEdgeShape0.020624999999441ms
                                            🟢newFixture0.077750000000876ms
                                            🟢newFrictionJoint0.031708333333214ms
                                            🔴newGearJoint0.12670833333139mstest tests/physics.lua:134: Box2D assertion failed: m_bodyA->m_type == b2_dynamicBody
                                            🟢newMotorJoint0.092416666667816ms
                                            🟢newMouseJoint0.050208333334467ms
                                            🟢newPolygonShape0.025333333333322ms
                                            🟢newPrismaticJoint0.034124999999108ms
                                            🟢newPulleyJoint0.035041666665236ms
                                            🟢newRectangleShape0.077833333332222ms
                                            🟢newRevoluteJoint0.040416666667653ms
                                            🟢newRopeJoint0.03037500000147ms
                                            🟢newWeldJoint0.074916666664038ms
                                            🟢newWheelJoint0.1102083333322ms
                                            🟢newWorld0.075416666666328ms
                                            🟢setMeter0.031208333336252ms

                                            🟢 love.sound

                                            • 🟢 2 Tests
                                            • 🔴 0 Failures
                                            • 🟡 0 Skipped
                                            • 0.93524999999842ms


                                              • MethodTimeDetails
                                                🟢newDecoder0.31383333333501ms
                                                🟢newSoundData1.1787083333292ms

                                                🟢 love.system

                                                • 🟢 6 Tests
                                                • 🔴 0 Failures
                                                • 🟡 2 Skipped
                                                • 1.3057500000059ms


                                                  • MethodTimeDetails
                                                    🟢getClipboardText1.6217916666665ms
                                                    🟢getOS0.034041666669538ms
                                                    🟢getPowerInfo0.080041666665309ms
                                                    🟢getProcessorCount0.017791666669709ms
                                                    🟢hasBackgroundMusic0.086708333334684ms
                                                    🟡openURL0.016333333334728msgets annoying to test everytime
                                                    🟢setClipboardText0.59291666666716ms
                                                    🟡vibrate0.0090416666651549mscant really test this

                                                    🟢 love.thread

                                                    • 🟢 3 Tests
                                                    • 🔴 0 Failures
                                                    • 🟡 0 Skipped
                                                    • 0.96195833333323ms


                                                      • MethodTimeDetails
                                                        🟢getChannel0.47320833333231ms
                                                        🟢newChannel0.028374999999414ms
                                                        🟢newThread0.2556250000012ms

                                                        🟢 love.timer

                                                        • 🟢 6 Tests
                                                        • 🔴 0 Failures
                                                        • 🟡 0 Skipped
                                                        • 3713.5796666667ms


                                                          • MethodTimeDetails
                                                            🟢getAverageDelta0.023208333331581ms
                                                            🟢getDelta0.015708333332753ms
                                                            🟢getFPS0.011125000000334ms
                                                            🟢getTime1001.1531666667ms
                                                            🟢sleep1000.4330833333ms
                                                            🟢step0.032958333331834ms

                                                            🟢 love.video

                                                            • 🟢 1 Tests
                                                            • 🔴 0 Failures
                                                            • 🟡 0 Skipped
                                                            • 0.67754166666772ms


                                                              • MethodTimeDetails
                                                                🟢newVideoStream3.4201249999981ms

                                                                🔴 love.window

                                                                • 🟢 32 Tests
                                                                • 🔴 2 Failures
                                                                • 🟡 1 Skipped
                                                                • 7985.3964583333ms


                                                                  • MethodTimeDetails
                                                                    🟢close11.641583333336ms
                                                                    🟢fromPixels0.015333333330148ms
                                                                    🟢getDPIScale0.014499999998918ms
                                                                    🟢getDesktopDimensions0.015083333330779ms
                                                                    🟢getDisplayCount0.010291666665552ms
                                                                    🟢getDisplayName0.014875000001524ms
                                                                    🟢getDisplayOrientation0.016250000001605ms
                                                                    🟢getFullscreen1305.7451666667ms
                                                                    🟢getFullscreenModes0.48033333332853ms
                                                                    🟢getIcon2.0577083333322ms
                                                                    🟢getMode0.10416666667012ms
                                                                    🟢getPosition4.9660833333327ms
                                                                    🟢getSafeArea0.067875000002715ms
                                                                    🟢getTitle0.55745833333276ms
                                                                    🟢getVSync0.095124999997864ms
                                                                    🟢hasFocus0.055624999998116ms
                                                                    🟢hasMouseFocus0.022541666666598ms
                                                                    🟢isDisplaySleepEnabled0.14775000000355ms
                                                                    🔴isMaximized642.02083333333msassert #2 [check window not maximized] expected 'true' got 'false'
                                                                    🟢isMinimized641.41475ms
                                                                    🟢isOpen25.519625000001ms
                                                                    🟢isVisible18.191791666666ms
                                                                    🔴maximize0.23570833333508msassert #1 [check window maximized] expected 'true' got 'false'
                                                                    🟢minimize640.26066666666ms
                                                                    🟢restore643.01916666667ms
                                                                    🟢setDisplaySleepEnabled0.59508333333014ms
                                                                    🟢setFullscreen1329.778375ms
                                                                    🟢setIcon2.0223750000028ms
                                                                    🟢setMode4.5707499999992ms
                                                                    🟢setPosition0.16512499999521ms
                                                                    🟢setTitle0.47262500000045ms
                                                                    🟢setVSync0.022583333333159ms
                                                                    🟡showMessageBox0.068958333333313msskipping cos annoying to test with
                                                                    🟢toPixels0.067666666666355ms
                                                                    🟢updateMode6.8227083333348ms
    \ No newline at end of file diff --git a/testing/output/lovetest_runAllTests.xml b/testing/output/lovetest_runAllTests.xml deleted file mode 100644 index a30afbbc2..000000000 --- a/testing/output/lovetest_runAllTests.xml +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/testing/readme.md b/testing/readme.md index 5740a6b4e..4269e4447 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -84,19 +84,22 @@ This is the status of all module tests currently. -- [x] audio 26 PASSED | 0 FAILED | 0 SKIPPED -- [x] data 7 PASSED | 0 FAILED | 3 SKIPPED [SEE BELOW] -- [x] event 4 PASSED | 0 FAILED | 2 SKIPPED [SEE BELOW] --- [x] filesystem 26 PASSED | 1 FAILED | 2 SKIPPED [SEE BELOW] +-- [x] filesystem 27 PASSED | 0 FAILED | 2 SKIPPED -- [x] font 4 PASSED | 0 FAILED | 1 SKIPPED [SEE BELOW] --- [ ] graphics STILL TO BE DONE +-- [ ] graphics 65 PASSED | 0 FAILED | 31 SKIPPED [SEE BELOW] -- [x] image 3 PASSED | 0 FAILED | 0 SKIPPED --- [x] math 16 PASSED | 0 FAILED | 0 SKIPPED [SEE BELOW] --- [x] physics 21 PASSED | 1 FAILED | 0 SKIPPED [SEE BELOW] +-- [x] math 17 PASSED | 0 FAILED | 0 SKIPPED +-- [x] physics 22 PASSED | 0 FAILED | 0 SKIPPED -- [x] sound 2 PASSED | 0 FAILED | 0 SKIPPED --- [x] system 7 PASSED | 0 FAILED | 1 SKIPPED --- [ ] thread 3 PASSED | 0 FAILED | 0 SKIPPED --- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED [SEE BELOW] +-- [x] system 6 PASSED | 0 FAILED | 2 SKIPPED +-- [x] thread 3 PASSED | 0 FAILED | 0 SKIPPED +-- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED -- [x] video 1 PASSED | 0 FAILED | 0 SKIPPED --- [x] window 32 PASSED | 2 FAILED | 1 SKIPPED [SEE BELOW] +-- [x] window 32 PASSED | 2 FAILED | 2 SKIPPED [SEE BELOW] + -- [ ] objects STILL TO BE DONE +-------------------------------------------------------------------------------- +-- [x] totals 226 PASSED | 4 FAILED | 43 SKIPPED ``` The following modules are not covered as we can't really emulate input nicely: @@ -108,24 +111,17 @@ The following modules are not covered as we can't really emulate input nicely: Modules with some small bits needed or needing sense checking: - **love.data** - packing methods need writing cos i dont really get what they are - **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check -- **love.filesystem** - getSource() / setSource() dont think we can test - **love.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected -- **love.timer** - couple methods I don't know if you could reliably test specific values +- **love.graphics** - still need to do tests for the drawing and state methods - **love.image** - ideally isCompressed should have an example of all compressed files love can take - **love.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back -- **love.window** - couple stuff just nil checked as I think it's hardware dependent, needs checking - -Modules still to be completed or barely started -- **love.graphics** - done 1 as an example of how we can test the drawing but not really started -- **love.objects** - done 1 as an example of how we can test objs with mini scenarios +- **love.objects** - not started properly yet --- ## Failures - **love.window.isMaximized()** - returns false after calling love.window.maximize? - **love.window.maximize()** - same as above -- **love.physics.newGearJoint()** - something changed in 12 -- **love.objects.File()** - dont think I understand the buffering system --- @@ -136,4 +132,4 @@ Modules still to be completed or barely started - [ ] Ability to test loading different combinations of modules - [ ] Performance tests -There is some unused code in the Test.lua class to add preview vs actual images to the HTML output \ No newline at end of file +There is some unused code in the Test.lua class to add preview vs actual images to the HTML output diff --git a/testing/resources/cubemap.png b/testing/resources/cubemap.png new file mode 100644 index 0000000000000000000000000000000000000000..2b8b2ed0c6b3eb8fd82bf7804ea9789bbdd306a5 GIT binary patch literal 27634 zcmV)%K#jkNP)&Id+ryde{N|zNxtcw(+2SNo6iLaFEZdqa zMKWSLNPxrv5(5qb1PPEqK>)|dR|5&`I6)%kg8(UUJcy1)TM{W!Y_iFoyQ`~fdiCb_ z?tJDwSJorP9Rr`w?sSibb~RX%g+B2lYHX`r-*{v_i+`}HsJr@wU-5Fi~t{WFGt@5esN zq{z6ryT?Q8i~Pdh`*m@jU%`Dv-tPyv-w3Axai{S!`yHsWh|Oo#8SQk)(-PxK@}fjb zL!=_kt)AfW+8NTaBrQtzM^p9>hFBbBT>y^l{+Rvgl-v<2+|&VebAI{X>Ml-w$xVSv-}J z_8Z{u-Vq9*u029Kr1XSRv))_b+=*jM^Nd$Fwm7q}NST);LBQNJp|XZ?UXT@raar-~ z_3JoOb9Qx^Il<#KtfRLZUz+0_X~u>$T~R2266nbEBI){^%1doj#5hHIqS&IN0T> zuU!DuhjGl8U)|zo z9{FKJ+GjM*h?)(4=l^*cfL71)$FDrirS(;=?H=$`j~!!cf5Pp(ocVc060|-jGk<7# z-~|wM3S?w))!j|utUxG*4jk4&5z8mXJ7h#v?+dX_h6uW&+Mr z8AE(HM(Kb_=@=aD@+;>bqCDK?Kq+!7XqyseXV2c5uc%5(ZVY+pxqY}x=?hv5HI{(a z1{)usr9YfJ@B%1?O_ne0vGuLv;NCtDi07x2r6mv!Efux5R8`HvV2naD%`+-fa;ANZ z`Bs7up3QNe!|{m9TJkEVtZS^PnNA&5l`+V#(++nDRls;UVN_0O#2V*4gV6-l0plz3 zA_t!kD+MURP>>cCdxsO8wRDZb=3{Q}l*VW=5QC+u!&=H^RQJ1{UXN>j$u0&BpCn$CPg634_k zr1mvwUJ=QVsUI+`zy~26uZXS3_frlBDP?WwHbbUGj&XDR*5Mw{@58IV|11#k@Fxm_ zPD;Jw7z|6aub9Z1U}b@J9MI4)XOD! z@J><-!|Amp#zjh;XoLsrJwX_N10gKldeZ8SOCu!KLuD+3>6A%6B`-^y0VxE}-PmB` z>Q(IR2^Y^a`SDMkzDy|${C)5ELg?A1e zc&f5uI&Lx78Ib0JD3)YJNo7117^MYKs8LGdyuaf^dAki_A2pHrkqdMcD?qi)}Fsff)=kNk0B0{au@_}~%js);VoYAxwQ^2B| zZA=7&te3AmDs+^U zqjrwU)C5u@5!9KXDhy#$qlLhGNhB0rfO3ieflURat2x$P#cE4sD{L_#i6U-{x2a@F zZ9Qpazy<^&#FTGt=y@u*xjjG}B?24?;Ef37@Io`)ZPQpxNv*;bigag*=CKW`+T!s@ zpe!5{3RDO|pfJ`V1xPPYUO_DgWP}e(rnyIH0oLO@cr)|mkq{t|H8|-(d2DVea)(X? zK`1D^Kr4wbp0e=N#<4orB`q^TA<E}()$~|xa1Mk4 z89;98*^06AWO+%mqp3}el!8Dhq?q+*PCA4XU~7C}DQ(C@AB!QFvefC)oAVrI2gtzR z#R3l&M*?^o0$aT`JSZqfZOT!b`Smfw9I{ah?*zgXlzIwyl%7R%ocBaZgNGVRpaTLi zTSeAV;Q`~#Y#Tyk@WK-Z8trE;Q!NacbGUjY1|h*4PmL!n4286K3u+3+8XBz-qz5bx zH@jX)DpMf>jnbC&)1FX8;0p>@p(Dv~IQ^iF`=R4V0Pn<|=;mALZ+(0B*lg}N8HTi$ zCAG77;SmBtrx9MDgv8>}LeY>hlG%0Oh|!eZQ3?nHiFT4!7%<8z6plbj5CZG%Yz82~ zy4n0d3O{q1ltT(hT^WouSPN082?Bwy6>(D`g++^qX_+$^?cuy*b-qI!w{WB%s7XJJ z90}lVI5F!{-(i!?8~>h;BNkT!1Onq70%naK3AG>$H5!dVBE7)bnY)vy2v=HS1+6fk zn0UsOB563B2#BO5txGHh>%n`0v>pQRe)fo2DhQ*QK%Dg?kpl0jOOG`*A`H-4Q`?-K zt(5u2h@z-D=%*x&8u?D&?*Zay68ug$feh^Tye!WowSk6+39UwXP3#i7x{a3-Wdekk zSmO|0(25(Zbi1G>%|z3U69kHGJH|;tRy2tdO{gSFdX%{1R@Hvy_IPj(Y$cK2P?e56 zb=Vq&78v8P)*}#LCCGfKD$V(2}C6KLA61xH%dDz6W8eqME)#xKMaj zP7lyhvesT?luqzibfBr7rKKa%s>B$JQj*F$x zg{?@dDRu2WP+NW&ITFBk!PSanIpx%oyG(Wyru$8%hqFa8@U-Sq=6jw{C?>@ShbJJ! zI)`zNP$@b|3+rlRAZP|LN_%uAIX$45963ZzuDS`k;CZ4k9e zf+WM`4&yyxqrl^_!ZY1nq_f_~TR{+eJm7`Hc|jZ~v{F<2z-Ox9nFo~o=7!NDj*7bJoB95)$4-EDBzpV&SLeet4-F|6xl>E+)Ws4 z&arZ=q)M9zCkV7bIFC-o99~;SDam-ZMG#0-EU?1jg+qwhD4>O;)l3M37*iBD>!>Qn zaHoC0&3oTD8Ufw~qm3S|mLpgg)9#hbpB&M@*=6@;kIq9GLMu{JQCfp_9+OR&?=~r& z;`(*Ls9)3W!0vX$%ChD&pSsM|E4O+2g^K+>kN42+wfW3vpJaKx#h?A@*Ld;S3;^#0 zQh*YI=HdZDS&$B;!8+)z4%ojok10c{EFl}TSUNophY?xjoV&mFCv< z7Sm}!Itc(sQ^z;Hb-=}kA7|_KA!#~Wjg?Yzb7PCAzy1olTa!24+dDyPc}Nt_8owMv*bGj&I+`RXmmXfe-y4fH+Y~o#2mRm z?-Hrt@X8`r{&uOuA5Jml=-1Eh8&DkKz&NC=9&q!ERrX~2!E3El}l_qk&z^?JzB z8prSce_!X{{hNOUAq7GR@~j{oWth^u?cSXp#5zI>i3*@BH0hwh{`FPTgEid?5Hu*`V)$kh5g9*YP~^ zsXn%bh2AVrzbY%7^pv@w9X0slFZb{sIvwy{GMT(R;v$5=-$~H<^bdcOja%E?zWw%E zJwkd;U7WJGSW?tA(=?-YhT3_w5Lg3sm5{Uzqx~Mu_AFOv<#+~2j58<%ftF-d4K_fV zh~}K-5B~4X2f7U$%>lj}-`+&^mbNR^EJa~y&SPDL&@q8lIP00FExz=0@}0!9@fhIl z;l^(_et@rj-+_x!AX(K!;pJD@{JUB2^5sjVf4dkIojTs)y^G`i%qp+Bh6 z3e5M;qIgIC_5b_jcYST0$Mo~NyG|-HoPQ*z#`FBwV=g^b5Cn>LkWf=1?*88%D2@d1 zPP~gmu`4e`K!h}K`TT^hJf+DpK_dZ^{rNxQ>v*JgI4fv&4W^bXot$#&Ts7NahUFVq zn%uk|aOzx194c(uB0uoJ!3X)EA3BZ%@D5025mMmYcMlRZn{e^G=auV{?VXuu()Zc; zKk>;&`P}C|!EgTN?{NLv?Kge)#)#3IKbU2$I-^)xNjY_PLKPc^W6disB`luEP}&nV z4Yyuwuzoz}`KKBjZpU{m1^J-yz+2$Eg+ZHbO*(mdT>g!F1)6P#k`hxxo_qZJOfkNA z@ibrj*Z&Ji5>r$azy5#yCcp6;|B8)keX{JGeRU!IohX$c2rXfw!dTDhLt~0jLOKk{ z1`$zW$wwibg^Kav>&bm-_VfeY298#OzspLnwVpS1y5jYpJ`o7zsJ-Cq`5K4e{CPuf z!7!aj%w3{Kcca~I@`+DA!sCx$=CA$i7icycG?Ijm|Iics^U)-Q7U!PR8 z+J?nt!DKA%xN5U|IV-7)09yq#l8U7ZV_Hik`&YY|Vm8>9`I}#PU2i|oE5S!D(09RE zPopi!CU;bD=ZA{;lKkMMWN49ah-Q*wruZjySKsVzblM@8FD-yv05YC??i*Y<-=tGDX?J4AX+{!-1p4*Y zqLkv&xpUmy+$PUwm7-sGKDjd*9rfz>%26`hyTE(cxdrpbYSu1HNt%W_mk6&}npueJzv=!$2-cPsc<7`Px_b=mOf zN6&ue9>c!nH~!Dx=I{KS|AeB*5kjD(B#yfG@tgl(auf!Amm6YUM^I&ImWwl~*}9$b zL!Vry88o@IdlMlf?YN1x7H=HVD}Ll-a~zI5t1FsjGvjMd4^YbRwXa>}r+)Gny58lX zhmP}+Cmv(#_Ab*&NtQWwc6Qj>{4ziO6F)}~1U&ZmMgHkO{pZxxUDhVvCl7iU^hf~j zSpaXr2_Aa%an77t;>NWXC~89(DCSxnrg=%8M+oH*p<^^EIUE;+EzM*Iacp?;`91pM z5m$D0S?xK_T{zC|%^`VKQI!fAwAkK$jvx7v&(ZC)vBL8wfAo#-&zI*&07nA2R{;P7 zHJ#3wo151OltcxRNCp&T&i+9Hs-l@dS_zPrtx3e(T+V#QGtM-<`G8l_He)lORqgXr zKlN!EO~uu#hiq?-c;?ybt9bw;#Qx7%y z!jE6#5C83N5o*bDcMfkYqsfH2h9C%tb(3ZzM0!h3nl!efdO)bW^as8BYmkmWFIeQ}H#K}2sZ)Ci&p=Z;h@aOlNBLUni z($Zc~%yrrXO4CdtCPhIaJcaj6vV=w`Nrb2AYRW30tV)8wqHD)qKjE>D820uxFFj?b z4O}=|Bh`>NmK4QN3G+Wsjs$RzsHj89lXdU1lkYS06YTB)YSFXOy z!C=b4Xavj_Yjq%TII2QZ8^dr~OS=;yl%TK%r3BrUCX51f1jc!^_VoJ^ zZ}sP=nWU^zrum3t$EKXWbbyc(9)Dy)nB;eVh$HTaBLUn4z7Elm#g-LHI7H~tQlkQi zk_zWNSv@t$YbCpfF^1WRk=`42`U5N_k32Hu)a6@rmiGwa zqqDufUmOYG9*|MR;%dZVuS=(?h;>9Wh#4K02tP|__D*n^mW->M${R`yMtPdun#JQI zbo9D=BZX&kt3_JWjI$hp0|AG_lu=q!yPDR*kfqaGvs1Z`xMz+8a4*P$VY*GbHIH+G zKx?{b4W%%orePEuJztI?wA`UIh(*Ju)H z%>fxcvD8)~q^HWEa1aKD5X*^^TLeMC%P$^hab-+eXmn8HoJA`^Z7g_!5MV77gBH4- z(>t*VUNhWWc~?~|j(9sq0=Nf+1f>IZM>{m6#9Plnzt7t09Orwh1Ug_4O-jxcI49>>vGPooMbWX5=FDh&n|Z)am2VPNpgo) z66YP(2xVhyf*q8N;y3Be123T8c$RD!DX7%Py0 z!FfqzK1XVomKWgPo)P>s~ps;Cm!l*+oTTF80;|!Oh(Ru#$3YX$BFUq`@f7 zkwM7vT!$nI@lK);;2=~nam%42ffJr$+-Cdbv)Ecw*B)a%)_F?fA#fm})spx-MTT_f zaLp+}Bcq-+I0}W{8%HC+dqC)#UT?~3dycbf%QT{pg}F92_O}Uo0V^wAwhsF&_U33t zAw^jsQ8;G_g`yIM%GDU}2qMqn#u9a&;EZChxlHfWZM>6I&LgxZ2n1mu2_k{X1=f1f z{T4cOjJM{&AN61N%8>xxB|37Z)hX0_zkj3r!|z#jU|UbFC)Jy$*R% zl9`;kHUvTw2#pc}N`eRkQaWT*U@AeDH86FER+j!wi_Xf3-r4|(U^*=^c2+HJw7GyS zW3s)Y!v5bc#Jk-R*jgCzV^1n}hf}`r_{X?>@hqDg8|;oJXsvKKUfbT~#QYMETs*;W zJY<}u+}PVk$BJ=PkX99=GN-O-~0L@x39DS&oBPxpX49@M}L*Q8`nv^rxSS6X$IP( z1dL0~cv`Z(f55aDaQ$$HK*Y0y)tn-84kbO6vm6X3%(vULTOl7kdj@G?d$-U2D5uqE z({9Z%-))k_5v@32Xa9iOSmxSIE*zg{l$Z39h>g8IfAaDbzIEdoH-@)x&cSZ&NB{sJ z07*naRAPO=#$Lj5Y`OCFE-ROYtewh9rzK_S*?Qpwbvhe0RZ!DAF{HJSz55X$8#SqH z$^3l6&E0)2ojXnx2F!JutgoLSbAn->@tG$tVXR?)Xvu3!+z7BJjL$I^taW%N5lY}4 z2q~#^MbZ!~%!f3>8fhZpPDQemP;Oxbm8?Sb__EOBv*8(2?Aw}pN&34GaR>aL0Lwc(R zoWH18n_uGci4$B{o2T{_fAWoMytuK+XD*%R(%Legdh8*ZNkH6eA)){~95 z3Upk}1Ry+%m$qoOVX)moz1yk?-bunp@Ue?+HV-CTJavk3IxE@~XvJK&&9kq(%y5{~ zZ7008xlJ6$AT*(hkX|yaaw=P5y}^5rRthQMV53EEB_q&+!C}bGjzf12K{;&Y@ulYA z);!s;1@BM|`GZDC|DN)1JaFdHn3IbQKKa-Ji|ZL-AlTc_7#)VZ@N|p4?HCm};zr5n zpuzf@2{X@o+jDvK{(tM9zqs7J39fJ97Ouom) ztFI9$O;HxKB8dtk0;NdHf|vKUkgj5wj=4D*5c`PS=M2*+$2$w;rDUl$PrGxP2AT-P ze5XOH(dJ{1evJ9nBI~Qi>9!IYaYQExiK2*=#U62>X~&u*6#Vf^FL870fLFJ6sOp+Q zKH;F~qhrPO9T?}3-)`ZZ0x!r12{I^%S}95>hTCmSshK;wgHWDy5-{EAzIy=xOj6Iq za{eu1i{R$lhSc#goT*_O+Y5bZe6!h>5}mWnI!whg5ZqcOESjNO0a_ ztfk$7sA=$o6uF_hI>1_wLZXFabZeF2cK1Wm_+eHH_dSWg3oe|8b8Cw%FLelw=F^wX zP}h!EU-L{x;dic!BSC*ZVC!~B(#<%%7NLE_Fw1DRN=zQHy{QmhvVKg^Ye$4S87jwSw$u7V6`6pO9bBab35|kjOC5@FuGB22phDh%?wzkA{l9FZ??;S~$ z@ac~}%oE2?@#N{VJaqCTy+(&n2&P$z7mlK?u_8o!h{A~N{XNReQ8`;4;@7?0Zh1TVj7S;Nxhe6=Mc^sfR6ATdelGajLXL&#FWQ(ta!@!=t_yxK&_m}aY_8^OtAnvG4z zwQG_r?bBT5;j@F_z~$)J07`+~)2jL-p!2Ge}NYkNDK zT7HO+9y>uh^mJOmYy?>9a%^RlRvhDP!P!-bmu)&-*xfszs7hL`04pt(DNrs)BoSCk zpfvqyMx-J(4mY@Quu1AtjBwcTltz$nVa@ZkKWdWoXHDAUX{-ruUt6Zw>d;yrvvPLA z&W2)mb?rO$e$P>$uY9xSvC9FqEYUhZNdLc3uSHl} z;=N#PA!d8u(P;~Q^yBBLM>&aih_Z$_fOZ=%B*I#{^F15^hu-t@i_dZH>D=JrW_4x)_|Mi2v1%kb2L#j!L(3X6fkd_CO!?icPm-plX0ThM6 ztDJ|<%<&_Sp2s1{^MbmvTwGdYeXhfHk#4@0)E1cIPaf`1#Ghvdxeu7Jy!Q@WS zx6l5t=EO0_E3e$?r#y^CiqS}6Eocp8>9H2RofEX*x8#N6{J^Hm`{S)ew%I+ z5d?@xgAn+#KwxMsF0j~HMMyYvYMvKf-XPWi$BwO&mV%--WJO6c(m3mggOGL-;-p|O zt(gp_1j5s9Hs}uvq<~(xiM56x40!DP8KerRN`sODD+5M#!v4VssU!`F9QONc z^@sfa*Pr6$%}shqgvXH?_|~-zZtWdX+LGO2pHf(m1|cLBhIG;(t72T`z7wRdm73Yb zNqilEYLITfIf(L}1pu(M1BcU+ZpU!>+$oBzWPdclcu&75xpa1&oxKr<<0;)%6M?}~ zgRhzR3U8n`HCa(2gIQQbDuHtb=Ru0up4d#gEuUn?mfGmG~`=fVYtzdacP?dtJzI#aOZ~x+1{_;=% zFv}-aXX^-&Ms)&k7BQLP>vCpS0n`Q+Mf|hpuJfn2#yqs#V0-(Jg?58D38;*q6$eV74^>ssX@o{(v8 zvdP1zPI7B+L^BK+<{8!)tShlqOT8#T`Qb}pa1cB&YulAvEHVa#3apth1MKjdFsndQ_EoZ_Day+!_Mw( zPW7fc1fU|pzw@(?@hiXl2^v9y-#a9T9nv`%4Dgi$uYeH50MY1zlE}Ep*3B`0|JQz> zU-`w${OXS_aC2*m6YIy3x=A{n5GNf5nMeAX%1(%)2IEPe;WVSJ9i4VUyO(flvc=&} zjt(`aKmK`KJ>vR~=jQf4iGnIG5K6PVdz(F>==56%=`fW6?|5{r$2Do#84hUew0UXs z2G%;}I!*S+L$nrDMi7J%N`o>2oJSWsB<&{o_-<~g$KR#C()(Ts_6}~|@=V7=&YU?$ zD8aazKYH~Fka(euKhwjOj?qC%*h*-2 zL;PfnEGE!hfVm$3;jjKE|MUO)CH~pJdX>NVSI*I_Et7P@{9M4^;ebX~k+ha@!ja4` za=d$-&CLy(qXC0)%Hm>|t>J)AK6Z{Te*J6Q?B8JZ+P65hc8s3NFs8%=o>r^~g<*G8 zFq~$L_xG9jjI=DMjo^i?TO67R>A2)zJmTu!HeNWwKoG|v?S+tI%{iuZf%TRmcOWE- zEzR7zBp<)MQOF2f`S$m5PpJ^w`8MVsS~u5gys1zhm$dpY}1kv zlWI)v4Pg*4&NA|%MmI|gHQrf-hlbJ!FQ~2K+Vkra{qM2p^&xKjLUQN)-q(5Zp*Fwp zsYSZIn7{P+!z9L`LP;exjkv+tkDS9gNg=QCb3b{JKYMDEn>#6!vF{O`~3cYo;|s|!tvBE@*at(`3{pPi$uDw0Nw z@D-<*=cpH(>`pTF4#qt3$OSSp;bYU2eC64zBDFcCF^r}e zwe{#gQ4}?^IlCa#0p7!{mlw$PTJPtvK0Lg|-j`3e`5*t|k5XI1+4WWC8%=PIq#ctq zLqs5vOA$(qXnMm>e&RTP`!Ap8m;dTzzV*@p)2!y>pE}Fm_#2->%8;PlV{xHFq9$}& zP~;vTx2Sdp{FC4MCSUy1T`rz#u|1d)B6;Z>H#r=Yv|3GqP!YsUjE<2wY^RN^4M;eB z=>pH}T;VJKc7v~d>yXcX?gEWQNSamTrozjBPIrNEkwcL)oussafbCI=sVfRovaq_kF)} z&fV|3)n3&rn@w^^4wo5@W;CObMl+HnS%_s>Ni>0CCxPL_Ru;p7oFD-V#6a>TfRg|g zkOYV$z)&1RuqD8fGjSAIOQadikh5{f=F;qD@71-w^{#h6OFrBtheI|wB!^^I59{}( z3RQ32y7zt0bIx;~^F04&bGPD09`5n-jTt}s@nybs<0ba?r}V?L&5Ku-Nj+zGIwR9L z(|pFxL5@^VYmI9K4@kohAz?Ok?7Z~DSK$5ApIYI>YJidf4;){o6NmIxVpQrQQiTY^ zHvfNm00=~GkiJiUsl&hj%a8Ln{`SxE7k>6*#Qi0R0z~LxrA8*bb}$H-m#{1iU-`y$ zzVydexH8oI*r!f$^~Q+3NzPiYLz;$k`YF?Sj`S2|qcCX+Qr7sJ0%Vam97Y^?OqT2s}UGz^Ji4;4wIrx0O^2m^#@c;vnl{N4ZH3;fbwdW8S{ zuYZPWZ|I%~)b*h#Br;FI`2* z3Wr5Fi)l233D;h@#8R)r^2QPlc>3Hn2h)=O_}}{!D9eo-L*me9Wu=3tXQ)7;(g2|y zIF0ifkfzObnjg>^4pCLj^1>4R1;h2tIe+j+7x=B;ev;q*mrwJJ7q&S6@&P~nlc&h5 zF%2*)D_*>Lovh43LmY)jX^Hz?N}F+c?=rayxppw+`glqu45ip%IN4)bO{wdQZYOR< z1B4}re40kLMqmZTwy6$ILLdXSFC543N~9f=k2-Ja@86F1!~g({b(}fXV{^M?J{5@W zkVr%=R3* zos_&Rxp;FEhoh|K%*%qv4+uk_``1si(n*p2oW|@kt`5kWF`>VJ))h)Ys1#TYQs5-i zRwDv|?|T^S5VGA2Ct<|(7uFeF^9hrNd=jF|cNW-u&kO(r7p}}%S@gJmT_9tF=jE&g zUDC+s!uB@bxj1I?>RVsMh=}Plru#FWq1xF+A+Yn?1aJ>I_kU!W-}s+?2~}5kD@({E zKyU3c**l=qb@*!ogdd=@673X&ldDi0j-6U2SREi-PPDNC`*YN((-haY$*%7Z))`7z zY~Z8f2)WorNQu=3MTaN}@RUb)kTTjE@$7{mSFTTZ{-r(s{J9~&_=P^>sb-cpEO$fF zUV!sGMC3zRAhH}+mALT~H_mZ`1=PkGs=rR;3$9HIe)G4!O;vxdk8$%xj_6ocdXm{> zPGc?AL5``+t7jPzKA}tK23>q%Xq+a`D&|d1h({DDv;l`f8;>}N@O_C46bc9fK@f#3 z^kep~E^_f3ixfj25R?;zuHJc6|2;H-mdUJrW3q8bdTfLfu$c6CVfPxNkz;4`%};d~ z&g2a4hmEye#O5_-WrDso#!o%MV+-i<-J_BJKm2$91`i(_V5c)=R3XY7@-b;MM@%bZ zH$}uADhcqz0AmE@ct$daNY)}mt#Q|fxL%KgtudF+U1czkq|}JeN1zbGA<_t{ntE!8 z`W>9sgr1~4m}49qKasGtH|OSdMwM&6d49qZk9EKpgh&_+x=05qE2wtoI2%IT1sS59 zhu0tAFFyb>=Go`Y^YdT)N95V<`xIX|KP4UH7*kM|C9(6+jixe|@vNY>j-KCTUS}NS z`wZuEtPtc?&GFtMy>3FGE2QwS0%RCtm7uB%ifKriCfvLj@#5FJ46lYbExtEaA{_5D zc=Dbbz^gbxcYQ|VPZ^a{Y%Q6{Av>488>dx~VeNqt;X+Mu5K?Cz#XMnnDMWQO_pM*U znFf=2xO|TC9j3WE@`670xeY%1iDOiGhLH+C709{-BR;g&1$bpcVUsr`V9AGZ3B-ar7ju_irKv4>cva^`mg^Uzxr$c z9P=i*M*v2{^Dh+aXNFV9EUwaIc|ooVq_5~lT?CF4bMLpaQTIVg%!)Gv^~3evTGhA(e`6WCf{_gkO;;5m=U`30nE?o+9)zWL>kj zQ?jts!|#O1r4^jE+`CqDd@aS-8E%rJt-$N|5W2t_iS#{$u5qIo9VytGS@ugu7(o=* zTs_$3um3y8__L>{Jo}9a&wOLZsYOecRgC5}_njKC*oz3HV}EzX3ol)z(1O4B51-`x zg#(moC0X7Mb>%qst&E>|%+W~_=B_|^k^m1;Yc9=p*twqY zI5lR5@IuO>0c$z`tq$ox;_{q2zkPNpSBk`m`U@^ZkdTlZV(%7LjO6SwL=YiN0-}QX2$6uC7pSO%a30mLWWGBk9xmaZ zcn}Z>f1i5pvEyRyIT=uF&M{euZ!+9|j!09SHBdW5W4SV%bN*n&#o;y+H*FjCm4=1R z2LI)+Jj&M|xXADP;Q>A=zMt}?KfO*69K5g13LN~)^C>Hw1&{Io%r zK|7O64_#Yy*)C<)aH~1=?Qw7MyZ0Mw!IQkf^?cyI4o_X(Vl_>;Ii4V|TxGSt!1`hr zq5z4-s~h(Arz{Lgr0=8inzeftNLN!_bAa$8gdE@}n$!11%q~C2^_@MIlN9&Tn0j6l zBnIOQR5hbK=WClcxU#j!)?}X>dYi1OI36!h1slij^HYqj)) zzn_;j8y-GYao@2uG*A~a{_LwI*Dv1wd?!^2o96;tQsH+pLNA~vC2=oczA@tDV;R@K zv+|}A*t?el*6(jvxF@5YNwWRqZQbYFmPL858Jrw*{LBax1hP$zs;Wg^esT$#<{e#2 z$o3K1GR4EefB3hSSU(BQDat~lkSujm);nv2k)kg>qR4092dpd%D0SV64cvc%$z)2W z*Jn>ER(#34&KT}bxp4CmSyeOeyA<=9Po2D%(inE9Q?h(crfaT_4tQbvI+yYtbX~F@ z56I>VW|J^ZRtnu{$vz;!Tm5gJjYL-qrwl0e|9sKt{kg&5| zk!1$s#P{S0yEmrB-*LWr{yO(*K^VmBX9p-JSnc&0_cN4JcoI%8uYxlipN`SeQMd;E za)y%u6Y|r;tS~)}Q1ZP(i|NGy0f+ov}dMW83B=S8PB()X%#+NSR99+Hm?jmni z3tqTV@R8*`oRT!+&9CDp(B$p+qdX573LGn~&sNSfMEHWh`bkUmsJPTpuDApwgP7G(`- zk}^KX`SbmA+`qEQF{jwxo#N&>qTgZtk#*#12RE(xojrp$^n2Yf7Ee$oB#OAHN^WE27L!OE2whlEX^q9in!-U z7c@fnJo@7!kU0mVibhPZ>5LPn9QU4aJajU__iCzOM0a4Bj{~eZ9Mxlb?%2MjSX?)R ziKEo*K#f#@RffE(uvQR-lC0F^+L76c{rQ-(vREtGn@%u|V>&9q2(q$ZKCKu{OZMke z#(7TGlr)W|&MjqCQ`!b2HC3*WvMpikcT=*w#CJXqt{&szjScd;W##?+E{A;X=ekYyTAxwczmr73hx z;|x-^*O$V>lM*RFN=2eP3fs0^T24C*yol3_12z`>4EizCX~se~VR^Anyxiq){DY@B znB1mz@SSq2U}UuC@zM(w$4>21X93l1qIE*PX76SlCmt-=zuGnupX>x=i!AxOxQ6z`00!&F+`~&P9vtHDMAS9 zgC%C85bISu_z6LhNG@EwPF-u1kXU0VD-EsS8B&3%98Q20pl$oJD3HXVN8*L_M2~yo zRf1TuKielFqBfSE3i!k5-~Q%Bp8C%4J$Ysk$hQ9Y7K_I- z@^L_!-98E=J%CnYseiJhx3K6P}Q^RoeJI z!exhA9lEItmit{iPvTrfBL&wEret}Iwr$T)Cmm@wV4;(6bv&i6G#Eh?f;EPyJ0%?y zE1$ZGu z9nhu2HPAE;>j|`lAOhzswh_$gnqKI5?8F&v z1gF;*cqyOofBchz%a?xuzyEc--i12Yd<$QkHq^cRz&5T?Otx3(Z`5>;4H;cpZ(pDs z-1_{aZ|L854QER*A=R{ttG{=pcTT*z7kMiV?Fz7ZkKq1~4sq5pucv5jXljSC0*j-r zETOLuo~4%rgwkhLHe^{%pcJ*UIKYzvV;yUqB_^B8oWF1=ANN(HbZne0SU<(a2DuyC2^eM2Mw_b`1Hw-(p5cf-j+YXQ}MMht>Ob@Is9d5sIA6@0_50VuA21owYH^@;5>!l))K=iYicGvfKAlxU(yOxV^UK#ywr`e`1Kv1mj}X)(s0sT|?tQ zAlpr$G58V=$_gVY#I5(caQc?@3yR9pO%zg2`OBZ}@{h-`w|D2Equs4kT7h$INupG3Lklm2S#8+L=k!)eM5iK5ERFWC zhbp;FAcSM>o-tZCSZi7Aq~uNA3S#NDFuXCZMgY;)p`>6TjR;)Gxvw0fseD$~8?>$& zB@_os zOmC#bD-%o+qXI`c>SF44?;t#l$y2}*45oyGIl!nC9?cF zqxl@`90rGVqOB03&ASOgfpwtucYg+gFc8GPB=iN!6L?BeG;QNKZ5&!Pq=SlhFlXu5 zlxRtyD<3b2(T&A86i%V4-!c05uXcrD`U7HrdErkRjs2hm9fVG~FZ9L*2 z<gN;(-NUyD4nm2u z=Qx;6sBPOxQJS_4PKb6DL$m_{+V-Q4cE%Tuw#l?`h+D6ZB1I6ih9W&lRa%6VG}@A; zj($3%^UywV5K=iw82Vsiu3qReydn{Ip#A!EcfhP4aQxJWrf%c;3u%O-q^b?tNfzUP z%2+&M@bM5vA^n2Sej?)J(tzQ3NL5u#o0?*SU=6OITkvJomXEXA;YDH~z&82*wuYWtG$==0$cc<*d zK|bsXVj`w2*ot(li*uU|?x(&_=yuc8I z6`@qrwE^vjWr!~n-7s!T2W5l6FdxS(F0`E_opGdrAogM|&UTp8mV>Q6raDafo$p8M z(l#?6Q)tqK8NIcP`yZJS_G_vtKsUGAYzaXz39!PWnTEHrD&E9$9jMe|Ye{;hK71|^ zKv^2Lw|ksiUgF|xhgw^Fb!!9fK@_zDy`E}kc!5M)i&VE7aoigCx5hSkp;=o_P>5E3 zqz30Zl=Uc@iXiZi!YA@WmV%UdmC=-%Jw2h8IgN0@+e@!~FOf1tg>!@zcqkOD%z3RF z8fr>mkSNMhGU(UXIwj~!(1ubgHmBPdXGuIuyiie1KKN&NFDNGw<)kfy**@>^0*x2e zqmJvY_v*yx`I@>6u=bWnkaT!yMKex7IE+aSZ>RX@Un*JepJ2&L!L=bm zg(D0^>+iP{1dB^PLOG;rMX16^k|sV;ps)zE5h$rB<`$)I)f+g0w2H=9JQlzKB4vR^I*Q=S?f}0n5cjP_T+wuvVht!g?snM?Owy1?=Qs)S3QAonj(n%%QoP1t! zW4~f+JZ7RZV$Ua%5!CNgUgnUVm$)`)QBD)GgM@6aM>UV=rclgcnlfNzqhxu#Ku9pU zbqk$oSNvw2yn3DdeONE!3U>5$=U-s-#4Hb3x$#8% zdGrxM64WGKjHS*0iB&|Un|6VB00Lhr@|;#kO4xSRLlgRrKzjIofbuKG2N71kan2LB zodys8X89GI6=d^P9YQI~Y!WgXMKo3Wv+us}jn8ywR{(&kH%rc(xR=kIxtE_fb3ae4 zpTcQL=qnbJnB_R4EG$)N>34iOo{y@B8fP3C)=+4RX&jv>U?b|&OA@Se z1WM5fBNo#X=_FDKdSQ%p1_N}$1YZRhV~D*7Un+L91B7slP0qO&V@B8RjOzpNxlgQf z;<%t}44o*Y7bSGUgun}lLZ8qJ353Lx9;qKtJ3|tLNF=?)V>C6$peFFtt0^I)eV^=B zPQ6g})zk7hmYKExWB7ea1a9hP_dTi!*2kuaN){?vnN-% z_n6|LGwaw)GAVM7E%(}(cioWBYbw(giThp~H&H^7gl%rQ5f)!4Qa{3zickdzCkbRg zWeOV8FcSq@Y4*1}*!s>D*IeG5@^ha$j#8S-TT?tCSnl^}OskFW`wFWKMJ-rc?4qn7 zkO6`6Xq=@M4fDD}C@{3m>9%(RvgzygGq+~?d+ybI`fSAZbj~fp)3Tx#4MxY_fqe+(GQitXFgrC5d?H&AJxE( zX3l&Zys5gfR2KW%3cEWx_#G!tN=`1tEcHDS-{ZmK0mpg~4wyC-jj$Li(N#rJTVhWl zq>pqp7DHZ|yUPHMt;TqM%E7^uV=D_xpD77$>10M;gcJ?h8GK(LB`73LIGl7;8l-ke z;bAa%Qec}_xOHANH~}kBhgp^}*$tt*^HOux!gP1STDL=JC2_?X9&K5zxfLb zoEmtH>XLpE69pb&8wMirJ>no{QrFZtl-I#F6_Jwop5&q95eG#{8W)E<4ElPaK!7e$ zUdYv*cESc?-5i=nhRrOU`njtT{S=(Uwo&Y_LQ^94!Zp=9gUPO6I0 zT(WcV`!whK0D11*bvy$LX~Jskb7HYa>?urb&_*MXZTf?S%GM-7j7LCs;jQa>%aP*h zv_iJ~U#3+_<}BspO)9q>-#h!?K{|=#qw8I|aYQUaZtjh_xi@8AG?+${mo-(TNri`R z93g^%?=uKO){~UQFrlwvR+2+}5_~)AV#4ldN?ui5*xJEYifJ{cXeuUIiKl$DbyT&+ zQxfZI9Ex5XVyLLCW~xi(O^tSj(rNaJj9S;EVT9**Snb%KP1u=DnU@t6plO}n>smz)!~q)QG5 z+P54`GnRWDdV$YEoRCUM;vCXA5^LF;Wz={AMb@+F?%Hk-x@v^G?Y25G5u&9p3$cnIMb&I%5uZ68{J#9~|d5Cfi*D5c1C z#n#Ygc>VAUet>`dwM}MaffO*+mU=QpG#VetiSB@Y7!mpk(->xDD|P4x3TfWD2KSSn zu$&!q@KA(-M{aB8!#9@@IaJhw8(Gc%{)Ap9rspd>0h6MpsB3nzl37t>wZ<0?fg`Id z`&q?7Su@c!o6{+QywfF-?|{`s1yV5@?V+S)QkMjtkFl0+)TMR}wb5V=N;-d7Z7}nU-3dJZjF0_3tC-UkkZ5g~mj#Ux6qDQ6%^o(&!tv7HoKwA! z2uEQIS{pP1>25unaBOBJtC3GE1X4I6shHLcl`%-IsI0?#HP`qDjvu@d?hIgd)s`U*E5-fEZv*n8iT;G zvmJ0Z<^Mc?&GPW+j1?QBjRqwNg`lb$JirGEZQ03doODE%w%d?4SZk4iM~%dLF9!cB zHuTDs-j8@e5IVGlv=gBZpcA%&PkGTW=y;@l8yYS1hO`q9dJ2TZ8i#2tg{|=kxUub1 z?ykZsDYAFLhd#+PPri7-J@*tWrZK%FKva%#Ra2KWyL%&S0F|}u?!3LjyPaK!6&`6E zaDFFax_h{!CBGljA&k8WQ8?~D#o`cNn=2nkfw2~eAV%OjC@tU|o`PNy-94LNKdC50z}9fg z=D~>64@mrowSFHb1(Da5$3=;c@+7V?$l8%lDjMU6{SawITQGAMvOm*oAB-rP8Y>;8 zu5YPD8)^?;z8H~B-r1IJdsp+~OLzXf@Y z3j#7zGs!b>l9@HEE(|DK1EHd^HO>j*FhpsMvX-oNoH(<7cNl>5HG{6lspH4ld`aRO zL0LC#@>*5k2a2MqkV1j<(O7D05Y8c_-y*nl;gydo;Kq$RdNX$% zX9Tl@fSqwh*bSJ}HBlGFI~h?LGOY^&BWRSOmw42shA^fPKB;H%D~-h69R?8hC#)@= zX8YQCgpdTvGRbqSZ>dbfaDPg#A0l+Cm=^jzq7oEkgRVTDJg3;-xof<=BiooMUy_((Cx7f#I>Ujx&QES}PWU5Ot6pUTx6VGFUs{ z6CXd$eG46=soBdiin>DhfDgOl35{upY5#e)(*=y3h|Wy+>Tsa6wcmRHE270n6*pEwGz z!r+8pJ_?Qo{}H!Au(uDt`{jmnv(eqL0@RJf_abC1z*qvMUM*yOvwX<$(}KqzevnWfV5}wyeD>xg-*{HD zdHF*MiB7D zzx-DjZ(Sw|eJ%acnT)w=A*54Jd zRZ3#a8`C0gUfp`1Z}x|iBLldTyk_uwzT&68@Nu$v!RJ2zasK2_zR86P+i&=j+YSCB z-aSVKa0f`!h@be}6a3L1ex0V#IOjNVe1*UED_bp6{WXL)PHzF5t)j zK0p>0x;*&s8F27tUw@AKPY(F#Lnnx$PvHqk8W_I)%r%~R>ipZjrc@Ho^Jwa$1i5#^ zkpX-_{MCQ=XZVF*_!OlPbR&;?KEyONH+S~YGN!5vb|;$u^Phc zilZ>-2f*s;0>AiIK8taVs>rA&HyKZ7c%I_I#j9-Y47qx9kDcus96zymr*HQ|#nB4z z0r2_He~iU$z~+Ibwh|MhM2Sz9mn5B(3!4XwCKFz~su>p9oxa@<6-O(;2f$DN^p9Xv z%A_zDCm0ukdF7}ZO=Cegi&Ozh`8@i_z1(x(u{(Xs9~zEUfDeGLeeGGggD(5qH<-`o z^p=mY)CrJ6GTGh3k5U$b4oN6cSbqK&KEc7k!^F~~oR0a^ue`|3?eU#{j2}vl4B!JG zjAOR<4=Brusw|jgB}z(`Q$^hEV{(lWhMoN}Qu?ef4(Ru~JaFH=EX43{{o;@DU;H=! zl&e?XcrbRv55|!T^Z{_=#x8??k94q1xOkdbB}jdb^_2yd27MkmyTRI0pZkvwIJ42k znToZg0lpGMNr#iCPw)uns!5WNjg0Aq{!t z>@fzN0FMTceC+-W9y-0k+2e~WrII=uQ#UojHT=b&dh|{|$`2h!2Jk);#{rK%dWO2p z2|YnI8PiDv;!sjG8r@XvPjYlVW<1Y%{>naHloEyk))?X_WLAO^AxS6x{{QfZcf`>i z;C-Omjftax-MtAQc=_^8dW${E*^Grwz=LO&$cmD(s;P}5AMc}tBlHzjU6bV{agq}F z0Z4(aa%v(*)1w2g_nIREcpv!B{^nog_{nv?{MB=WNteinY&0Z}0#2;=C~CuSJjIjX z`7v5MLMiA+;DsKmi#?J~7thrsfrpg=7q0Db<>u&4KiUr+M+WddkPHSq{@4RN^3gL~ z*`6RwiL^DfHW+6S2&6LzClJEnkW^X_d5$=6B+8;pK_oRrUUGADh^;l_{dblicf|MS zLvH{=Ioz9dTDeWZ%9~zCh&HYH703Cas7 z%K~R}gpw$wFvc*;ORC(k7)z=u=gO5Wu3o;$GtXRp&z}2;mJhuFeDN>AOM7F^J)O|x zudAzl2byutwJ(;whx8MymNYiQvyN^WBe6&Up(ja`1g#rp^PHxbB9%lbpOdH0P}Z7S zc*JR+aaA&#WjuJ_2LI2$`o??s)JMF+hdv5)P_1L60%dsZh?nZ!2~urd-6qQ_*4Nfp zSsG9j1;hP4>U_%TAfexhP!guIDf2wTSa4oS)EO|#3NBr~OjDJ3LZiYCHe8@E0YRL+ zM^AjjYx&Tx0DtiNH&MQasUu#i!e-68lMIdHfcbnz5}l+}2G5oRfna%Yg|&?hJSlnk z(q-z#P*#S1ZvbA%I4c;9CkPy!P~c(dCq6-VoL~Dp|2}6K6ici4&(t`%BCk#ii{T=dMl2MVGkKCrx7dy&lU8J(d<0sPZ`*%YE)WeS*+~ z;b_d}<_*5{t>@mq=lYOyWB~62PkrrK{;%Kt3PIXO%b0VUCC_ipdG_j`@KHa z%6VVX(&GHy+t+bGMrWnXkALkWUF91MBC9AjlL@PTi(;?Kt>CVmhaDE&h>dx4Fcb{@vV|2T-1uBM%Z-Tl8pVqk=oNoao8Nm# zWooLrB#tE3f>4$(fA>Ch?!0-H9_L#CT`R1SG@~v>VOVc=h^kfZ{Epy!E#LpFi>^X! zt!Q-C7)2$m)uVkvee!+Tab5t`6b6db4U0yu@g`@4h} zfX8XP06b3P1>kWSF946zcmccwKLL69@d9`WLU{8mJHCcrhV_F2%Z?Yo3-RLtF5m_5 zLVN_^0$u~AjBp(d0JC@YQ8ULdcFZvoyS zbPaU{d2YCQvzT{rmI5z;x0KzT#=MKL6nFug7vI}hO1uEhK_IOk7Fbfe0M3CAHkTJK zfa3@t@FsByU)#sAfO!KG;EwY50`N0R7aCtX=jF($1BD3W;qNaRs5;8u+oumgcp)q( zzE;l5kyD!*YxL7&NKZt@XX)WvY0c{LNCe`S-;ENqT;7QTpK=>x`_A| z;JSGO4S@)JYx1V>0=Q=0g!9_7x?i44;k*EXuqFug%U^WTXT{|m&>Fzs!50SSV*sNA zRC`KmbA$>Fv;7t(Yf#PNXD7&8Ag~0|VyXZkEnu*9z=iuX*2e;ig!2LjSNb$I_Gu=9 zB$mYS9#NzaLQzd4vQfmi*QA=n7<1_CwhjoQ64frK#_61|!1FpdF90PiVZFk7OOm!E zwbe|g8P-A>Opq;?Hpq*v&UV8)X2D|p2hRN6wf7azBAfPzkApr z5te`Wc*Oec5(rRn$YfklP791RU^EB2YaBf25-5wQpP4R*590_^N=z-mygg=}&i?TB z6!r>mz6CfO(S>j`VPZ#^Cj-C|g^H*V5r=Jhk2+NJ2%86lt(a=kfKVWe!D@ji6jlqY z2?#qg>T&Wcepnd%VBA@F0ay?X$@*qQwihuR-=)zh+5FJZ7a{$7A=y_3f(<&`l5}g2 zYSbd@x3T7#`D`r#sD>$l(uV>N9R4i826G}fN}qZW9LITUeBA{)fxUf`^c~6Ui!tJ0 zeEJ1~r%7ZB$JYx4Jn!&AoSrlE5`;R+E?oh_fIU*>A+C3U7OkDWc5EP^rLZS*lVSdt z_v+sfi1Gz*1T@b(Kb*ST2cf>uZN^^Z;v0L3wC$4PyZ~-|44WU7r$%Tyos6wCq`f|c z@bYF7fkA|4v;YEBrvQ1vA+2}N>%@5he0pPyvf{+(uBE%VLOW{nPj_m*^~nTeaO}V5 zcT$}zY<>FgaW}`5>O!COLXL_i044pZwhQ3Ar6$BY8MHti2C-HMY%64?)u5HOxtYY= zZW(0z`S;mZn9e>o_uq1I__r7|Fu6qNV|}K}YQb_iI&Ce~`tUgjUcP9@1NbZu@1_mH z4>kQ;DfjmzG(!e;$hS8p1X(~R6x}$bxz=YmT0t0#IK!cV=K|h9L8Cn*8zoQUgjYDC zIQt{dg*_QNJe_V~trx&6a9#inDfwn3DP_TT*Cat(kR}o)2HjAU6{x`S&+oU{?ZCZV z#dKg0mBAW|IPTcTvOTu4l;Z|rqo$gKuP(@&oF8Pret7n|7tBVvg7X4cNdjU8flNu$ zkl8e2JrbDJgi$GY+#4YS*lH!*Y#NegkKaFhm-^8ND*e(NzpeswHSb>Lkr2G|pM~=R zXmu1@jRs*L>1P$%3i1-R);g?P&1x&5KPlNCX3VmjJFPaIZ}<3Z56WWR&h2?!oUg$o zPspZ%cg!Hssx_SSIT#eWTaa16c+L>h-k zA!rbhYDK5hAni1;2N^|T=}j~C_9uuSq7^q;>vowHC4mq$+Z>J`ymIhr5$E9em;ihW z04Ul0qg5sjD|P}kV3H0Xt13m*s3B`5qXg#m8H-X))oZnJdU(z&hI(Gc>#0? z=x9SrNp5X)X(tV09WcpC(kLX*8Z4}JQ&!svgqnldkXje)?bn#OXL&rYgY&i5lmVS) z%-v7kXX~T)_gQpSZz>J&>N1KmL+**&_=U6oKWV;#lB2fqP5A@T!`mVI4^)G zku*CA!#YG)npQVONl4R(#}5x663ncoKOHm3Cln@UG|QP~f~?l-_BGZtF z029K_?hrD|aB{hZQ-l@8q(QAyru%*$p+&%X0sP0`|3(-|?hgW@8wE){L$wq;!#-&{ zW~ygAnhe+VCFq^R4dM9SGpHPg>u|B|aEjTZLFAoat{VgHs zRy-I-h$v#aGolO(y@M%M2xetKay#VFe{WpQ`GF5V>9Vp~^X0vmlZyz1vWF|W{Pdh_ z$9VyK{)Z;D)ySw~w%g)=rXlLnjG`=wTZ+NMh_C*%2Ei)m!)*{vaWS*4Z3o=FqxtQB l2H5;`>hnssLh-zm{|Aw|P^cj-0Mq~g002ovPDHLkV1f>ZN74WQ literal 0 HcmV?d00001 diff --git a/testing/resources/love2.png b/testing/resources/love2.png new file mode 100644 index 0000000000000000000000000000000000000000..e2612a857c850afa83db824f1b5a30d226508df0 GIT binary patch literal 680 zcmV;Z0$2TsP)Px%Vo5|nRCt{2o7+*tFc3vAv;sfS2Mqv2C;^I~4k&>z&<^}SE%3o?#!>9(vG=YF z@%7T0>Fr z7M27`Bhl~{h6Hy5z2Gfg3CEs;d&2|3)$^z89GV5p0p8+~&{RHifq%HX*n0hTds@v? zT>*1}A4^LmR2gf5KU?2z{{C1!(T+*4{xCI_Q2fPO_#s4^DX5xb_6Y#WB@}&$32#Y( zYL3alTS_Ekzo3A(7*NeI*XysE)5%KM`=Juv6Q+d859SJQVM!Pr2IoA~wPtFF+_B;v z>LOEH1;B14Y*oO2yz*(%N^so_{fBG>9KzMN469(NfZiw2I|nadYe?|?ADH_Op<#wY z;ZgzV8-Jk+SXUnyseoQfRU$HWKR~+~vZ$+|_3BUE3{h`~Eh-6Yct9{AVqr^AzyqQw zF$+tA3LX$nidwu9l<8FF4Q!4>;Ecn1otzc3R;9!U75J^LcMP@BnFvOfLyuc!0P_ zDp~>q9w0B1i;}>C2LuZx)e@NSfM}_#N&*`m5H6NxOHjZA;^p!z2`YFXV8eu0f)XAG z+A`BBK@ATCZkno<5CIPaZ<{NX5Cso(*f^P!5D5=-+&Y_zhz4J>Px%Vo5|nRCt{2o7+*tFc3vAv;sfS2Mqv2C;^I~4k&>z&<^}SE%3o?#!>9(vG=YF z@%7T0>Fr z7M27`Bhl~{h6Hy5z2Gfg3CEs;d&2|3)$^z89GV5p0p8+~&{RHifq%HX*n0hTds@v? zT>*1}A4^LmR2gf5KU?2z{{C1!(T+*4{xCI_Q2fPO_#s4^DX5xb_6Y#WB@}&$32#Y( zYL3alTS_Ekzo3A(7*NeI*XysE)5%KM`=Juv6Q+d859SJQVM!Pr2IoA~wPtFF+_B;v z>LOEH1;B14Y*oO2yz*(%N^so_{fBG>9KzMN469(NfZiw2I|nadYe?|?ADH_Op<#wY z;ZgzV8-Jk+SXUnyseoQfRU$HWKR~+~vZ$+|_3BUE3{h`~Eh-6Yct9{AVqr^AzyqQw zF$+tA3LX$nidwu9l<8FF4Q!4>;Ecn1otzc3R;9!U75J^LcMP@BnFvOfLyuc!0P_ zDp~>q9w0B1i;}>C2LuZx)e@NSfM}_#N&*`m5H6NxOHjZA;^p!z2`YFXV8eu0f)XAG z+A`BBK@ATCZkno<5CIPaZ<{NX5Cso(*f^P!5D5=-+&Y_zhz4J> Date: Thu, 5 Oct 2023 23:44:15 +0100 Subject: [PATCH 019/409] Test MacOS Testing workflow --- .github/workflows/main.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 50c0236c1..ee0121242 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -233,6 +233,14 @@ jobs: with: name: love-macos path: love-macos.zip + - name: Run All Tests + run: love-macos/love.app testing --runAllTests + - name: Test Report + uses: dorny/test-reporter@v1 + with: + name: Test Output + path: testing/output/*.xml + reporter: jest-junit iOS-Simulator: runs-on: macos-latest steps: From db600b7fb6e74807a272c20fd9922aecb94dc96b Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:08:39 +0100 Subject: [PATCH 020/409] output to src --- .github/workflows/main.yml | 2 +- .gitignore | 4 +++- testing/classes/TestSuite.lua | 8 ++++--- testing/output/readme.md | 2 ++ testing/readme.md | 11 +++++----- testing/todo.md | 39 +++++++++++++++++------------------ 6 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 testing/output/readme.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ee0121242..787bf5b4a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -234,7 +234,7 @@ jobs: name: love-macos path: love-macos.zip - name: Run All Tests - run: love-macos/love.app testing --runAllTests + run: love-macos/love.app/Contents/MacOS/love testing --runAllTests - name: Test Report uses: dorny/test-reporter@v1 with: diff --git a/.gitignore b/.gitignore index a8b316a2d..5bc5b9401 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,6 @@ stamp-h1 /src/love /src/tags .vs/ -.vscode/ \ No newline at end of file +.vscode/ +/testing/output/*.xml +/testing/output/*.html diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 9552b5aee..012947771 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -144,9 +144,11 @@ TestSuite = { '
  • ' .. finaltime .. 's


' -- @TODO use mountFullPath to write output to src? - love.filesystem.createDirectory('output') - love.filesystem.write('output/' .. self.output .. '.xml', xml .. self.xml .. '') - love.filesystem.write('output/' .. self.output .. '.html', html .. self.html .. '') + love.filesystem.mountFullPath(love.filesystem.getSource() .. "/output", "tempoutput", "readwrite") + love.filesystem.remove('tempoutput/' .. self.output .. '.xml') + love.filesystem.remove('tempoutput/' .. self.output .. '.html') + love.filesystem.write('tempoutput/' .. self.output .. '.xml', xml .. self.xml .. '') + love.filesystem.write('tempoutput/' .. self.output .. '.html', html .. self.html .. '') self.module:log('grey', '\nFINISHED - ' .. finaltime .. 's\n') local failedcol = '\27[31m' diff --git a/testing/output/readme.md b/testing/output/readme.md new file mode 100644 index 000000000..1a1059a7b --- /dev/null +++ b/testing/output/readme.md @@ -0,0 +1,2 @@ +# Testing Output +Any tests run will output an XML and HTML file here, assuming the tests are run with readwrite permissions for this repo \ No newline at end of file diff --git a/testing/readme.md b/testing/readme.md index 4269e4447..a156d2675 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -34,9 +34,9 @@ If you want to specify only 1 specific method only you can use: All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level. -An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in your save directory, along with a `HTML` file with a summary of all tests (including visuals for love.graphics tests). +An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in the `/output` directory, along with a `HTML` file with a summary of all tests (including visuals for love.graphics tests) - you will need to make sure the command is run with read/write permissions for the source directory. > Note that this can only be viewed properly locally as the generated images are written to the save directory. -> An example of both types of output can be found in the `/output` folder +> An example of both types of output can be found in the `/examples` folder --- @@ -45,6 +45,7 @@ Each method has it's own test method written in `/tests` under the matching modu When you run the tests, a single TestSuite object is created which handles the progress + totals for all the tests. Each module has a TestModule object created, and each test method has a TestMethod object created which keeps track of assertions for that method. You can currently do the following assertions: +- **assertNotNil**(value) - **assertEquals**(expected, actual) - **assertNotEquals**(expected, actual) - **assertRange**(actual, min, max) @@ -60,14 +61,14 @@ Example test method: love.test.filesystem.read = function(test) -- setup any data needed then run any asserts using the passed test object local content, size = love.filesystem.read('resources/test.txt') - test:assertNotEquals(nil, content, 'check not nil') + test:assertNotNil(content) test:assertEquals('helloworld', content, 'check content match') test:assertEquals(10, size, 'check size match') content, size = love.filesystem.read('resources/test.txt', 5) - test:assertNotEquals(nil, content, 'check not nil') + test:assertNotNil(content) test:assertEquals('hello', content, 'check content match') test:assertEquals(5, size, 'check size match') - -- no need to return anything just cleanup any objs if needed + -- no need to return anything or cleanup, GCC is called after each method end ``` diff --git a/testing/todo.md b/testing/todo.md index 969cbf547..86fc2b105 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -2,25 +2,24 @@ # v0.2 -## Changed -- Added tests for all obj creation, transformation, window + system info graphics methods -- Added half the state methods for graphics + added placeholders for missing drawing methods -- Added TestMethod:assertNotNil() for quick nil checking -- Added time total to the end of each module summary in console log to match file output - -- Removed a bunch of unessecary nil checks -- Removed :release() from test methods, collectgarbage("collect") is called between methods instead - -- Renamed /output to /examples to avoid confusion - -- Replaced love.filesystem.newFile with love.filesystem.openFile -- Replaced love.math.noise with love.math.perlinNoise / love.math.simplexNoise - -- Fixed newGearJoint throwing an error in 12 as body needs to be dynamic not static now - -- Some general cleanup, incl. better comments and time format in file output - ## Todo -- graphics state methods -- graphics drawing methods +- finish graphics state methods +- start graphics drawing methods +- start object methods +- look into XML reader github actions to display results in readme? + dorny/test-reporter@v1.6.0 seems to do it + would need to run the tests first then could use it like: + + - name: Run Tests + - run: PATH_TO_BUILT_APP ./testing --runAllTests + - name: Test Report + uses: dorny/test-reporter@v1 + with: + name: Test Output + path: output/*.xml + reporter: jest-junit + + and d. check format: https://github.com/testmoapp/junitxml + + - need a platform: format table somewhere for compressed formats (i.e. DXT not supported) From fae3b6ff633375a1e8e7ddb893433bee8a096f24 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:37:35 +0100 Subject: [PATCH 021/409] fix xml format --- .github/workflows/main.yml | 8 ++++++++ testing/classes/TestMethod.lua | 7 ++++--- testing/classes/TestSuite.lua | 2 -- testing/todo.md | 20 ++++++-------------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 787bf5b4a..70d7a9489 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -205,6 +205,14 @@ jobs: with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb + - name: Run All Tests + run: build/love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}.exe testing --runAllTests + - name: Test Report + uses: dorny/test-reporter@v1 + with: + name: Test Output + path: testing/output/*.xml + reporter: jest-junit macOS: runs-on: macos-latest steps: diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 8fa55080f..0294756e3 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -309,14 +309,15 @@ TestMethod = { output = self.result.key .. ' ' .. self.result.message end if output == '' and self.skipped == true then + failure = '\t\t\t\n' .. - failure .. '\t\t\n' + failure .. '\t\t\n' -- unused currently, adds a preview image for certain graphics methods to the output local preview = '' diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 012947771..99ee6bbcc 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -145,8 +145,6 @@ TestSuite = { -- @TODO use mountFullPath to write output to src? love.filesystem.mountFullPath(love.filesystem.getSource() .. "/output", "tempoutput", "readwrite") - love.filesystem.remove('tempoutput/' .. self.output .. '.xml') - love.filesystem.remove('tempoutput/' .. self.output .. '.html') love.filesystem.write('tempoutput/' .. self.output .. '.xml', xml .. self.xml .. '') love.filesystem.write('tempoutput/' .. self.output .. '.html', html .. self.html .. '') diff --git a/testing/todo.md b/testing/todo.md index 86fc2b105..1a9e28a8d 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -6,20 +6,12 @@ - finish graphics state methods - start graphics drawing methods - start object methods -- look into XML reader github actions to display results in readme? - dorny/test-reporter@v1.6.0 seems to do it - would need to run the tests first then could use it like: - - - name: Run Tests - - run: PATH_TO_BUILT_APP ./testing --runAllTests - - name: Test Report - uses: dorny/test-reporter@v1 - with: - name: Test Output - path: output/*.xml - reporter: jest-junit - - and d. check format: https://github.com/testmoapp/junitxml +- some joystick/input stuff could be at least nil checked maybe? +- add test run for linux, windows, + ios builds +- pass in err string returns to the test output + maybe even assertNotNil could use the second value automatically + test:assertNotNil(love.filesystem.openFile('file2', 'r')) wouldn't have to change - need a platform: format table somewhere for compressed formats (i.e. DXT not supported) + could add platform as global to command and then use in tests? From 6c29497be2a0b3bb705f089ceeb607148fe824ab Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 00:53:29 +0100 Subject: [PATCH 022/409] skipped format --- testing/classes/TestMethod.lua | 2 +- testing/todo.md | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 0294756e3..7ef97ec81 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -309,7 +309,7 @@ TestMethod = { output = self.result.key .. ' ' .. self.result.message end if output == '' and self.skipped == true then - failure = '\t\t\t\n' output = self.skipreason end diff --git a/testing/todo.md b/testing/todo.md index 1a9e28a8d..e64f5e165 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -1,17 +1,15 @@ `/Applications/love_12.app/Contents/MacOS/love ./testing` -# v0.2 - ## Todo +- fix XML format +- check test runs for windows setup +- add runs for linux + ios - finish graphics state methods - start graphics drawing methods - start object methods - some joystick/input stuff could be at least nil checked maybe? -- add test run for linux, windows, + ios builds - pass in err string returns to the test output maybe even assertNotNil could use the second value automatically test:assertNotNil(love.filesystem.openFile('file2', 'r')) wouldn't have to change - - - need a platform: format table somewhere for compressed formats (i.e. DXT not supported) - could add platform as global to command and then use in tests? + could add platform as global to command and then use in tests? \ No newline at end of file From a513320a4741b2c4b140f9d983a7a43b5b8c714a Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 10:10:08 +0100 Subject: [PATCH 023/409] prevent empty tag dorny/test-reporter@v1 will fail to parse tags that are empty as it's expected a message both in the attr and inside --- .github/workflows/main.yml | 2 +- testing/classes/TestMethod.lua | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 70d7a9489..4f7aa5628 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -206,7 +206,7 @@ jobs: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb - name: Run All Tests - run: build/love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}.exe testing --runAllTests + run: "build/love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}.exe" "testing" --console --runAllTests - name: Test Report uses: dorny/test-reporter@v1 with: diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 7ef97ec81..7422fb935 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -303,13 +303,15 @@ TestMethod = { -- get failure/skip message for output (if any) local failure = '' local output = '' + -- @NOTE if you don't put anything inside of the then + -- dorny/test-reporter@v1 will fail to parse it if self.passed == false and self.skipped == false then failure = '\t\t\t\n' + self.result.message .. '">' .. self.result.key .. ' ' .. self.result.message .. '\n' output = self.result.key .. ' ' .. self.result.message end if output == '' and self.skipped == true then - failure = '\t\t\t\n' + failure = '\t\t\t\n' output = self.skipreason end From ac5f97e656a3e8a0669dfedda4447ccc70804fa0 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 10:14:44 +0100 Subject: [PATCH 024/409] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4f7aa5628..6eac9e3d8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -206,7 +206,7 @@ jobs: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb - name: Run All Tests - run: "build/love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}.exe" "testing" --console --runAllTests + run: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}.exe testing --console --runAllTests - name: Test Report uses: dorny/test-reporter@v1 with: From 04293d3fbd1c5712ee23cc47e165b060f53622c2 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:26:51 +0100 Subject: [PATCH 025/409] use love-test-report action added md support to work with love-test-report, a basic action made to just dump md files into repo checks --- .github/workflows/main.yml | 24 +++++++++++++----------- .gitignore | 1 + testing/classes/TestMethod.lua | 6 ++++-- testing/classes/TestModule.lua | 11 +++++++++-- testing/classes/TestSuite.lua | 18 +++++++++++++++++- testing/output/readme.md | 2 +- testing/todo.md | 3 +-- 7 files changed, 46 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6eac9e3d8..31c982836 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -205,14 +205,16 @@ jobs: with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb + - name: Build Test Exe + run: cmake --build build --config Release --target install - name: Run All Tests - run: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}.exe testing --console --runAllTests - - name: Test Report - uses: dorny/test-reporter@v1 + run: install\love.exe testing --console --runAllTests + - name: Love Test Report + uses: ellraiser/love-test-report@main with: - name: Test Output - path: testing/output/*.xml - reporter: jest-junit + name: Love Testsuite Windows + title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report + path: testing/output/lovetest_runAllTests.md macOS: runs-on: macos-latest steps: @@ -243,12 +245,12 @@ jobs: path: love-macos.zip - name: Run All Tests run: love-macos/love.app/Contents/MacOS/love testing --runAllTests - - name: Test Report - uses: dorny/test-reporter@v1 + - name: Love Test Report + uses: ellraiser/love-test-report@main with: - name: Test Output - path: testing/output/*.xml - reporter: jest-junit + name: Love Testsuite MacOS + title: macos-test-report + path: testing/output/lovetest_runAllTests.md iOS-Simulator: runs-on: macos-latest steps: diff --git a/.gitignore b/.gitignore index 5bc5b9401..f84038cd7 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,4 @@ stamp-h1 .vscode/ /testing/output/*.xml /testing/output/*.html +/testing/output/*.md diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 7422fb935..6f9b182f9 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -303,18 +303,20 @@ TestMethod = { -- get failure/skip message for output (if any) local failure = '' local output = '' - -- @NOTE if you don't put anything inside of the then - -- dorny/test-reporter@v1 will fail to parse it if self.passed == false and self.skipped == false then failure = '\t\t\t' .. self.result.key .. ' ' .. self.result.message .. '\n' output = self.result.key .. ' ' .. self.result.message + -- append failures if any to report md + love.test.mdfailures = love.test.mdfailures .. '> 🔴 ' .. self.method .. ' \n' .. + '> ' .. output .. ' \n\n' end if output == '' and self.skipped == true then failure = '\t\t\t\n' output = self.skipreason end + -- append XML for the test class result self.testmodule.xml = self.testmodule.xml .. '\t\t\n' .. self.xml .. '\t\n' -- add html to main output - local status = '🔴' - if self.failed == 0 then status = '🟢' end love.test.html = love.test.html .. '

' .. status .. ' love.' .. self.module .. '

    ' .. '
  • 🟢 ' .. tostring(self.passed) .. ' Tests
  • ' .. '
  • 🔴 ' .. tostring(self.failed) .. ' Failures
  • ' .. diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 99ee6bbcc..0396d841b 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -17,6 +17,8 @@ TestSuite = { time = 0, xml = '', html = '', + mdrows = '', + mdfailures = '', fakequit = false, windowmode = true, @@ -124,10 +126,23 @@ TestSuite = { -- @method - TestSuite:printResult() -- @desc - prints the result of the whole test suite as well as writes - -- the XML + HTML of the testsuite output + -- the MD, XML + HTML of the testsuite output -- @return {nil} printResult = function(self) local finaltime = UtilTimeFormat(self.time) + + local md = '\n\n' .. + '**' .. tostring(self.totals[1] + self.totals[2] + self.totals[3]) .. '** tests were completed in **' .. + finaltime .. 's** with **' .. + tostring(self.totals[1]) .. '** passed, **' .. + tostring(self.totals[2]) .. '** failed, and **' .. + tostring(self.totals[3]) .. '** skipped\n\n### Report\n' .. + '| Module | Passed | Failed | Skipped | Time |\n' .. + '| --------------------- | ------ | ------ | ------- | ------ |\n' .. + self.mdrows .. '\n\n### Failures\n' .. self.mdfailures local xml = '') love.filesystem.write('tempoutput/' .. self.output .. '.html', html .. self.html .. '') + love.filesystem.write('tempoutput/' .. self.output .. '.md', md) self.module:log('grey', '\nFINISHED - ' .. finaltime .. 's\n') local failedcol = '\27[31m' diff --git a/testing/output/readme.md b/testing/output/readme.md index 1a1059a7b..bff4c6375 100644 --- a/testing/output/readme.md +++ b/testing/output/readme.md @@ -1,2 +1,2 @@ # Testing Output -Any tests run will output an XML and HTML file here, assuming the tests are run with readwrite permissions for this repo \ No newline at end of file +Any tests run will output an XML, MD, and HTML file here, assuming the tests are run with readwrite permissions for this repo \ No newline at end of file diff --git a/testing/todo.md b/testing/todo.md index e64f5e165..f5951c748 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -1,9 +1,8 @@ `/Applications/love_12.app/Contents/MacOS/love ./testing` ## Todo -- fix XML format - check test runs for windows setup -- add runs for linux + ios +- add runs for linux + ios? - finish graphics state methods - start graphics drawing methods - start object methods From 6a0ff067c8a6f8c2a4f51a49d7c5a493959b1b24 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:39:43 +0100 Subject: [PATCH 026/409] fixed test.filesystem.openFile --- .github/workflows/main.yml | 6 +++--- testing/tests/filesystem.lua | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 31c982836..c5ae7da5b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -206,9 +206,9 @@ jobs: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb - name: Build Test Exe - run: cmake --build build --config Release --target install + run: cmake --build build --config Release --target testbuild - name: Run All Tests - run: install\love.exe testing --console --runAllTests + run: testbuild\love.exe ./testing/main.lua --console - name: Love Test Report uses: ellraiser/love-test-report@main with: @@ -244,7 +244,7 @@ jobs: name: love-macos path: love-macos.zip - name: Run All Tests - run: love-macos/love.app/Contents/MacOS/love testing --runAllTests + run: love-macos/love.app/Contents/MacOS/love testing - name: Love Test Report uses: ellraiser/love-test-report@main with: diff --git a/testing/tests/filesystem.lua b/testing/tests/filesystem.lua index a360dc6d8..248aa39c4 100644 --- a/testing/tests/filesystem.lua +++ b/testing/tests/filesystem.lua @@ -231,10 +231,11 @@ end -- love.filesystem.openFile -- @NOTE this is just basic nil checking, full obj test are in objects.lua love.test.filesystem.openFile = function(test) - test:assertNotNil(love.filesystem.openFile('file2', 'r')) - test:assertNotNil(love.filesystem.openFile('file2', 'w')) - test:assertNotNil(love.filesystem.openFile('file2', 'a')) - test:assertNotNil(love.filesystem.openFile('file2', 'c')) + test:assertNotNil(love.filesystem.openFile('file2.txt', 'w')) + test:assertNotNil(love.filesystem.openFile('file2.txt', 'r')) + test:assertNotNil(love.filesystem.openFile('file2.txt', 'a')) + test:assertNotNil(love.filesystem.openFile('file2.txt', 'c')) + love.filesystem.remove('file2.txt') end From 5ac5438cb4dc746f653c319f58ab5c22d4248d3d Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:02:12 +0100 Subject: [PATCH 027/409] try lovec instead --- .github/workflows/main.yml | 4 ++-- testing/todo.md | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c5ae7da5b..c8a990cb2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -206,9 +206,9 @@ jobs: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb - name: Build Test Exe - run: cmake --build build --config Release --target testbuild + run: cmake --build build --config Release --target install - name: Run All Tests - run: testbuild\love.exe ./testing/main.lua --console + run: install\lovec.exe ./testing/main.lua - name: Love Test Report uses: ellraiser/love-test-report@main with: diff --git a/testing/todo.md b/testing/todo.md index f5951c748..78ca67640 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -1,14 +1,19 @@ `/Applications/love_12.app/Contents/MacOS/love ./testing` -## Todo -- check test runs for windows setup -- add runs for linux + ios? -- finish graphics state methods -- start graphics drawing methods -- start object methods -- some joystick/input stuff could be at least nil checked maybe? -- pass in err string returns to the test output +## CI +- [ ] ignore test suite for windows AMD +- [ ] add test run to linux + ios builds +- [ ] add metal/vulkan runs + +## TESTSUITE +- [ ] finish graphics state methods +- [ ] start graphics drawing methods +- [ ] start object methods + +## FUTURE +- [ ] pass in err string returns to the test output maybe even assertNotNil could use the second value automatically test:assertNotNil(love.filesystem.openFile('file2', 'r')) wouldn't have to change -- need a platform: format table somewhere for compressed formats (i.e. DXT not supported) +- [ ] some joystick/input stuff could be at least nil checked maybe? +- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) could add platform as global to command and then use in tests? \ No newline at end of file From a620910121816f1e969fe56adc77110ac996f0b0 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:33:53 +0100 Subject: [PATCH 028/409] add renderer alts. --- .github/workflows/main.yml | 41 ++++++++++++++++++++++++++++---------- testing/todo.md | 3 +-- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c8a990cb2..baa2e7286 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -206,14 +206,27 @@ jobs: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb - name: Build Test Exe + if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - - name: Run All Tests - run: install\lovec.exe ./testing/main.lua - - name: Love Test Report + - name: Run All Tests (OpenGL) + if: steps.vars.outputs.arch != 'ARM64' + run: install\lovec.exe testing/main.lua --renderers opengl + - name: Love Test Report (OpenGL) + if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: - name: Love Testsuite Windows - title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report + name: Love Testsuite Windows (OpenGL) + title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-opengl + path: testing/output/lovetest_runAllTests.md + - name: Run All Tests (Vulkan) + if: steps.vars.outputs.arch != 'ARM64' + run: install\lovec.exe testing/main.lua --renderers vulkan + - name: Love Test Report (Vulkan) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (Vulkan) + title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-vulkan path: testing/output/lovetest_runAllTests.md macOS: runs-on: macos-latest @@ -243,13 +256,21 @@ jobs: with: name: love-macos path: love-macos.zip - - name: Run All Tests - run: love-macos/love.app/Contents/MacOS/love testing - - name: Love Test Report + - name: Run All Tests (OpenGL) + run: love-macos/love.app/Contents/MacOS/love testing --renderers opengl + - name: Love Test Report (OpenGL) uses: ellraiser/love-test-report@main with: - name: Love Testsuite MacOS - title: macos-test-report + name: Love Testsuite MacOS (OpenGL) + title: macos-test-report-opengl + path: testing/output/lovetest_runAllTests.md + - name: Run All Tests (metal) + run: love-macos/love.app/Contents/MacOS/love testing --renderers opengl + - name: Love Test Report (metal) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite MacOS (Metal) + title: macos-test-report-metal path: testing/output/lovetest_runAllTests.md iOS-Simulator: runs-on: macos-latest diff --git a/testing/todo.md b/testing/todo.md index 78ca67640..480c19e7a 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -2,8 +2,7 @@ ## CI - [ ] ignore test suite for windows AMD -- [ ] add test run to linux + ios builds -- [ ] add metal/vulkan runs +- [ ] add test run to linux (opengl+vulkan) + ios builds (opengl+metal) ## TESTSUITE - [ ] finish graphics state methods From 8f10ba907c8da6a00bf51f660950ca73e7b4add1 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:58:55 +0100 Subject: [PATCH 029/409] check flag change --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index baa2e7286..f8ef7a5dd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -210,7 +210,7 @@ jobs: run: cmake --build build --config Release --target install - name: Run All Tests (OpenGL) if: steps.vars.outputs.arch != 'ARM64' - run: install\lovec.exe testing/main.lua --renderers opengl + run: install\lovec.exe testing/main.lua - name: Love Test Report (OpenGL) if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main @@ -257,7 +257,7 @@ jobs: name: love-macos path: love-macos.zip - name: Run All Tests (OpenGL) - run: love-macos/love.app/Contents/MacOS/love testing --renderers opengl + run: love-macos/love.app/Contents/MacOS/love testing - name: Love Test Report (OpenGL) uses: ellraiser/love-test-report@main with: @@ -265,7 +265,7 @@ jobs: title: macos-test-report-opengl path: testing/output/lovetest_runAllTests.md - name: Run All Tests (metal) - run: love-macos/love.app/Contents/MacOS/love testing --renderers opengl + run: love-macos/love.app/Contents/MacOS/love testing --renderers metal - name: Love Test Report (metal) uses: ellraiser/love-test-report@main with: From ac9ae8252410cd7dc3117259ed7bef8b52516cda Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 7 Oct 2023 15:17:24 -0300 Subject: [PATCH 030/409] love.physics: simplify Body and Shape API. #1130 - Shapes are now directly attached to Bodies when they're created (similar to love 0.7 and older). - Fixtures are removed. - All methods that were in Fixtures now exist in Shapes. - All APIs that used or returned a Fixture now do the same with a Shape. - Add new love.physics.new*Shape variants that take a Body as the first parameter. - Deprecate the new*Shape APIs that don't take a Body. - Deprecate love.physics.newFixture (the deprecated function now returns a Shape). - Replace Body:getFixture and Body:getFixtures with Body:getShape and Body:getShapes (Body:getFixtures is deprecated). - Replace World:queryFixturesInArea and World:getFixturesInArea with World:queryShapesInArea and World:getShapesInArea (queryFixturesInArea is deprecated). - Replace Contact:getFixtures with Contact:getShapes (Contact:getFixtures is deprecated). - Replace all love.physics callback Fixture parameters with Shape parameters. - Deprecate ChainShape:getChildEdge. --- CMakeLists.txt | 4 - src/common/deprecation.cpp | 6 + src/common/deprecation.h | 2 + src/modules/physics/box2d/Body.cpp | 22 +- src/modules/physics/box2d/Body.h | 11 +- src/modules/physics/box2d/ChainShape.cpp | 29 +- src/modules/physics/box2d/ChainShape.h | 2 +- src/modules/physics/box2d/CircleShape.cpp | 8 +- src/modules/physics/box2d/CircleShape.h | 2 +- src/modules/physics/box2d/Contact.cpp | 17 +- src/modules/physics/box2d/Contact.h | 4 +- src/modules/physics/box2d/EdgeShape.cpp | 11 +- src/modules/physics/box2d/EdgeShape.h | 2 +- src/modules/physics/box2d/Fixture.cpp | 349 ---------------- src/modules/physics/box2d/Fixture.h | 216 ---------- src/modules/physics/box2d/Physics.cpp | 135 +++--- src/modules/physics/box2d/Physics.h | 35 +- src/modules/physics/box2d/PolygonShape.cpp | 6 +- src/modules/physics/box2d/PolygonShape.h | 2 +- src/modules/physics/box2d/Shape.cpp | 395 ++++++++++++++++-- src/modules/physics/box2d/Shape.h | 132 +++++- src/modules/physics/box2d/World.cpp | 80 ++-- src/modules/physics/box2d/World.h | 15 +- src/modules/physics/box2d/wrap_Body.cpp | 26 +- src/modules/physics/box2d/wrap_ChainShape.cpp | 15 +- .../physics/box2d/wrap_CircleShape.cpp | 8 +- src/modules/physics/box2d/wrap_Contact.cpp | 26 +- src/modules/physics/box2d/wrap_EdgeShape.cpp | 14 +- src/modules/physics/box2d/wrap_Fixture.cpp | 311 -------------- src/modules/physics/box2d/wrap_Fixture.h | 43 -- src/modules/physics/box2d/wrap_Physics.cpp | 127 +++--- .../physics/box2d/wrap_PolygonShape.cpp | 8 +- src/modules/physics/box2d/wrap_Shape.cpp | 293 ++++++++++++- src/modules/physics/box2d/wrap_Shape.h | 1 + src/modules/physics/box2d/wrap_World.cpp | 16 +- 35 files changed, 1137 insertions(+), 1236 deletions(-) delete mode 100644 src/modules/physics/box2d/Fixture.cpp delete mode 100644 src/modules/physics/box2d/Fixture.h delete mode 100644 src/modules/physics/box2d/wrap_Fixture.cpp delete mode 100644 src/modules/physics/box2d/wrap_Fixture.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 644f71410..550d20fef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -837,8 +837,6 @@ set(LOVE_SRC_MODULE_PHYSICS_BOX2D src/modules/physics/box2d/DistanceJoint.h src/modules/physics/box2d/EdgeShape.cpp src/modules/physics/box2d/EdgeShape.h - src/modules/physics/box2d/Fixture.cpp - src/modules/physics/box2d/Fixture.h src/modules/physics/box2d/FrictionJoint.cpp src/modules/physics/box2d/FrictionJoint.h src/modules/physics/box2d/GearJoint.cpp @@ -881,8 +879,6 @@ set(LOVE_SRC_MODULE_PHYSICS_BOX2D src/modules/physics/box2d/wrap_DistanceJoint.h src/modules/physics/box2d/wrap_EdgeShape.cpp src/modules/physics/box2d/wrap_EdgeShape.h - src/modules/physics/box2d/wrap_Fixture.cpp - src/modules/physics/box2d/wrap_Fixture.h src/modules/physics/box2d/wrap_FrictionJoint.cpp src/modules/physics/box2d/wrap_FrictionJoint.h src/modules/physics/box2d/wrap_GearJoint.cpp diff --git a/src/common/deprecation.cpp b/src/common/deprecation.cpp index f0b0cae72..84f1b264f 100644 --- a/src/common/deprecation.cpp +++ b/src/common/deprecation.cpp @@ -107,8 +107,12 @@ std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere) if (info.apiType == API_FUNCTION) notice << "function "; + else if (info.apiType == API_FUNCTION_VARIANT) + notice << "function variant in "; else if (info.apiType == API_METHOD) notice << "method "; + else if (info.apiType == API_METHOD_VARIANT) + notice << "method variant in "; else if (info.apiType == API_CALLBACK) notice << "callback "; else if (info.apiType == API_FIELD) @@ -188,7 +192,9 @@ MarkDeprecated::~MarkDeprecated() STRINGMAP_BEGIN(APIType, API_MAX_ENUM, apiType) { { "function", API_FUNCTION }, + { "functionvariant", API_FUNCTION_VARIANT }, { "method", API_METHOD }, + { "methodvariant", API_METHOD_VARIANT }, { "callback", API_CALLBACK }, { "field", API_FIELD }, { "constant", API_CONSTANT }, diff --git a/src/common/deprecation.h b/src/common/deprecation.h index 7ac407cb3..55b0e89e2 100644 --- a/src/common/deprecation.h +++ b/src/common/deprecation.h @@ -32,7 +32,9 @@ namespace love enum APIType { API_FUNCTION, + API_FUNCTION_VARIANT, API_METHOD, + API_METHOD_VARIANT, API_CALLBACK, API_FIELD, API_CONSTANT, diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index 2c8acfd64..a3e7ee110 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -23,12 +23,12 @@ #include "common/math.h" #include "Shape.h" -#include "Fixture.h" #include "World.h" #include "Physics.h" // Needed for luax_pushjoint. #include "wrap_Joint.h" +#include "wrap_Shape.h" namespace love { @@ -461,20 +461,20 @@ World *Body::getWorld() const return world; } -Fixture *Body::getFixture() const +Shape *Body::getShape() const { b2Fixture *f = body->GetFixtureList(); if (f == nullptr) return nullptr; - Fixture *fixture = (Fixture *)(f->GetUserData().pointer); - if (!fixture) - throw love::Exception("A fixture has escaped Memoizer!"); + Shape *shape = (Shape *)(f->GetUserData().pointer); + if (!shape) + throw love::Exception("A Shape has escaped Memoizer!"); - return fixture; + return shape; } -int Body::getFixtures(lua_State *L) const +int Body::getShapes(lua_State *L) const { lua_newtable(L); b2Fixture *f = body->GetFixtureList(); @@ -483,10 +483,10 @@ int Body::getFixtures(lua_State *L) const { if (!f) break; - Fixture *fixture = (Fixture *)(f->GetUserData().pointer); - if (!fixture) - throw love::Exception("A fixture has escaped Memoizer!"); - luax_pushtype(L, fixture); + Shape *shape = (Shape *)(f->GetUserData().pointer); + if (!shape) + throw love::Exception("A Shape has escaped Memoizer!"); + luax_pushshape(L, shape); lua_rawseti(L, -2, i); i++; } diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index 0be88c6c7..1d0b2d770 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -39,7 +39,6 @@ namespace box2d // Forward declarations. class World; class Shape; -class Fixture; /** * A Body is an entity which has position and orientation @@ -57,7 +56,6 @@ public: friend class CircleShape; friend class PolygonShape; friend class Shape; - friend class Fixture; // Public because joints et al ask for b2body b2Body *body; @@ -391,15 +389,14 @@ public: World *getWorld() const; /** - * Gets the first Fixture attached to this Body. + * Gets the first Shape attached to this Body. **/ - Fixture *getFixture() const; + Shape *getShape() const; /** - * Get an array of all the Fixtures attached to this Body. - * @return An array of Fixtures. + * Get an array of all the Shapes attached to this Body. **/ - int getFixtures(lua_State *L) const; + int getShapes(lua_State *L) const; /** * Get an array of all Joints attached to this Body. diff --git a/src/modules/physics/box2d/ChainShape.cpp b/src/modules/physics/box2d/ChainShape.cpp index 9bfef155c..7a2390ab0 100644 --- a/src/modules/physics/box2d/ChainShape.cpp +++ b/src/modules/physics/box2d/ChainShape.cpp @@ -34,8 +34,8 @@ namespace box2d love::Type ChainShape::type("ChainShape", &Shape::type); -ChainShape::ChainShape(b2ChainShape *c, bool own) - : Shape(c, own) +ChainShape::ChainShape(Body *body, const b2ChainShape &c) + : Shape(body, c) { } @@ -45,6 +45,7 @@ ChainShape::~ChainShape() void ChainShape::setNextVertex(float x, float y) { + throwIfShapeNotValid(); b2Vec2 v(x, y); b2ChainShape *c = (b2ChainShape *)shape; c->m_nextVertex = Physics::scaleDown(v); @@ -52,6 +53,7 @@ void ChainShape::setNextVertex(float x, float y) void ChainShape::setPreviousVertex(float x, float y) { + throwIfShapeNotValid(); b2Vec2 v(x, y); b2ChainShape *c = (b2ChainShape *)shape; c->m_prevVertex = Physics::scaleDown(v); @@ -59,44 +61,40 @@ void ChainShape::setPreviousVertex(float x, float y) b2Vec2 ChainShape::getNextVertex() const { + throwIfShapeNotValid(); b2ChainShape *c = (b2ChainShape *)shape; - return Physics::scaleUp(c->m_nextVertex); } b2Vec2 ChainShape::getPreviousVertex() const { + throwIfShapeNotValid(); b2ChainShape *c = (b2ChainShape *)shape; - return Physics::scaleUp(c->m_prevVertex); } EdgeShape *ChainShape::getChildEdge(int index) const { + throwIfShapeNotValid(); + b2ChainShape *c = (b2ChainShape *)shape; - b2EdgeShape *e = new b2EdgeShape; - try - { - c->GetChildEdge(e, index); - } - catch (love::Exception &) - { - delete e; - throw; - } + b2EdgeShape e; + c->GetChildEdge(&e, index); - return new EdgeShape(e, true); + return new EdgeShape(nullptr, e); } int ChainShape::getVertexCount() const { + throwIfShapeNotValid(); b2ChainShape *c = (b2ChainShape *)shape; return c->m_count; } b2Vec2 ChainShape::getPoint(int index) const { + throwIfShapeNotValid(); b2ChainShape *c = (b2ChainShape *)shape; if (index < 0 || index >= c->m_count) throw love::Exception("Physics error: index out of bounds"); @@ -106,6 +104,7 @@ b2Vec2 ChainShape::getPoint(int index) const const b2Vec2 *ChainShape::getPoints() const { + throwIfShapeNotValid(); b2ChainShape *c = (b2ChainShape *)shape; return c->m_vertices; } diff --git a/src/modules/physics/box2d/ChainShape.h b/src/modules/physics/box2d/ChainShape.h index 07f89f440..2b2ee14e1 100644 --- a/src/modules/physics/box2d/ChainShape.h +++ b/src/modules/physics/box2d/ChainShape.h @@ -45,7 +45,7 @@ public: * Create a new ChainShape from a Box2D chain shape. * @param c The chain shape. **/ - ChainShape(b2ChainShape *c, bool own = true); + ChainShape(Body *body, const b2ChainShape &c); virtual ~ChainShape(); diff --git a/src/modules/physics/box2d/CircleShape.cpp b/src/modules/physics/box2d/CircleShape.cpp index 545620f81..628b96bb0 100644 --- a/src/modules/physics/box2d/CircleShape.cpp +++ b/src/modules/physics/box2d/CircleShape.cpp @@ -34,8 +34,8 @@ namespace box2d love::Type CircleShape::type("CircleShape", &Shape::type); -CircleShape::CircleShape(b2CircleShape *c, bool own) - : Shape(c, own) +CircleShape::CircleShape(Body *body, const b2CircleShape &c) + : Shape(body, c) { } @@ -45,16 +45,19 @@ CircleShape::~CircleShape() float CircleShape::getRadius() const { + throwIfShapeNotValid(); return Physics::scaleUp(shape->m_radius); } void CircleShape::setRadius(float r) { + throwIfShapeNotValid(); shape->m_radius = Physics::scaleDown(r); } void CircleShape::getPoint(float &x_o, float &y_o) const { + throwIfShapeNotValid(); b2CircleShape *c = (b2CircleShape *) shape; x_o = Physics::scaleUp(c->m_p.x); y_o = Physics::scaleUp(c->m_p.y); @@ -62,6 +65,7 @@ void CircleShape::getPoint(float &x_o, float &y_o) const void CircleShape::setPoint(float x, float y) { + throwIfShapeNotValid(); b2CircleShape *c = (b2CircleShape *) shape; c->m_p = Physics::scaleDown(b2Vec2(x, y)); } diff --git a/src/modules/physics/box2d/CircleShape.h b/src/modules/physics/box2d/CircleShape.h index 438034bb8..20e5e3bac 100644 --- a/src/modules/physics/box2d/CircleShape.h +++ b/src/modules/physics/box2d/CircleShape.h @@ -50,7 +50,7 @@ public: * Create a new CircleShape from the a Box2D CircleShape definition. * @param c The CircleShape definition. **/ - CircleShape(b2CircleShape *c, bool own = true); + CircleShape(Body *body, const b2CircleShape &c); virtual ~CircleShape(); diff --git a/src/modules/physics/box2d/Contact.cpp b/src/modules/physics/box2d/Contact.cpp index 46e2b2a89..63b51ef04 100644 --- a/src/modules/physics/box2d/Contact.cpp +++ b/src/modules/physics/box2d/Contact.cpp @@ -35,7 +35,6 @@ Contact::Contact(World *world, b2Contact *contact) : contact(contact) , world(world) { - //contact->user world->registerObject(contact, this); } @@ -46,16 +45,16 @@ Contact::~Contact() void Contact::invalidate() { - if (contact != NULL) + if (contact != nullptr) { world->unregisterObject(contact); - contact = NULL; + contact = nullptr; } } bool Contact::isValid() { - return contact != NULL; + return contact != nullptr; } int Contact::getPositions(lua_State *L) @@ -144,13 +143,13 @@ void Contact::getChildren(int &childA, int &childB) childB = contact->GetChildIndexB(); } -void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB) +void Contact::getShapes(Shape *&shapeA, Shape *&shapeB) { - fixtureA = (Fixture *) (contact->GetFixtureA()->GetUserData().pointer); - fixtureB = (Fixture *) (contact->GetFixtureB()->GetUserData().pointer); + shapeA = (Shape *) (contact->GetFixtureA()->GetUserData().pointer); + shapeB = (Shape *) (contact->GetFixtureB()->GetUserData().pointer); - if (!fixtureA || !fixtureB) - throw love::Exception("A fixture has escaped Memoizer!"); + if (!shapeA || !shapeB) + throw love::Exception("A Shape has escaped Memoizer!"); } } // box2d diff --git a/src/modules/physics/box2d/Contact.h b/src/modules/physics/box2d/Contact.h index afbe587d6..1287ca285 100644 --- a/src/modules/physics/box2d/Contact.h +++ b/src/modules/physics/box2d/Contact.h @@ -151,9 +151,9 @@ public: void getChildren(int &childA, int &childB); /** - * Gets the Fixtures associated with this Contact. + * Gets the Shapes associated with this Contact. **/ - void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB); + void getShapes(Shape *&shapeA, Shape *&shapeB); private: diff --git a/src/modules/physics/box2d/EdgeShape.cpp b/src/modules/physics/box2d/EdgeShape.cpp index e4f3c146f..f49925783 100644 --- a/src/modules/physics/box2d/EdgeShape.cpp +++ b/src/modules/physics/box2d/EdgeShape.cpp @@ -34,8 +34,8 @@ namespace box2d love::Type EdgeShape::type("EdgeShape", &Shape::type); -EdgeShape::EdgeShape(b2EdgeShape *e, bool own) - : Shape(e, own) +EdgeShape::EdgeShape(Body *body, const b2EdgeShape &e) + : Shape(body, e) { } @@ -45,6 +45,7 @@ EdgeShape::~EdgeShape() void EdgeShape::setNextVertex(float x, float y) { + throwIfShapeNotValid(); b2EdgeShape *e = (b2EdgeShape *)shape; b2Vec2 v(x, y); e->m_vertex3 = Physics::scaleDown(v); @@ -52,13 +53,14 @@ void EdgeShape::setNextVertex(float x, float y) b2Vec2 EdgeShape::getNextVertex() const { + throwIfShapeNotValid(); b2EdgeShape *e = (b2EdgeShape *)shape; - return Physics::scaleUp(e->m_vertex3); } void EdgeShape::setPreviousVertex(float x, float y) { + throwIfShapeNotValid(); b2EdgeShape *e = (b2EdgeShape *)shape; b2Vec2 v(x, y); e->m_vertex0 = Physics::scaleDown(v); @@ -66,13 +68,14 @@ void EdgeShape::setPreviousVertex(float x, float y) b2Vec2 EdgeShape::getPreviousVertex() const { + throwIfShapeNotValid(); b2EdgeShape *e = (b2EdgeShape *)shape; - return Physics::scaleUp(e->m_vertex0); } int EdgeShape::getPoints(lua_State *L) { + throwIfShapeNotValid(); b2EdgeShape *e = (b2EdgeShape *)shape; b2Vec2 v1 = Physics::scaleUp(e->m_vertex1); b2Vec2 v2 = Physics::scaleUp(e->m_vertex2); diff --git a/src/modules/physics/box2d/EdgeShape.h b/src/modules/physics/box2d/EdgeShape.h index 4db2383ce..9445e5b62 100644 --- a/src/modules/physics/box2d/EdgeShape.h +++ b/src/modules/physics/box2d/EdgeShape.h @@ -45,7 +45,7 @@ public: * Create a new EdgeShape from a Box2D edge shape. * @param e The edge shape. **/ - EdgeShape(b2EdgeShape *e, bool own = true); + EdgeShape(Body *body, const b2EdgeShape &e); virtual ~EdgeShape(); diff --git a/src/modules/physics/box2d/Fixture.cpp b/src/modules/physics/box2d/Fixture.cpp deleted file mode 100644 index 12fc9b2d7..000000000 --- a/src/modules/physics/box2d/Fixture.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/** - * Copyright (c) 2006-2023 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 "Fixture.h" - -// Module -#include "Body.h" -#include "World.h" -#include "Physics.h" - -// STD -#include - -namespace love -{ -namespace physics -{ -namespace box2d -{ - -love::Type Fixture::type("Fixture", &Object::type); - -Fixture::Fixture(Body *body, Shape *shape, float density) - : body(body) - , fixture(nullptr) -{ - b2FixtureDef def; - def.shape = shape->shape; - def.userData.pointer = (uintptr_t)this; - def.density = density; - fixture = body->body->CreateFixture(&def); - this->retain(); -} - -Fixture::~Fixture() -{ - if (ref) - delete ref; -} - -void Fixture::checkCreateShape() -{ - if (shape.get() != nullptr || fixture == nullptr || fixture->GetShape() == nullptr) - return; - - b2Shape *bshape = fixture->GetShape(); - - switch (bshape->GetType()) - { - case b2Shape::e_circle: - shape.set(new CircleShape((b2CircleShape *) bshape, false), Acquire::NORETAIN); - break; - case b2Shape::e_edge: - shape.set(new EdgeShape((b2EdgeShape *) bshape, false), Acquire::NORETAIN); - break; - case b2Shape::e_polygon: - shape.set(new PolygonShape((b2PolygonShape *) bshape, false), Acquire::NORETAIN); - break; - case b2Shape::e_chain: - shape.set(new ChainShape((b2ChainShape *) bshape, false), Acquire::NORETAIN); - break; - default: - break; - } -} - -Shape::Type Fixture::getType() -{ - checkCreateShape(); - if (shape.get() == nullptr) - return Shape::SHAPE_INVALID; - else - return shape->getType(); -} - -void Fixture::setFriction(float friction) -{ - fixture->SetFriction(friction); -} - -void Fixture::setRestitution(float restitution) -{ - fixture->SetRestitution(restitution); -} - -void Fixture::setDensity(float density) -{ - fixture->SetDensity(density); -} - -void Fixture::setSensor(bool sensor) -{ - fixture->SetSensor(sensor); -} - -float Fixture::getFriction() const -{ - return fixture->GetFriction(); -} - -float Fixture::getRestitution() const -{ - return fixture->GetRestitution(); -} - -float Fixture::getDensity() const -{ - return fixture->GetDensity(); -} - -bool Fixture::isSensor() const -{ - return fixture->IsSensor(); -} - -Body *Fixture::getBody() const -{ - return body; -} - -Shape *Fixture::getShape() -{ - checkCreateShape(); - return shape; -} - -bool Fixture::isValid() const -{ - return fixture != nullptr; -} - -void Fixture::setFilterData(int *v) -{ - b2Filter f; - f.categoryBits = (uint16) v[0]; - f.maskBits = (uint16) v[1]; - f.groupIndex = (int16) v[2]; - fixture->SetFilterData(f); -} - -void Fixture::getFilterData(int *v) -{ - b2Filter f = fixture->GetFilterData(); - v[0] = (int) f.categoryBits; - v[1] = (int) f.maskBits; - v[2] = (int) f.groupIndex; -} - -int Fixture::setCategory(lua_State *L) -{ - b2Filter f = fixture->GetFilterData(); - f.categoryBits = (uint16)getBits(L); - fixture->SetFilterData(f); - return 0; -} - -int Fixture::setMask(lua_State *L) -{ - b2Filter f = fixture->GetFilterData(); - f.maskBits = ~(uint16)getBits(L); - fixture->SetFilterData(f); - return 0; -} - -void Fixture::setGroupIndex(int index) -{ - b2Filter f = fixture->GetFilterData(); - f.groupIndex = (uint16)index; - fixture->SetFilterData(f); -} - -int Fixture::getGroupIndex() const -{ - b2Filter f = fixture->GetFilterData(); - return f.groupIndex; -} - -int Fixture::getCategory(lua_State *L) -{ - return pushBits(L, fixture->GetFilterData().categoryBits); -} - -int Fixture::getMask(lua_State *L) -{ - return pushBits(L, ~(fixture->GetFilterData().maskBits)); -} - -uint16 Fixture::getBits(lua_State *L) -{ - // Get number of args. - bool istable = lua_istable(L, 1); - int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L); - - // The new bitset. - std::bitset<16> b; - - for (int i = 1; i <= argc; i++) - { - size_t bpos = 0; - - if (istable) - { - lua_rawgeti(L, 1, i); - bpos = (size_t) (lua_tointeger(L, -1) - 1); - lua_pop(L, 1); - } - else - bpos = (size_t) (lua_tointeger(L, i) - 1); - - if (bpos >= 16) - luaL_error(L, "Values must be in range 1-16."); - - b.set(bpos, true); - } - - return (uint16)b.to_ulong(); -} - -int Fixture::pushBits(lua_State *L, uint16 bits) -{ - // Create a bitset. - std::bitset<16> b((int)bits); - - // Push all set bits. - for (int i = 0; i<16; i++) - if (b.test(i)) - lua_pushinteger(L, i+1); - - // Count number of set bits. - return (int)b.count(); -} - -int Fixture::setUserData(lua_State *L) -{ - love::luax_assert_argc(L, 1, 1); - - if(!ref) - ref = new Reference(); - - ref->ref(L); - - return 0; -} - -int Fixture::getUserData(lua_State *L) -{ - if (ref != nullptr) - ref->push(L); - else - lua_pushnil(L); - - return 1; -} - -bool Fixture::testPoint(float x, float y) const -{ - return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y))); -} - -int Fixture::rayCast(lua_State *L) const -{ - float p1x = Physics::scaleDown((float)luaL_checknumber(L, 1)); - float p1y = Physics::scaleDown((float)luaL_checknumber(L, 2)); - float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3)); - float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4)); - float maxFraction = (float)luaL_checknumber(L, 5); - int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index - b2RayCastInput input; - input.p1.Set(p1x, p1y); - input.p2.Set(p2x, p2y); - input.maxFraction = maxFraction; - b2RayCastOutput output; - if (!fixture->RayCast(&output, input, childIndex)) - return 0; // Nothing hit. - lua_pushnumber(L, output.normal.x); - lua_pushnumber(L, output.normal.y); - lua_pushnumber(L, output.fraction); - return 3; -} - -int Fixture::getBoundingBox(lua_State *L) const -{ - int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index - b2AABB box; - luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); }); - box = Physics::scaleUp(box); - lua_pushnumber(L, box.lowerBound.x); - lua_pushnumber(L, box.lowerBound.y); - lua_pushnumber(L, box.upperBound.x); - lua_pushnumber(L, box.upperBound.y); - return 4; -} - -int Fixture::getMassData(lua_State *L) const -{ - b2MassData data; - fixture->GetMassData(&data); - b2Vec2 center = Physics::scaleUp(data.center); - lua_pushnumber(L, center.x); - lua_pushnumber(L, center.y); - lua_pushnumber(L, data.mass); - lua_pushnumber(L, data.I); - return 4; -} - -void Fixture::destroy(bool implicit) -{ - if (body->world->world->IsLocked()) - { - // Called during time step. Save reference for destruction afterwards. - this->retain(); - body->world->destructFixtures.push_back(this); - return; - } - - shape.set(nullptr); - - if (!implicit && fixture != nullptr) - body->body->DestroyFixture(fixture); - fixture = nullptr; - - // Remove userdata reference to avoid it sticking around after GC - if (ref) - ref->unref(); - - // Box2D fixture destroyed. Release its reference to the love Fixture. - this->release(); -} - -} // box2d -} // physics -} // love diff --git a/src/modules/physics/box2d/Fixture.h b/src/modules/physics/box2d/Fixture.h deleted file mode 100644 index 4f0d54e99..000000000 --- a/src/modules/physics/box2d/Fixture.h +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright (c) 2006-2023 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_PHYSICS_BOX2D_FIXTURE_H -#define LOVE_PHYSICS_BOX2D_FIXTURE_H - -// LOVE -#include "physics/Shape.h" -#include "physics/box2d/Body.h" -#include "physics/box2d/Shape.h" -#include "common/Object.h" -#include "common/Reference.h" - -// Box2D -#include - -namespace love -{ -namespace physics -{ -namespace box2d -{ - -class World; - -/** - * A Fixture is used to attach a shape to a body for collision detection. - * A Fixture inherits its transform from its parent. Fixtures hold - * additional non-geometric data such as friction, collision filters, - * etc. - **/ -class Fixture : public Object -{ -public: - friend class Physics; - - static love::Type type; - - /** - * Creates a Fixture. - **/ - Fixture(Body *body, Shape *shape, float density); - - virtual ~Fixture(); - - /** - * Gets the type of the Fixture's Shape. Useful for - * debug drawing. - **/ - Shape::Type getType(); - - /** - * Gets the Shape attached to this Fixture. - **/ - Shape *getShape(); - - /** - * Returns true if the fixture is active in a Box2D world. - **/ - bool isValid() const; - - /** - * Checks whether this Fixture acts as a sensor. - * @return True if sensor, false otherwise. - **/ - bool isSensor() const; - - /** - * Set whether this Fixture should be a sensor or not. - * @param sensor True if sensor, false if not. - **/ - void setSensor(bool sensor); - - /** - * Gets the Body this Fixture is attached to. - **/ - Body *getBody() const; - - /** - * Sets the filter data. An integer array is used even though the - * first two elements are unsigned shorts. The elements are: - * category (16-bits), mask (16-bits) and group (32-bits/int). - **/ - void setFilterData(int *v); - - /** - * Gets the filter data. An integer array is used even though the - * first two elements are unsigned shorts. The elements are: - * category (16-bits), mask (16-bits) and group (32-bits/int). - **/ - void getFilterData(int *v); - - /** - * This function stores an in-C reference to - * arbitrary Lua data in the Box2D Fixture object. - **/ - int setUserData(lua_State *L); - - /** - * Gets the data set with setData. If no - * data is set, nil is returned. - **/ - int getUserData(lua_State *L); - - /** - * Sets the friction of the Fixture. - * @param friction The new friction. - **/ - void setFriction(float friction); - - /** - * Sets the restitution for the Fixture. - * @param restitution The restitution. - **/ - void setRestitution(float restitution); - - /** - * Sets the density of the Fixture. - * @param density The density of the Fixture. - **/ - void setDensity(float density); - - /** - * Gets the friction of the Fixture. - * @returns The friction. - **/ - float getFriction() const; - - /** - * Gets the restitution of the Fixture. - * @return The restitution of the Fixture. - **/ - float getRestitution() const; - - /** - * Gets the density of the Fixture. - * @return The density. - **/ - float getDensity() const; - - /** - * Checks if a point is inside the Fixture. - * @param x The x-component of the point. - * @param y The y-component of the point. - **/ - bool testPoint(float x, float y) const; - - /** - * Cast a ray against this Fixture. - **/ - int rayCast(lua_State *L) const; - - void setGroupIndex(int index); - int getGroupIndex() const; - - int setCategory(lua_State *L); - int setMask(lua_State *L); - int getCategory(lua_State *L); - int getMask(lua_State *L); - uint16 getBits(lua_State *L); - int pushBits(lua_State *L, uint16 bits); - - /** - * Gets the bounding box for this Fixture. - * The function returns eight values which can be - * passed directly to love.graphics.polygon. - **/ - int getBoundingBox(lua_State *L) const; - - /** - * Gets the mass data for this Fixture. - * This operation may be expensive. - **/ - int getMassData(lua_State *L) const; - - /** - * Destroys this fixture. - **/ - void destroy(bool implicit = false); - -protected: - - void checkCreateShape(); - - Body *body; - b2Fixture *fixture; - - // Reference to arbitrary data. - Reference* ref = nullptr; - - StrongRef shape; - -}; - -} // box2d -} // physics -} // love - -#endif // LOVE_PHYSICS_BOX2D_FIXTURE_H diff --git a/src/modules/physics/box2d/Physics.cpp b/src/modules/physics/box2d/Physics.cpp index 5c3a134f9..6fb860b18 100644 --- a/src/modules/physics/box2d/Physics.cpp +++ b/src/modules/physics/box2d/Physics.cpp @@ -35,6 +35,7 @@ namespace box2d float Physics::meter = Physics::DEFAULT_METER; Physics::Physics() + : blockAllocator() { meter = DEFAULT_METER; } @@ -66,8 +67,7 @@ Body *Physics::newBody(World *world, Body::Type type) Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, float radius) { StrongRef body(newBody(world, x, y, type), Acquire::NORETAIN); - StrongRef shape(newCircleShape(0, 0, radius), Acquire::NORETAIN); - StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + StrongRef shape(newCircleShape(body, 0, 0, radius), Acquire::NORETAIN); body->retain(); return body.get(); } @@ -75,8 +75,7 @@ Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, fl Body *Physics::newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle) { StrongRef body(newBody(world, x, y, type), Acquire::NORETAIN); - StrongRef shape(newRectangleShape(0, 0, w, h, angle), Acquire::NORETAIN); - StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + StrongRef shape(newRectangleShape(body, 0, 0, w, h, angle), Acquire::NORETAIN); body->retain(); return body.get(); } @@ -93,8 +92,7 @@ Body *Physics::newPolygonBody(World *world, Body::Type type, const Vector2 *coor localcoords.push_back(coords[i] - origin); StrongRef body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN); - StrongRef shape(newPolygonShape(localcoords.data(), count), Acquire::NORETAIN); - StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + StrongRef shape(newPolygonShape(body, localcoords.data(), count), Acquire::NORETAIN); body->retain(); return body.get(); } @@ -104,8 +102,7 @@ Body *Physics::newEdgeBody(World *world, Body::Type type, float x1, float y1, fl float wx = (x2 - x1) / 2.0f; float wy = (y2 - y1) / 2.0f; StrongRef body(newBody(world, wx, wy, type), Acquire::NORETAIN); - StrongRef shape(newEdgeShape(x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN); - StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + StrongRef shape(newEdgeShape(body, x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN); body->retain(); return body.get(); } @@ -122,44 +119,75 @@ Body *Physics::newChainBody(World *world, Body::Type type, bool loop, const Vect localcoords.push_back(coords[i] - origin); StrongRef body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN); - StrongRef shape(newChainShape(loop, localcoords.data(), count), Acquire::NORETAIN); - StrongRef fixture(newFixture(body, shape, 1.0f), Acquire::NORETAIN); + StrongRef shape(newChainShape(body, loop, localcoords.data(), count), Acquire::NORETAIN); body->retain(); return body.get(); } -CircleShape *Physics::newCircleShape(float x, float y, float radius) +Shape *Physics::newAttachedShape(Body *body, Shape *prototype, float density) { - b2CircleShape *s = new b2CircleShape(); - s->m_p = Physics::scaleDown(b2Vec2(x, y)); - s->m_radius = Physics::scaleDown(radius); - return new CircleShape(s); + if (prototype->isValid()) + throw love::Exception("The given Shape must not be part of the World."); + + Shape *shape = nullptr; + + switch (prototype->getType()) + { + case Shape::SHAPE_CIRCLE: + shape = new CircleShape(body, *(b2CircleShape *) prototype->shape); + break; + case Shape::SHAPE_POLYGON: + shape = new PolygonShape(body, *(b2PolygonShape *) prototype->shape); + break; + case Shape::SHAPE_EDGE: + shape = new EdgeShape(body, *(b2EdgeShape *) prototype->shape); + break; + case Shape::SHAPE_CHAIN: + shape = new ChainShape(body, *(b2ChainShape *) prototype->shape); + break; + default: + throw love::Exception("Unknown shape type."); + break; + } + + shape->setDensity(density); + body->resetMassData(); + + return shape; } -PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h, float angle) +CircleShape *Physics::newCircleShape(Body *body, float x, float y, float radius) { - b2PolygonShape *s = new b2PolygonShape(); - s->SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle); - return new PolygonShape(s); + b2CircleShape s; + s.m_p = Physics::scaleDown(b2Vec2(x, y)); + s.m_radius = Physics::scaleDown(radius); + return new CircleShape(body, s); } -EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided) +PolygonShape *Physics::newRectangleShape(Body *body, float x, float y, float w, float h, float angle) { - b2EdgeShape *s = new b2EdgeShape(); + b2PolygonShape s; + s.SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle); + return new PolygonShape(body, s); +} + +EdgeShape *Physics::newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided) +{ + b2EdgeShape s; if (oneSided) { b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1)); b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2)); - s->SetOneSided(v1, v1, v2, v2); + s.SetOneSided(v1, v1, v2, v2); } else { - s->SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2))); + s.SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2))); } - return new EdgeShape(s); + return new EdgeShape(body, s); } -PolygonShape *Physics::newPolygonShape(const Vector2 *coords, int count) +PolygonShape *Physics::newPolygonShape(Body *body, const Vector2 *coords, int count) { // 3 to 8 (b2_maxPolygonVertices) vertices if (count < 3) @@ -172,44 +200,28 @@ PolygonShape *Physics::newPolygonShape(const Vector2 *coords, int count) for (int i = 0; i < count; i++) vecs[i] = Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y)); - b2PolygonShape *s = new b2PolygonShape(); + b2PolygonShape s; - try - { - s->Set(vecs, count); - } - catch (love::Exception &) - { - delete s; - throw; - } + s.Set(vecs, count); - return new PolygonShape(s); + return new PolygonShape(body, s); } -ChainShape *Physics::newChainShape(bool loop, const Vector2 *coords, int count) +ChainShape *Physics::newChainShape(Body *body, bool loop, const Vector2 *coords, int count) { std::vector vecs; for (int i = 0; i < count; i++) vecs.push_back(Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y))); - b2ChainShape *s = new b2ChainShape(); + b2ChainShape s; - try - { - if (loop) - s->CreateLoop(vecs.data(), count); - else - s->CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]); - } - catch (love::Exception &) - { - delete s; - throw; - } + if (loop) + s.CreateLoop(vecs.data(), count); + else + s.CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]); - return new ChainShape(s); + return new ChainShape(body, s); } DistanceJoint *Physics::newDistanceJoint(Body *body1, Body *body2, float x1, float y1, float x2, float y2, bool collideConnected) @@ -287,16 +299,10 @@ MotorJoint *Physics::newMotorJoint(Body *body1, Body *body2, float correctionFac return new MotorJoint(body1, body2, correctionFactor, collideConnected); } - -Fixture *Physics::newFixture(Body *body, Shape *shape, float density) -{ - return new Fixture(body, shape, density); -} - int Physics::getDistance(lua_State *L) { - Fixture *fixtureA = luax_checktype(L, 1); - Fixture *fixtureB = luax_checktype(L, 2); + Shape *shapeA = luax_checktype(L, 1); + Shape *shapeB = luax_checktype(L, 2); b2DistanceProxy pA, pB; b2DistanceInput i; b2DistanceOutput o; @@ -304,12 +310,15 @@ int Physics::getDistance(lua_State *L) c.count = 0; luax_catchexcept(L, [&]() { - pA.Set(fixtureA->fixture->GetShape(), 0); - pB.Set(fixtureB->fixture->GetShape(), 0); + if (!shapeA->isValid() || !shapeB->isValid()) + throw love::Exception("The given Shape is not active in the physics World."); + + pA.Set(shapeA->fixture->GetShape(), 0); + pB.Set(shapeB->fixture->GetShape(), 0); i.proxyA = pA; i.proxyB = pB; - i.transformA = fixtureA->fixture->GetBody()->GetTransform(); - i.transformB = fixtureB->fixture->GetBody()->GetTransform(); + i.transformA = shapeA->fixture->GetBody()->GetTransform(); + i.transformB = shapeB->fixture->GetBody()->GetTransform(); i.useRadii = true; b2Distance(&o, &c, &i); }); diff --git a/src/modules/physics/box2d/Physics.h b/src/modules/physics/box2d/Physics.h index 9c81ffe41..c198a7b78 100644 --- a/src/modules/physics/box2d/Physics.h +++ b/src/modules/physics/box2d/Physics.h @@ -28,7 +28,6 @@ #include "World.h" #include "Contact.h" #include "Body.h" -#include "Fixture.h" #include "Shape.h" #include "CircleShape.h" #include "PolygonShape.h" @@ -95,9 +94,9 @@ public: Body *newBody(World *world, Body::Type type); /** - * Convenience functions for creating a Body, Shape, and Fixture all in one - * call. The body's world position is the center/average of the given - * coordinates, and the shape is centered at the local origin. + * Convenience functions for creating a Body and Shape all in one call. The + * body's world position is the center/average of the given coordinates, + * and the shape is centered at the local origin. **/ Body *newCircleBody(World *world, Body::Type type, float x, float y, float radius); Body *newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle); @@ -105,13 +104,16 @@ public: Body *newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided); Body *newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count); + // Necessary to support the deprecated newFixture API. + Shape *newAttachedShape(Body *body, Shape *prototype, float density); + /** * Creates a new CircleShape at (x,y) in local coordinates. * @param x The offset along the x-axis. * @param y The offset along the y-axis. * @param radius The radius of the circle. **/ - CircleShape *newCircleShape(float x, float y, float radius); + CircleShape *newCircleShape(Body *body, float x, float y, float radius); /** * Shorthand for creating rectangular PolygonShapes. The rectangle @@ -122,7 +124,7 @@ public: * @param h The height of the rectangle. * @param angle The angle of the rectangle. (rad) **/ - PolygonShape *newRectangleShape(float x, float y, float w, float h, float angle); + PolygonShape *newRectangleShape(Body *body, float x, float y, float w, float h, float angle); /** * Creates a new EdgeShape. The edge will be created from @@ -132,18 +134,17 @@ public: * @param x2 The x coordinate of the second point. * @param y2 The y coordinate of the second point. **/ - EdgeShape *newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided); + EdgeShape *newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided); /** * Creates a new PolygonShape from a variable number of vertices. **/ - //int newPolygonShape(lua_State *L); - PolygonShape *newPolygonShape(const Vector2 *coords, int count); + PolygonShape *newPolygonShape(Body *body, const Vector2 *coords, int count); /** * Creates a new ChainShape from a variable number of vertices. **/ - ChainShape *newChainShape(bool loop, const Vector2 *coords, int count); + ChainShape *newChainShape(Body *body, bool loop, const Vector2 *coords, int count); /** * Creates a new DistanceJoint connecting body1 with body2. @@ -263,15 +264,6 @@ public: MotorJoint *newMotorJoint(Body *body1, Body *body2); MotorJoint *newMotorJoint(Body *body1, Body *body2, float correctionFactor, bool collideConnected); - /** - * Creates a new Fixture attaching shape to body. - * @param body The body to attach the Fixture to. - * @param shape The shape to attach to the Fixture, - * @param density The density of the Fixture. - **/ - - Fixture *newFixture(Body *body, Shape *shape, float density); - /** * Calculates the distance between two Fixtures. * @param fixtureA The first Fixture. @@ -393,10 +385,15 @@ public: **/ static void computeAngularFrequency(float &frequency, float &ratio, float stiffness, float damping, b2Body *bodyA, b2Body *bodyB); + b2BlockAllocator *getBlockAllocator() { return &blockAllocator; } + private: // The length of one meter in pixels. static float meter; + + b2BlockAllocator blockAllocator; + }; // Physics } // box2d diff --git a/src/modules/physics/box2d/PolygonShape.cpp b/src/modules/physics/box2d/PolygonShape.cpp index 4655c8cc4..12b314f02 100644 --- a/src/modules/physics/box2d/PolygonShape.cpp +++ b/src/modules/physics/box2d/PolygonShape.cpp @@ -34,8 +34,8 @@ namespace box2d love::Type PolygonShape::type("PolygonShape", &Shape::type); -PolygonShape::PolygonShape(b2PolygonShape *p, bool own) - : Shape(p, own) +PolygonShape::PolygonShape(Body *body, const b2PolygonShape &p) + : Shape(body, p) { } @@ -45,6 +45,7 @@ PolygonShape::~PolygonShape() int PolygonShape::getPoints(lua_State *L) { + throwIfShapeNotValid(); love::luax_assert_argc(L, 0); b2PolygonShape *p = (b2PolygonShape *)shape; int count = p->m_count; @@ -59,6 +60,7 @@ int PolygonShape::getPoints(lua_State *L) bool PolygonShape::validate() const { + throwIfShapeNotValid(); b2PolygonShape *p = (b2PolygonShape *)shape; return p->Validate(); } diff --git a/src/modules/physics/box2d/PolygonShape.h b/src/modules/physics/box2d/PolygonShape.h index 9a632ae6d..5d400553f 100644 --- a/src/modules/physics/box2d/PolygonShape.h +++ b/src/modules/physics/box2d/PolygonShape.h @@ -48,7 +48,7 @@ public: * Create a new PolygonShape from a Box2D polygon definition. * @param p The polygon definition. **/ - PolygonShape(b2PolygonShape *p, bool own = true); + PolygonShape(Body *body, const b2PolygonShape &p); virtual ~PolygonShape(); diff --git a/src/modules/physics/box2d/Shape.cpp b/src/modules/physics/box2d/Shape.cpp index e65807582..c47c4c7ff 100644 --- a/src/modules/physics/box2d/Shape.cpp +++ b/src/modules/physics/box2d/Shape.cpp @@ -35,54 +35,348 @@ namespace physics namespace box2d { -Shape::Shape() +Shape::Shape(Body *body, const b2Shape &shape) : shape(nullptr) , own(false) + , shapeType(SHAPE_INVALID) + , body(body) + , fixture(nullptr) { -} + if (body) + { + b2FixtureDef def; + def.shape = &shape; + def.userData.pointer = (uintptr_t)this; + def.density = 1.0f; + fixture = body->body->CreateFixture(&def); + this->shape = fixture->GetShape(); + retain(); // Shape::destroy does the release(). + } + else + { + // Path to support deprecated APIs. + auto physics = Module::getInstance(Module::M_PHYSICS); + this->shape = shape.Clone(physics->getBlockAllocator()); + own = true; + } -Shape::Shape(b2Shape *shape, bool own) - : shape(shape) - , own(own) -{ + switch (this->shape->GetType()) + { + case b2Shape::e_circle: + shapeType = SHAPE_CIRCLE; + break; + case b2Shape::e_polygon: + shapeType = SHAPE_POLYGON; + break; + case b2Shape::e_edge: + shapeType = SHAPE_EDGE; + break; + case b2Shape::e_chain: + shapeType = SHAPE_CHAIN; + break; + default: + shapeType = SHAPE_INVALID; + break; + } } Shape::~Shape() { if (shape && own) - delete shape; + { + auto physics = Module::getInstance(Module::M_PHYSICS); + auto allocator = physics->getBlockAllocator(); + + // Taken from b2Fixture::Destroy. Not very pretty... + switch (shapeType) + { + case SHAPE_CIRCLE: + { + b2CircleShape *s = (b2CircleShape*)shape; + s->~b2CircleShape(); + allocator->Free(s, sizeof(b2CircleShape)); + break; + } + case SHAPE_EDGE: + { + b2EdgeShape *s = (b2EdgeShape*)shape; + s->~b2EdgeShape(); + allocator->Free(s, sizeof(b2EdgeShape)); + break; + } + case SHAPE_POLYGON: + { + b2PolygonShape *s = (b2PolygonShape*)shape; + s->~b2PolygonShape(); + allocator->Free(s, sizeof(b2PolygonShape)); + break; + } + case SHAPE_CHAIN: + { + b2ChainShape *s = (b2ChainShape*)shape; + s->~b2ChainShape(); + allocator->Free(s, sizeof(b2ChainShape)); + break; + } + default: + break; + } + } + + if (ref) + delete ref; +} + +void Shape::destroy(bool implicit) +{ + if (fixture == nullptr) + return; + + if (body->world->world->IsLocked()) + { + // Called during time step. Save reference for destruction afterwards. + this->retain(); + body->world->destructShapes.push_back(this); + return; + } + + if (!implicit && fixture != nullptr) + body->body->DestroyFixture(fixture); + + fixture = nullptr; shape = nullptr; + body = nullptr; + + // Remove userdata reference to avoid it sticking around after GC + if (ref) + ref->unref(); + + // Box2D fixture destroyed. Release its reference to the love Shape. + release(); +} + +void Shape::throwIfFixtureNotValid() const +{ + if (fixture == nullptr) + throw love::Exception("Shape must be active in the physics World to use this method."); +} + +void Shape::throwIfShapeNotValid() const +{ + if (shape == nullptr) + throw love::Exception("Cannot call this method on a destroyed Shape."); } Shape::Type Shape::getType() const { - switch (shape->GetType()) - { - case b2Shape::e_circle: - return SHAPE_CIRCLE; - case b2Shape::e_polygon: - return SHAPE_POLYGON; - case b2Shape::e_edge: - return SHAPE_EDGE; - case b2Shape::e_chain: - return SHAPE_CHAIN; - default: - return SHAPE_INVALID; - } + return shapeType; +} + +void Shape::setFriction(float friction) +{ + throwIfFixtureNotValid(); + fixture->SetFriction(friction); +} + +void Shape::setRestitution(float restitution) +{ + throwIfFixtureNotValid(); + fixture->SetRestitution(restitution); +} + +void Shape::setDensity(float density) +{ + throwIfFixtureNotValid(); + fixture->SetDensity(density); +} + +void Shape::setSensor(bool sensor) +{ + throwIfFixtureNotValid(); + fixture->SetSensor(sensor); +} + +float Shape::getFriction() const +{ + throwIfFixtureNotValid(); + return fixture->GetFriction(); +} + +float Shape::getRestitution() const +{ + throwIfFixtureNotValid(); + return fixture->GetRestitution(); +} + +float Shape::getDensity() const +{ + throwIfFixtureNotValid(); + return fixture->GetDensity(); +} + +bool Shape::isSensor() const +{ + throwIfFixtureNotValid(); + return fixture->IsSensor(); +} + +Body *Shape::getBody() const +{ + return body; } float Shape::getRadius() const { + throwIfShapeNotValid(); return Physics::scaleUp(shape->m_radius); } int Shape::getChildCount() const { + throwIfShapeNotValid(); return shape->GetChildCount(); } +void Shape::setFilterData(int *v) +{ + throwIfFixtureNotValid(); + b2Filter f; + f.categoryBits = (uint16) v[0]; + f.maskBits = (uint16) v[1]; + f.groupIndex = (int16) v[2]; + fixture->SetFilterData(f); +} + +void Shape::getFilterData(int *v) +{ + throwIfFixtureNotValid(); + b2Filter f = fixture->GetFilterData(); + v[0] = (int) f.categoryBits; + v[1] = (int) f.maskBits; + v[2] = (int) f.groupIndex; +} + +int Shape::setCategory(lua_State *L) +{ + throwIfFixtureNotValid(); + b2Filter f = fixture->GetFilterData(); + f.categoryBits = (uint16)getBits(L); + fixture->SetFilterData(f); + return 0; +} + +int Shape::setMask(lua_State *L) +{ + throwIfFixtureNotValid(); + b2Filter f = fixture->GetFilterData(); + f.maskBits = ~(uint16)getBits(L); + fixture->SetFilterData(f); + return 0; +} + +void Shape::setGroupIndex(int index) +{ + throwIfFixtureNotValid(); + b2Filter f = fixture->GetFilterData(); + f.groupIndex = (uint16)index; + fixture->SetFilterData(f); +} + +int Shape::getGroupIndex() const +{ + throwIfFixtureNotValid(); + b2Filter f = fixture->GetFilterData(); + return f.groupIndex; +} + +int Shape::getCategory(lua_State *L) +{ + throwIfFixtureNotValid(); + return pushBits(L, fixture->GetFilterData().categoryBits); +} + +int Shape::getMask(lua_State *L) +{ + throwIfFixtureNotValid(); + return pushBits(L, ~(fixture->GetFilterData().maskBits)); +} + +uint16 Shape::getBits(lua_State *L) +{ + // Get number of args. + bool istable = lua_istable(L, 1); + int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L); + + // The new bitset. + std::bitset<16> b; + + for (int i = 1; i <= argc; i++) + { + size_t bpos = 0; + + if (istable) + { + lua_rawgeti(L, 1, i); + bpos = (size_t) (lua_tointeger(L, -1) - 1); + lua_pop(L, 1); + } + else + bpos = (size_t) (lua_tointeger(L, i) - 1); + + if (bpos >= 16) + luaL_error(L, "Values must be in range 1-16."); + + b.set(bpos, true); + } + + return (uint16)b.to_ulong(); +} + +int Shape::pushBits(lua_State *L, uint16 bits) +{ + // Create a bitset. + std::bitset<16> b((int)bits); + + // Push all set bits. + for (int i = 0; i<16; i++) + if (b.test(i)) + lua_pushinteger(L, i+1); + + // Count number of set bits. + return (int)b.count(); +} + +int Shape::setUserData(lua_State *L) +{ + love::luax_assert_argc(L, 1, 1); + + if(!ref) + ref = new Reference(); + + ref->ref(L); + + return 0; +} + +int Shape::getUserData(lua_State *L) +{ + if (ref != nullptr) + ref->push(L); + else + lua_pushnil(L); + + return 1; +} + +bool Shape::testPoint(float x, float y) const +{ + throwIfFixtureNotValid(); + return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y))); +} + bool Shape::testPoint(float x, float y, float r, float px, float py) const { + throwIfShapeNotValid(); b2Vec2 point(px, py); b2Transform transform(Physics::scaleDown(b2Vec2(x, y)), b2Rot(r)); return shape->TestPoint(transform, Physics::scaleDown(point)); @@ -95,18 +389,34 @@ int Shape::rayCast(lua_State *L) const float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3)); float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4)); float maxFraction = (float)luaL_checknumber(L, 5); - float x = Physics::scaleDown((float)luaL_checknumber(L, 6)); - float y = Physics::scaleDown((float)luaL_checknumber(L, 7)); - float r = (float)luaL_checknumber(L, 8); - int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index + b2RayCastInput input; + b2RayCastOutput output; input.p1.Set(p1x, p1y); input.p2.Set(p2x, p2y); input.maxFraction = maxFraction; - b2Transform transform(b2Vec2(x, y), b2Rot(r)); - b2RayCastOutput output; - if (!shape->RayCast(&output, input, transform, childIndex)) - return 0; // No hit. + + if (lua_isnoneornil(L, 7)) + { + throwIfFixtureNotValid(); + int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index + if (!fixture->RayCast(&output, input, childIndex)) + return 0; // Nothing hit. + } + else + { + throwIfShapeNotValid(); + float x = Physics::scaleDown((float)luaL_checknumber(L, 6)); + float y = Physics::scaleDown((float)luaL_checknumber(L, 7)); + float r = (float)luaL_checknumber(L, 8); + int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index + + b2Transform transform(b2Vec2(x, y), b2Rot(r)); + + if (!shape->RayCast(&output, input, transform, childIndex)) + return 0; // No hit. + } + lua_pushnumber(L, output.normal.x); lua_pushnumber(L, output.normal.y); lua_pushnumber(L, output.fraction); @@ -115,6 +425,7 @@ int Shape::rayCast(lua_State *L) const int Shape::computeAABB(lua_State *L) const { + throwIfShapeNotValid(); float x = Physics::scaleDown((float)luaL_checknumber(L, 1)); float y = Physics::scaleDown((float)luaL_checknumber(L, 2)); float r = (float)luaL_checknumber(L, 3); @@ -132,6 +443,7 @@ int Shape::computeAABB(lua_State *L) const int Shape::computeMass(lua_State *L) const { + throwIfShapeNotValid(); float density = (float)luaL_checknumber(L, 1); b2MassData data; shape->ComputeMass(&data, density); @@ -143,6 +455,33 @@ int Shape::computeMass(lua_State *L) const return 4; } +int Shape::getBoundingBox(lua_State *L) const +{ + throwIfFixtureNotValid(); + int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index + b2AABB box; + luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); }); + box = Physics::scaleUp(box); + lua_pushnumber(L, box.lowerBound.x); + lua_pushnumber(L, box.lowerBound.y); + lua_pushnumber(L, box.upperBound.x); + lua_pushnumber(L, box.upperBound.y); + return 4; +} + +int Shape::getMassData(lua_State *L) const +{ + throwIfFixtureNotValid(); + b2MassData data; + fixture->GetMassData(&data); + b2Vec2 center = Physics::scaleUp(data.center); + lua_pushnumber(L, center.x); + lua_pushnumber(L, center.y); + lua_pushnumber(L, data.mass); + lua_pushnumber(L, data.I); + return 4; +} + } // box2d } // physics } // love diff --git a/src/modules/physics/box2d/Shape.h b/src/modules/physics/box2d/Shape.h index 94b314dc9..6eb4e0586 100644 --- a/src/modules/physics/box2d/Shape.h +++ b/src/modules/physics/box2d/Shape.h @@ -24,6 +24,7 @@ // LOVE #include "physics/Shape.h" #include "physics/box2d/Body.h" +#include "common/Reference.h" // Box2D #include @@ -45,34 +46,155 @@ class Shape : public love::physics::Shape { public: - friend class Fixture; + friend class Physics; /** * Creates a Shape. **/ - Shape(); - Shape(b2Shape *shape, bool own = true); + Shape(Body *body, const b2Shape &shape); virtual ~Shape(); + void destroy(bool implicit = false); + + /** + * Returns true if the shape is active in a Box2D world. + **/ + bool isValid() const { return fixture != nullptr; } + + /** + * Returns true if the shape has not been destroyed. + **/ + bool isShapeValid() const { return shape != nullptr; } + + /** + * Checks whether this Shape acts as a sensor. + **/ + bool isSensor() const; + + /** + * Set whether this Shape should be a sensor or not. + **/ + void setSensor(bool sensor); + + /** + * Gets the Body this Shape is attached to. + **/ + Body *getBody() const; + + /** + * Sets the filter data. An integer array is used even though the + * first two elements are unsigned shorts. The elements are: + * category (16-bits), mask (16-bits) and group (32-bits/int). + **/ + void setFilterData(int *v); + + /** + * Gets the filter data. An integer array is used even though the + * first two elements are unsigned shorts. The elements are: + * category (16-bits), mask (16-bits) and group (32-bits/int). + **/ + void getFilterData(int *v); + + /** + * This function stores an in-C reference to + * arbitrary Lua data in the Shape object. + **/ + int setUserData(lua_State *L); + + /** + * Gets the data set with setUserData. If no + * data is set, nil is returned. + **/ + int getUserData(lua_State *L); + + /** + * Sets the friction of the Shape. + **/ + void setFriction(float friction); + + /** + * Sets the restitution for the Shape. + **/ + void setRestitution(float restitution); + + /** + * Sets the density of the Shape. + **/ + void setDensity(float density); + + /** + * Gets the friction of the Shape. + **/ + float getFriction() const; + + /** + * Gets the restitution of the Shape. + **/ + float getRestitution() const; + + /** + * Gets the density of the Shape. + **/ + float getDensity() const; + + /** + * Checks if a point is inside the Shape. + **/ + bool testPoint(float x, float y) const; + bool testPoint(float x, float y, float r, float px, float py) const; + /** * Gets the type of Shape. Useful for * debug drawing. **/ Type getType() const; + float getRadius() const; int getChildCount() const; - bool testPoint(float x, float y, float r, float px, float py) const; int rayCast(lua_State *L) const; int computeAABB(lua_State *L) const; int computeMass(lua_State *L) const; + void setGroupIndex(int index); + int getGroupIndex() const; + + int setCategory(lua_State *L); + int setMask(lua_State *L); + int getCategory(lua_State *L); + int getMask(lua_State *L); + uint16 getBits(lua_State *L); + int pushBits(lua_State *L, uint16 bits); + + /** + * Gets the bounding box for this Shape. + **/ + int getBoundingBox(lua_State *L) const; + + /** + * Gets the mass data for this Shape. + * This operation may be expensive. + **/ + int getMassData(lua_State *L) const; + + void throwIfFixtureNotValid() const; + void throwIfShapeNotValid() const; + protected: // The Box2D shape. b2Shape *shape; bool own; -}; + + Shape::Type shapeType; + + Body *body; + b2Fixture *fixture; + + // Reference to arbitrary data. + Reference* ref = nullptr; + +}; // Shape } // box2d } // physics diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index 8e37940c7..b90c4a3c7 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -20,7 +20,6 @@ #include "World.h" -#include "Fixture.h" #include "Shape.h" #include "Contact.h" #include "Physics.h" @@ -28,6 +27,7 @@ // Needed for World::getJoints. It should be moved to wrapper code... #include "wrap_Joint.h" +#include "wrap_Shape.h" namespace love { @@ -58,22 +58,22 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse { ref->push(L); - // Push first fixture. + // Push first shape. { - Fixture *a = (Fixture *)(contact->GetFixtureA()->GetUserData().pointer); + Shape *a = (Shape *)(contact->GetFixtureA()->GetUserData().pointer); if (a != nullptr) - luax_pushtype(L, a); + luax_pushshape(L, a); else - throw love::Exception("A fixture has escaped Memoizer!"); + throw love::Exception("A Shape has escaped Memoizer!"); } - // Push second fixture. + // Push second shape. { - Fixture *b = (Fixture *)(contact->GetFixtureB()->GetUserData().pointer); + Shape *b = (Shape *)(contact->GetFixtureB()->GetUserData().pointer); if (b != nullptr) - luax_pushtype(L, b); + luax_pushshape(L, b); else - throw love::Exception("A fixture has escaped Memoizer!"); + throw love::Exception("A Shape has escaped Memoizer!"); } Contact *cobj = (Contact *)world->findObject(contact); @@ -112,7 +112,7 @@ World::ContactFilter::~ContactFilter() delete ref; } -bool World::ContactFilter::process(Fixture *a, Fixture *b) +bool World::ContactFilter::process(Shape *a, Shape *b) { // Handle masks, reimplemented from the manual int filterA[3], filterB[3]; @@ -133,8 +133,8 @@ bool World::ContactFilter::process(Fixture *a, Fixture *b) if (ref != nullptr && L != nullptr) { ref->push(L); - luax_pushtype(L, a); - luax_pushtype(L, b); + luax_pushshape(L, a); + luax_pushshape(L, b); lua_call(L, 2, 1); return luax_toboolean(L, -1); } @@ -159,10 +159,10 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture) if (L != nullptr) { lua_pushvalue(L, funcidx); - Fixture *f = (Fixture *)(fixture->GetUserData().pointer); + Shape *f = (Shape *)(fixture->GetUserData().pointer); if (!f) - throw love::Exception("A fixture has escaped Memoizer!"); - luax_pushtype(L, f); + throw love::Exception("A Shape has escaped Memoizer!"); + luax_pushshape(L, f); for (int i = 1; i <= userargs; i++) lua_pushvalue(L, funcidx + i); lua_call(L, 1 + userargs, 1); @@ -191,10 +191,10 @@ bool World::CollectCallback::ReportFixture(b2Fixture *f) if (categoryMask != 0xFFFF && (categoryMask & f->GetFilterData().categoryBits) == 0) return true; - Fixture *fixture = (Fixture *)(f->GetUserData().pointer); - if (!fixture) - throw love::Exception("A fixture has escaped Memoizer!"); - luax_pushtype(L, fixture); + Shape *shape = (Shape *)(f->GetUserData().pointer); + if (!shape) + throw love::Exception("A Shape has escaped Memoizer!"); + luax_pushshape(L, shape); lua_rawseti(L, -2, i); i++; return true; @@ -218,10 +218,10 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po if (L != nullptr) { lua_pushvalue(L, funcidx); - Fixture *f = (Fixture *)(fixture->GetUserData().pointer); + Shape *f = (Shape *)(fixture->GetUserData().pointer); if (!f) - throw love::Exception("A fixture has escaped Memoizer!"); - luax_pushtype(L, f); + throw love::Exception("A Shape has escaped Memoizer!"); + luax_pushshape(L, f); b2Vec2 scaledPoint = Physics::scaleUp(point); lua_pushnumber(L, scaledPoint.x); lua_pushnumber(L, scaledPoint.y); @@ -267,9 +267,9 @@ float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 void World::SayGoodbye(b2Fixture *fixture) { - Fixture *f = (Fixture *)(fixture->GetUserData().pointer); + Shape *s = (Shape *)(fixture->GetUserData().pointer); // Hint implicit destruction with true. - if (f) f->destroy(true); + if (s) s->destroy(true); } void World::SayGoodbye(b2Joint *joint) @@ -336,11 +336,11 @@ void World::update(float dt, int velocityIterations, int positionIterations) // Release for reference in vector. b->release(); } - for (Fixture *f : destructFixtures) + for (Shape *s : destructShapes) { - if (f->isValid()) f->destroy(); + if (s->isValid()) s->destroy(); // Release for reference in vector. - f->release(); + s->release(); } for (Joint *j : destructJoints) { @@ -349,7 +349,7 @@ void World::update(float dt, int velocityIterations, int positionIterations) j->release(); } destructBodies.clear(); - destructFixtures.clear(); + destructShapes.clear(); destructJoints.clear(); if (destructWorld) @@ -384,11 +384,11 @@ void World::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse) bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB) { - // Fixtures should be memoized, if we created them - Fixture *a = (Fixture *)(fixtureA->GetUserData().pointer); - Fixture *b = (Fixture *)(fixtureB->GetUserData().pointer); + // Shapes should be memoized, if we created them + Shape *a = (Shape *)(fixtureA->GetUserData().pointer); + Shape *b = (Shape *)(fixtureB->GetUserData().pointer); if (!a || !b) - throw love::Exception("A fixture has escaped Memoizer!"); + throw love::Exception("A Shape has escaped Memoizer!"); return filter.process(a, b); } @@ -597,7 +597,7 @@ b2Body *World::getGroundBody() const return groundBody; } -int World::queryFixturesInArea(lua_State *L) +int World::queryShapesInArea(lua_State *L) { b2AABB box; float lx = (float)luaL_checknumber(L, 1); @@ -612,7 +612,7 @@ int World::queryFixturesInArea(lua_State *L) return 0; } -int World::getFixturesInArea(lua_State *L) +int World::getShapesInArea(lua_State *L) { float lx = (float)luaL_checknumber(L, 1); float ly = (float)luaL_checknumber(L, 2); @@ -654,10 +654,10 @@ int World::rayCastAny(lua_State *L) world->RayCast(&raycast, v1, v2); if (raycast.hitFixture) { - Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer); + Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer); if (f == nullptr) - return luaL_error(L, "A fixture has escaped Memoizer!"); - luax_pushtype(L, f); + return luaL_error(L, "A Shape has escaped Memoizer!"); + luax_pushshape(L, f); b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint); lua_pushnumber(L, hitPoint.x); @@ -683,10 +683,10 @@ int World::rayCastClosest(lua_State *L) world->RayCast(&raycast, v1, v2); if (raycast.hitFixture) { - Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer); + Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer); if (f == nullptr) - return luaL_error(L, "A fixture has escaped Memoizer!"); - luax_pushtype(L, f); + return luaL_error(L, "A Shape has escaped Memoizer!"); + luax_pushshape(L, f); b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint); lua_pushnumber(L, hitPoint.x); diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 94d2a1e09..2c7eb78b7 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -42,7 +42,6 @@ namespace box2d class Contact; class Body; -class Fixture; class Joint; /** @@ -65,7 +64,7 @@ public: friend class DistanceJoint; friend class MouseJoint; friend class Body; - friend class Fixture; + friend class Shape; static love::Type type; @@ -87,7 +86,7 @@ public: lua_State *L; ContactFilter(); ~ContactFilter(); - bool process(Fixture *a, Fixture *b); + bool process(Shape *a, Shape *b); }; class QueryCallback : public b2QueryCallback @@ -302,14 +301,14 @@ public: b2Body *getGroundBody() const; /** - * Calls a callback on all fixtures that overlap a given bounding box. + * Calls a callback on all Shapes that overlap a given bounding box. **/ - int queryFixturesInArea(lua_State *L); + int queryShapesInArea(lua_State *L); /** - * Gets all fixtures that overlap a given bounding box. + * Gets all Shapes that overlap a given bounding box. **/ - int getFixturesInArea(lua_State *L); + int getShapesInArea(lua_State *L); /** * Raycasts the World for all Fixtures in the path of the ray. @@ -338,7 +337,7 @@ private: // The list of to be destructed bodies. std::vector destructBodies; - std::vector destructFixtures; + std::vector destructShapes; std::vector destructJoints; bool destructWorld; diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index 6ed39ef2e..f0d4dd865 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -20,6 +20,7 @@ #include "wrap_Body.h" #include "wrap_Physics.h" +#include "wrap_Shape.h" namespace love { @@ -599,26 +600,32 @@ int w_Body_getWorld(lua_State *L) return 1; } -int w_Body_getFixture(lua_State *L) +int w_Body_getShape(lua_State *L) { Body *t = luax_checkbody(L, 1); - Fixture *f = t->getFixture(); - if (f) - luax_pushtype(L, f); + Shape *s = t->getShape(); + if (s) + luax_pushshape(L, s); else lua_pushnil(L); return 1; } -int w_Body_getFixtures(lua_State *L) +int w_Body_getShapes(lua_State *L) { Body *t = luax_checkbody(L, 1); lua_remove(L, 1); int n = 0; - luax_catchexcept(L, [&](){ n = t->getFixtures(L); }); + luax_catchexcept(L, [&](){ n = t->getShapes(L); }); return n; } +int w_Body_getFixtures(lua_State *L) +{ + luax_markdeprecated(L, 1, "Body:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Body:getShapes"); + return w_Body_getShapes(L); +} + int w_Body_getJoints(lua_State *L) { Body *t = luax_checkbody(L, 1); @@ -724,8 +731,8 @@ static const luaL_Reg w_Body_functions[] = { "isFixedRotation", w_Body_isFixedRotation }, { "isTouching", w_Body_isTouching }, { "getWorld", w_Body_getWorld }, - { "getFixture", w_Body_getFixture }, - { "getFixtures", w_Body_getFixtures }, + { "getShape", w_Body_getShape }, + { "getShapes", w_Body_getShapes }, { "getJoints", w_Body_getJoints }, { "getContacts", w_Body_getContacts }, { "destroy", w_Body_destroy }, @@ -733,6 +740,9 @@ static const luaL_Reg w_Body_functions[] = { "setUserData", w_Body_setUserData }, { "getUserData", w_Body_getUserData }, + // Deprecated + { "getFixtures", w_Body_getFixtures }, + { 0, 0 } }; diff --git a/src/modules/physics/box2d/wrap_ChainShape.cpp b/src/modules/physics/box2d/wrap_ChainShape.cpp index 52c94ef70..d0597e778 100644 --- a/src/modules/physics/box2d/wrap_ChainShape.cpp +++ b/src/modules/physics/box2d/wrap_ChainShape.cpp @@ -54,9 +54,10 @@ int w_ChainShape_setPreviousVertex(lua_State *L) int w_ChainShape_getChildEdge(lua_State *L) { + luax_markdeprecated(L, 1, "ChainShape:getChildEdge", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr); ChainShape *c = luax_checkchainshape(L, 1); int index = (int) luaL_checkinteger(L, 2) - 1; // Convert from 1-based index - EdgeShape *e = 0; + EdgeShape *e = nullptr; luax_catchexcept(L, [&](){ e = c->getChildEdge(index); }); luax_pushtype(L, e); e->release(); @@ -66,7 +67,8 @@ int w_ChainShape_getChildEdge(lua_State *L) int w_ChainShape_getVertexCount(lua_State *L) { ChainShape *c = luax_checkchainshape(L, 1); - int count = c->getVertexCount(); + int count = 0; + luax_catchexcept(L, [&]() { count = c->getVertexCount(); }); lua_pushinteger(L, count); return 1; } @@ -85,7 +87,8 @@ int w_ChainShape_getPoint(lua_State *L) int w_ChainShape_getNextVertex(lua_State *L) { ChainShape *c = luax_checkchainshape(L, 1); - b2Vec2 v = c->getNextVertex(); + b2Vec2 v; + luax_catchexcept(L, [&]() { v = c->getNextVertex(); }); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); return 2; @@ -94,7 +97,8 @@ int w_ChainShape_getNextVertex(lua_State *L) int w_ChainShape_getPreviousVertex(lua_State *L) { ChainShape *c = luax_checkchainshape(L, 1); - b2Vec2 v = c->getPreviousVertex(); + b2Vec2 v; + luax_catchexcept(L, [&]() { v = c->getPreviousVertex(); }); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); return 2; @@ -103,7 +107,8 @@ int w_ChainShape_getPreviousVertex(lua_State *L) int w_ChainShape_getPoints(lua_State *L) { ChainShape *c = luax_checkchainshape(L, 1); - const b2Vec2 *verts = c->getPoints(); + const b2Vec2 *verts; + luax_catchexcept(L, [&]() { verts = c->getPoints(); }); int count = c->getVertexCount(); if (!lua_checkstack(L, count*2)) return luaL_error(L, "Too many return values"); diff --git a/src/modules/physics/box2d/wrap_CircleShape.cpp b/src/modules/physics/box2d/wrap_CircleShape.cpp index f9ec8394a..99bc524d6 100644 --- a/src/modules/physics/box2d/wrap_CircleShape.cpp +++ b/src/modules/physics/box2d/wrap_CircleShape.cpp @@ -35,7 +35,9 @@ CircleShape *luax_checkcircleshape(lua_State *L, int idx) int w_CircleShape_getRadius(lua_State *L) { CircleShape *c = luax_checkcircleshape(L, 1); - lua_pushnumber(L, c->getRadius()); + float r = 0; + luax_catchexcept(L, [&]() { r = c->getRadius(); }); + lua_pushnumber(L, r); return 1; } @@ -43,7 +45,7 @@ int w_CircleShape_setRadius(lua_State *L) { CircleShape *c = luax_checkcircleshape(L, 1); float r = (float)luaL_checknumber(L, 2); - c->setRadius(r); + luax_catchexcept(L, [&]() { c->setRadius(r); }); return 0; } @@ -51,7 +53,7 @@ int w_CircleShape_getPoint(lua_State *L) { CircleShape *c = luax_checkcircleshape(L, 1); float x, y; - c->getPoint(x, y); + luax_catchexcept(L, [&]() { c->getPoint(x, y); }); lua_pushnumber(L, x); lua_pushnumber(L, y); return 2; diff --git a/src/modules/physics/box2d/wrap_Contact.cpp b/src/modules/physics/box2d/wrap_Contact.cpp index d18d39402..a61c6a72b 100644 --- a/src/modules/physics/box2d/wrap_Contact.cpp +++ b/src/modules/physics/box2d/wrap_Contact.cpp @@ -19,7 +19,7 @@ **/ #include "wrap_Contact.h" -#include "Fixture.h" +#include "wrap_Shape.h" namespace love { @@ -139,18 +139,24 @@ int w_Contact_getChildren(lua_State *L) return 2; } -int w_Contact_getFixtures(lua_State *L) +int w_Contact_getShapes(lua_State *L) { Contact *t = luax_checkcontact(L, 1); - Fixture *a = nullptr; - Fixture *b = nullptr; - luax_catchexcept(L, [&](){ t->getFixtures(a, b); }); + Shape *a = nullptr; + Shape *b = nullptr; + luax_catchexcept(L, [&](){ t->getShapes(a, b); }); - luax_pushtype(L, a); - luax_pushtype(L, b); + luax_pushshape(L, a); + luax_pushshape(L, b); return 2; } +int w_Contact_getFixtures(lua_State *L) +{ + luax_markdeprecated(L, 1, "Contact:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Contact:getShapes"); + return w_Contact_getShapes(L); +} + int w_Contact_isDestroyed(lua_State *L) { Contact *c = luax_checktype(L, 1); @@ -174,8 +180,12 @@ static const luaL_Reg w_Contact_functions[] = { "setTangentSpeed", w_Contact_setTangentSpeed }, { "getTangentSpeed", w_Contact_getTangentSpeed }, { "getChildren", w_Contact_getChildren }, - { "getFixtures", w_Contact_getFixtures }, + { "getShapes", w_Contact_getShapes }, { "isDestroyed", w_Contact_isDestroyed }, + + // Deprecated + { "getFixtures", w_Contact_getFixtures }, + { 0, 0 } }; diff --git a/src/modules/physics/box2d/wrap_EdgeShape.cpp b/src/modules/physics/box2d/wrap_EdgeShape.cpp index fbc0c0574..a97b115a5 100644 --- a/src/modules/physics/box2d/wrap_EdgeShape.cpp +++ b/src/modules/physics/box2d/wrap_EdgeShape.cpp @@ -37,7 +37,7 @@ int w_EdgeShape_setNextVertex(lua_State *L) EdgeShape *t = luax_checkedgeshape(L, 1); float x = (float)luaL_checknumber(L, 2); float y = (float)luaL_checknumber(L, 3); - t->setNextVertex(x, y); + luax_catchexcept(L, [&]() { t->setNextVertex(x, y); }); return 0; } @@ -46,14 +46,15 @@ int w_EdgeShape_setPreviousVertex(lua_State *L) EdgeShape *t = luax_checkedgeshape(L, 1); float x = (float)luaL_checknumber(L, 2); float y = (float)luaL_checknumber(L, 3); - t->setPreviousVertex(x, y); + luax_catchexcept(L, [&]() { t->setPreviousVertex(x, y); }); return 0; } int w_EdgeShape_getNextVertex(lua_State *L) { EdgeShape *t = luax_checkedgeshape(L, 1); - b2Vec2 v = t->getNextVertex(); + b2Vec2 v; + luax_catchexcept(L, [&]() { v = t->getNextVertex(); }); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); return 2; @@ -62,7 +63,8 @@ int w_EdgeShape_getNextVertex(lua_State *L) int w_EdgeShape_getPreviousVertex(lua_State *L) { EdgeShape *t = luax_checkedgeshape(L, 1); - b2Vec2 v = t->getPreviousVertex(); + b2Vec2 v; + luax_catchexcept(L, [&]() { v = t->getPreviousVertex(); }); lua_pushnumber(L, v.x); lua_pushnumber(L, v.y); return 2; @@ -72,7 +74,9 @@ int w_EdgeShape_getPoints(lua_State *L) { EdgeShape *t = luax_checkedgeshape(L, 1); lua_remove(L, 1); - return t->getPoints(L); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getPoints(L); }); + return ret; } static const luaL_Reg w_EdgeShape_functions[] = diff --git a/src/modules/physics/box2d/wrap_Fixture.cpp b/src/modules/physics/box2d/wrap_Fixture.cpp deleted file mode 100644 index 4056874c9..000000000 --- a/src/modules/physics/box2d/wrap_Fixture.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/** - * Copyright (c) 2006-2023 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 "wrap_Fixture.h" -#include "common/StringMap.h" - -namespace love -{ -namespace physics -{ -namespace box2d -{ - -Fixture *luax_checkfixture(lua_State *L, int idx) -{ - Fixture *f = luax_checktype(L, idx); - if (!f->isValid()) - luaL_error(L, "Attempt to use destroyed fixture."); - return f; -} - -int w_Fixture_getType(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - const char *type = ""; - Shape::getConstant(t->getType(), type); - lua_pushstring(L, type); - return 1; -} - -int w_Fixture_setFriction(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - float arg1 = (float)luaL_checknumber(L, 2); - t->setFriction(arg1); - return 0; -} - -int w_Fixture_setRestitution(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - float arg1 = (float)luaL_checknumber(L, 2); - t->setRestitution(arg1); - return 0; -} - -int w_Fixture_setDensity(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - float arg1 = (float)luaL_checknumber(L, 2); - luax_catchexcept(L, [&](){ t->setDensity(arg1); }); - return 0; -} - -int w_Fixture_setSensor(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - bool arg1 = luax_checkboolean(L, 2); - t->setSensor(arg1); - return 0; -} - -int w_Fixture_getFriction(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_pushnumber(L, t->getFriction()); - return 1; -} - -int w_Fixture_getRestitution(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_pushnumber(L, t->getRestitution()); - return 1; -} - -int w_Fixture_getDensity(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_pushnumber(L, t->getDensity()); - return 1; -} - -int w_Fixture_isSensor(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - luax_pushboolean(L, t->isSensor()); - return 1; -} - -int w_Fixture_getBody(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - Body *body = t->getBody(); - if (body == 0) - return 0; - luax_pushtype(L, body); - return 1; -} - -int w_Fixture_getShape(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - Shape * shape = t->getShape(); - if (shape == nullptr) - return 0; - switch (shape->getType()) - { - case Shape::SHAPE_EDGE: - luax_pushtype(L, dynamic_cast(shape)); - break; - case Shape::SHAPE_CHAIN: - luax_pushtype(L, dynamic_cast(shape)); - break; - case Shape::SHAPE_CIRCLE: - luax_pushtype(L, dynamic_cast(shape)); - break; - case Shape::SHAPE_POLYGON: - luax_pushtype(L, dynamic_cast(shape)); - break; - default: - luax_pushtype(L, shape); - break; - } - return 1; -} - -int w_Fixture_testPoint(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - float x = (float)luaL_checknumber(L, 2); - float y = (float)luaL_checknumber(L, 3); - luax_pushboolean(L, t->testPoint(x, y)); - return 1; -} - -int w_Fixture_rayCast(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - int ret = 0; - luax_catchexcept(L, [&](){ ret = t->rayCast(L); }); - return ret; -} - -int w_Fixture_setFilterData(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - int v[3]; - v[0] = (int) luaL_checkinteger(L, 2); - v[1] = (int) luaL_checkinteger(L, 3); - v[2] = (int) luaL_checkinteger(L, 4); - t->setFilterData(v); - return 0; -} - -int w_Fixture_getFilterData(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - int v[3]; - t->getFilterData(v); - lua_pushinteger(L, v[0]); - lua_pushinteger(L, v[1]); - lua_pushinteger(L, v[2]); - return 3; -} - -int w_Fixture_setCategory(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->setCategory(L); -} - -int w_Fixture_getCategory(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->getCategory(L); -} - -int w_Fixture_setMask(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->setMask(L); -} - -int w_Fixture_getMask(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->getMask(L); -} - -int w_Fixture_setUserData(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->setUserData(L); -} - -int w_Fixture_getUserData(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->getUserData(L); -} - -int w_Fixture_getBoundingBox(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->getBoundingBox(L); -} - -int w_Fixture_getMassData(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - lua_remove(L, 1); - return t->getMassData(L); -} - -int w_Fixture_getGroupIndex(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - int i = t->getGroupIndex(); - lua_pushinteger(L, i); - return 1; -} - -int w_Fixture_setGroupIndex(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - int i = (int) luaL_checkinteger(L, 2); - t->setGroupIndex(i); - return 0; -} - -int w_Fixture_destroy(lua_State *L) -{ - Fixture *t = luax_checkfixture(L, 1); - luax_catchexcept(L, [&](){ t->destroy(); }); - return 0; -} - -int w_Fixture_isDestroyed(lua_State *L) -{ - Fixture *f = luax_checktype(L, 1); - luax_pushboolean(L, !f->isValid()); - return 1; -} - -static const luaL_Reg w_Fixture_functions[] = -{ - { "getType", w_Fixture_getType }, - { "setFriction", w_Fixture_setFriction }, - { "setRestitution", w_Fixture_setRestitution }, - { "setDensity", w_Fixture_setDensity }, - { "setSensor", w_Fixture_setSensor }, - { "getFriction", w_Fixture_getFriction }, - { "getRestitution", w_Fixture_getRestitution }, - { "getDensity", w_Fixture_getDensity }, - { "getBody", w_Fixture_getBody }, - { "getShape", w_Fixture_getShape }, - { "isSensor", w_Fixture_isSensor }, - { "testPoint", w_Fixture_testPoint }, - { "rayCast", w_Fixture_rayCast }, - { "setFilterData", w_Fixture_setFilterData }, - { "getFilterData", w_Fixture_getFilterData }, - { "setCategory", w_Fixture_setCategory }, - { "getCategory", w_Fixture_getCategory }, - { "setMask", w_Fixture_setMask }, - { "getMask", w_Fixture_getMask }, - { "setUserData", w_Fixture_setUserData }, - { "getUserData", w_Fixture_getUserData }, - { "getBoundingBox", w_Fixture_getBoundingBox }, - { "getMassData", w_Fixture_getMassData }, - { "getGroupIndex", w_Fixture_getGroupIndex }, - { "setGroupIndex", w_Fixture_setGroupIndex }, - { "destroy", w_Fixture_destroy }, - { "isDestroyed", w_Fixture_isDestroyed }, - { 0, 0 } -}; - -extern "C" int luaopen_fixture(lua_State *L) -{ - return luax_register_type(L, &Fixture::type, w_Fixture_functions, nullptr); -} - -} // box2d -} // physics -} // love - diff --git a/src/modules/physics/box2d/wrap_Fixture.h b/src/modules/physics/box2d/wrap_Fixture.h deleted file mode 100644 index 0d31d6fa0..000000000 --- a/src/modules/physics/box2d/wrap_Fixture.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2006-2023 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_PHYSICS_BOX2D_WRAP_FIXTURE_H -#define LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H - -// LOVE -#include "common/runtime.h" -#include "Fixture.h" -#include "wrap_Physics.h" - -namespace love -{ -namespace physics -{ -namespace box2d -{ - -Fixture *luax_checkfixture(lua_State *L, int idx); -extern "C" int luaopen_fixture(lua_State *L); - -} // box2d -} // physics -} // love - -#endif // LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index 7b755f92e..917cdf812 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -23,7 +23,6 @@ #include "wrap_World.h" #include "wrap_Contact.h" #include "wrap_Body.h" -#include "wrap_Fixture.h" #include "wrap_Shape.h" #include "wrap_CircleShape.h" #include "wrap_PolygonShape.h" @@ -256,36 +255,56 @@ int w_newChainBody(lua_State *L) int w_newFixture(lua_State *L) { + luax_markdeprecated(L, 1, "love.physics.newFixture", API_FUNCTION, DEPRECATED_REPLACED, "love.physics.newCircle/Rectangle/Polygon/Edge/ChainShape"); + Body *body = luax_checkbody(L, 1); Shape *shape = luax_checkshape(L, 2); float density = (float)luaL_optnumber(L, 3, 1.0f); - Fixture *fixture; - luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); }); - luax_pushtype(L, fixture); - fixture->release(); + + Shape *newShape; + luax_catchexcept(L, [&]() { + newShape = instance()->newAttachedShape(body, shape, density); + newShape->setDensity(density); + body->resetMassData(); + }); + + luax_pushshape(L, newShape); + newShape->release(); return 1; } +static Body *luax_optbodyforshape(lua_State *L, int idx, const char *name) +{ + if (luax_istype(L, idx, Body::type)) + return luax_checkbody(L, idx); + + luax_markdeprecated(L, 1, name, API_FUNCTION_VARIANT, DEPRECATED_REPLACED, "variant with Body parameter"); + return nullptr; +} + int w_newCircleShape(lua_State *L) { - int top = lua_gettop(L); + Body *body = luax_optbodyforshape(L, 1, "love.physics.newCircleShape"); + int bodyidx = body ? 1 : 0; + + int top = lua_gettop(L) - bodyidx; if (top == 1) { - float radius = (float)luaL_checknumber(L, 1); + float radius = (float)luaL_checknumber(L, bodyidx + 1); CircleShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(0, 0, radius); }); + luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, 0, 0, radius); }); luax_pushtype(L, shape); shape->release(); return 1; } else if (top == 3) { - float x = (float)luaL_checknumber(L, 1); - float y = (float)luaL_checknumber(L, 2); - float radius = (float)luaL_checknumber(L, 3); + float x = (float)luaL_checknumber(L, bodyidx + 1); + float y = (float)luaL_checknumber(L, bodyidx + 2); + float radius = (float)luaL_checknumber(L, bodyidx + 3); CircleShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); }); + luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, x, y, radius); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -296,27 +315,30 @@ int w_newCircleShape(lua_State *L) int w_newRectangleShape(lua_State *L) { - int top = lua_gettop(L); + Body *body = luax_optbodyforshape(L, 1, "love.physics.newRectangleShape"); + int bodyidx = body ? 1 : 0; + + int top = lua_gettop(L) - bodyidx; if (top == 2) { - float w = (float)luaL_checknumber(L, 1); - float h = (float)luaL_checknumber(L, 2); + float w = (float)luaL_checknumber(L, bodyidx + 1); + float h = (float)luaL_checknumber(L, bodyidx + 2); PolygonShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(0, 0, w, h, 0); }); + luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, 0, 0, w, h, 0); }); luax_pushtype(L, shape); shape->release(); return 1; } else if (top == 4 || top == 5) { - float x = (float)luaL_checknumber(L, 1); - float y = (float)luaL_checknumber(L, 2); - float w = (float)luaL_checknumber(L, 3); - float h = (float)luaL_checknumber(L, 4); - float angle = (float)luaL_optnumber(L, 5, 0); + float x = (float)luaL_checknumber(L, bodyidx + 1); + float y = (float)luaL_checknumber(L, bodyidx + 2); + float w = (float)luaL_checknumber(L, bodyidx + 3); + float h = (float)luaL_checknumber(L, bodyidx + 4); + float angle = (float)luaL_optnumber(L, bodyidx + 5, 0); PolygonShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); }); + luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, x, y, w, h, angle); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -327,13 +349,16 @@ int w_newRectangleShape(lua_State *L) int w_newEdgeShape(lua_State *L) { - float x1 = (float)luaL_checknumber(L, 1); - float y1 = (float)luaL_checknumber(L, 2); - float x2 = (float)luaL_checknumber(L, 3); - float y2 = (float)luaL_checknumber(L, 4); - bool oneSided = luax_optboolean(L, 5, false); + Body *body = luax_optbodyforshape(L, 1, "love.physics.newEdgeShape"); + int bodyidx = body ? 1 : 0; + + float x1 = (float)luaL_checknumber(L, bodyidx + 1); + float y1 = (float)luaL_checknumber(L, bodyidx + 2); + float x2 = (float)luaL_checknumber(L, bodyidx + 3); + float y2 = (float)luaL_checknumber(L, bodyidx + 4); + bool oneSided = luax_optboolean(L, bodyidx + 5, false); EdgeShape *shape; - luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2, oneSided); }); + luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(body, x1, y1, x2, y2, oneSided); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -341,12 +366,15 @@ int w_newEdgeShape(lua_State *L) int w_newPolygonShape(lua_State *L) { - int argc = lua_gettop(L); + Body *body = luax_optbodyforshape(L, 1, "love.physics.newPolygonShape"); + int bodyidx = body ? 1 : 0; - bool istable = lua_istable(L, 1); + int argc = lua_gettop(L) - bodyidx; + + bool istable = lua_istable(L, bodyidx + 1); if (istable) - argc = (int)luax_objlen(L, 1); + argc = (int)luax_objlen(L, bodyidx + 1); if (argc % 2 != 0) return luaL_error(L, "Number of vertex components must be a multiple of two."); @@ -358,8 +386,8 @@ int w_newPolygonShape(lua_State *L) { for (int i = 0; i < vcount; i++) { - lua_rawgeti(L, 1, 1 + i * 2); - lua_rawgeti(L, 1, 2 + i * 2); + lua_rawgeti(L, bodyidx + 1, 1 + i * 2); + lua_rawgeti(L, bodyidx + 1, 2 + i * 2); float x = (float)luaL_checknumber(L, -2); float y = (float)luaL_checknumber(L, -1); coords.emplace_back(x, y); @@ -370,14 +398,14 @@ int w_newPolygonShape(lua_State *L) { for (int i = 0; i < vcount; i++) { - float x = (float)luaL_checknumber(L, 1 + i * 2); - float y = (float)luaL_checknumber(L, 2 + i * 2); + float x = (float)luaL_checknumber(L, bodyidx + 1 + i * 2); + float y = (float)luaL_checknumber(L, bodyidx + 2 + i * 2); coords.emplace_back(x, y); } } PolygonShape *shape = nullptr; - luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(coords.data(), (int)coords.size()); }); + luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(body, coords.data(), (int)coords.size()); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -385,26 +413,29 @@ int w_newPolygonShape(lua_State *L) int w_newChainShape(lua_State *L) { - int argc = lua_gettop(L) - 1; // first argument is looping + Body *body = luax_optbodyforshape(L, 1, "love.physics.newChainShape"); + int bodyidx = body ? 1 : 0; - bool istable = lua_istable(L, 2); + int argc = lua_gettop(L) - 1 - bodyidx; // first argument is looping + + bool istable = lua_istable(L, bodyidx + 2); if (istable) - argc = (int)luax_objlen(L, 2); + argc = (int)luax_objlen(L, bodyidx + 2); if (argc == 0 || argc % 2 != 0) return luaL_error(L, "Number of vertex components must be a multiple of two."); int vcount = argc / 2; - bool loop = luax_checkboolean(L, 1); + bool loop = luax_checkboolean(L, bodyidx + 1); std::vector coords; if (istable) { for (int i = 0; i < vcount; i++) { - lua_rawgeti(L, 2, 1 + i * 2); - lua_rawgeti(L, 2, 2 + i * 2); + lua_rawgeti(L, bodyidx + 2, 1 + i * 2); + lua_rawgeti(L, bodyidx + 2, 2 + i * 2); float x = (float)lua_tonumber(L, -2); float y = (float)lua_tonumber(L, -1); coords.emplace_back(x, y); @@ -415,14 +446,14 @@ int w_newChainShape(lua_State *L) { for (int i = 0; i < vcount; i++) { - float x = (float)luaL_checknumber(L, 2 + i * 2); - float y = (float)luaL_checknumber(L, 3 + i * 2); + float x = (float)luaL_checknumber(L, bodyidx + 2 + i * 2); + float y = (float)luaL_checknumber(L, bodyidx + 3 + i * 2); coords.emplace_back(x, y); } } ChainShape *shape = nullptr; - luax_catchexcept(L, [&]() { shape = instance()->newChainShape(loop, coords.data(), coords.size()); }); + luax_catchexcept(L, [&]() { shape = instance()->newChainShape(body, loop, coords.data(), coords.size()); }); luax_pushtype(L, shape); shape->release(); return 1; @@ -824,7 +855,6 @@ static const luaL_Reg functions[] = { "newPolygonBody", w_newPolygonBody }, { "newEdgeBody", w_newEdgeBody }, { "newChainBody", w_newChainBody }, - { "newFixture", w_newFixture }, { "newCircleShape", w_newCircleShape }, { "newRectangleShape", w_newRectangleShape }, { "newPolygonShape", w_newPolygonShape }, @@ -848,6 +878,10 @@ static const luaL_Reg functions[] = { "computeLinearFrequency", w_computeLinearFrequency }, { "computeAngularStiffness", w_computeAngularStiffness }, { "computeAngularFrequency", w_computeAngularFrequency }, + + // Deprecated + { "newFixture", w_newFixture }, + { 0, 0 }, }; @@ -856,7 +890,6 @@ static const lua_CFunction types[] = luaopen_world, luaopen_contact, luaopen_body, - luaopen_fixture, luaopen_shape, luaopen_circleshape, luaopen_polygonshape, diff --git a/src/modules/physics/box2d/wrap_PolygonShape.cpp b/src/modules/physics/box2d/wrap_PolygonShape.cpp index 522b1bf9f..e558f000e 100644 --- a/src/modules/physics/box2d/wrap_PolygonShape.cpp +++ b/src/modules/physics/box2d/wrap_PolygonShape.cpp @@ -36,13 +36,17 @@ int w_PolygonShape_getPoints(lua_State *L) { PolygonShape *t = luax_checkpolygonshape(L, 1); lua_remove(L, 1); - return t->getPoints(L); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getPoints(L); }); + return ret; } int w_PolygonShape_validate(lua_State *L) { PolygonShape *t = luax_checkpolygonshape(L, 1); - luax_pushboolean(L, t->validate()); + bool valid = false; + luax_catchexcept(L, [&]() { valid = t->validate(); }); + luax_pushboolean(L, valid); return 1; } diff --git a/src/modules/physics/box2d/wrap_Shape.cpp b/src/modules/physics/box2d/wrap_Shape.cpp index 497f5d95f..7b32cac13 100644 --- a/src/modules/physics/box2d/wrap_Shape.cpp +++ b/src/modules/physics/box2d/wrap_Shape.cpp @@ -33,6 +33,35 @@ Shape *luax_checkshape(lua_State *L, int idx) return luax_checktype(L, idx); } +void luax_pushshape(lua_State *L, Shape *shape) +{ + if (shape != nullptr) + { + switch (shape->getType()) + { + case Shape::SHAPE_CIRCLE: + luax_pushtype(L, (CircleShape *) shape); + break; + case Shape::SHAPE_POLYGON: + luax_pushtype(L, (PolygonShape *) shape); + break; + case Shape::SHAPE_EDGE: + luax_pushtype(L, (EdgeShape *) shape); + break; + case Shape::SHAPE_CHAIN: + luax_pushtype(L, (ChainShape *) shape); + break; + default: + luax_pushtype(L, shape); + break; + } + } + else + { + lua_pushnil(L); + } +} + int w_Shape_getType(lua_State *L) { Shape *t = luax_checkshape(L, 1); @@ -45,7 +74,8 @@ int w_Shape_getType(lua_State *L) int w_Shape_getRadius(lua_State *L) { Shape *t = luax_checkshape(L, 1); - float radius = t->getRadius(); + float radius = 0; + luax_catchexcept(L, [&]() { radius = t->getRadius(); }); lua_pushnumber(L, radius); return 1; } @@ -53,20 +83,115 @@ int w_Shape_getRadius(lua_State *L) int w_Shape_getChildCount(lua_State *L) { Shape *t = luax_checkshape(L, 1); - int childCount = t->getChildCount(); + int childCount = 0; + luax_catchexcept(L, [&]() { childCount = t->getChildCount(); }); lua_pushinteger(L, childCount); return 1; } +int w_Shape_setFriction(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + float arg1 = (float)luaL_checknumber(L, 2); + luax_catchexcept(L, [&]() { t->setFriction(arg1); }); + return 0; +} + +int w_Shape_setRestitution(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + float arg1 = (float)luaL_checknumber(L, 2); + luax_catchexcept(L, [&]() { t->setRestitution(arg1); }); + return 0; +} + +int w_Shape_setDensity(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + float arg1 = (float)luaL_checknumber(L, 2); + luax_catchexcept(L, [&](){ t->setDensity(arg1); }); + return 0; +} + +int w_Shape_setSensor(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + bool arg1 = luax_checkboolean(L, 2); + luax_catchexcept(L, [&]() { t->setSensor(arg1); }); + return 0; +} + +int w_Shape_getFriction(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + float friction = 0; + luax_catchexcept(L, [&]() { friction = t->getFriction(); }); + lua_pushnumber(L, friction); + return 1; +} + +int w_Shape_getRestitution(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + float r = 0; + luax_catchexcept(L, [&]() { r = t->getRestitution(); }); + lua_pushnumber(L, r); + return 1; +} + +int w_Shape_getDensity(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + float d = 0; + luax_catchexcept(L, [&]() { d = t->getDensity(); }); + lua_pushnumber(L, d); + return 1; +} + +int w_Shape_isSensor(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + bool sensor = false; + luax_catchexcept(L, [&]() { sensor = t->isSensor(); }); + luax_pushboolean(L, sensor); + return 1; +} + +int w_Shape_getBody(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + Body *body = t->getBody(); + if (body == nullptr) + return 0; + luax_pushtype(L, body); + return 1; +} + +int w_Shape_getShape(lua_State *L) +{ + luax_markdeprecated(L, 1, "Fixture:getShape", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr); + Shape *t = luax_checkshape(L, 1); + luax_pushshape(L, t); + return 1; +} + int w_Shape_testPoint(lua_State *L) { Shape *t = luax_checkshape(L, 1); float x = (float)luaL_checknumber(L, 2); float y = (float)luaL_checknumber(L, 3); - float r = (float)luaL_checknumber(L, 4); - float px = (float)luaL_checknumber(L, 5); - float py = (float)luaL_checknumber(L, 6); - bool result = t->testPoint(x, y, r, px, py); + bool result = false; + if (!lua_isnoneornil(L, 4)) + { + float r = (float)luaL_checknumber(L, 4); + float px = (float)luaL_checknumber(L, 5); + float py = (float)luaL_checknumber(L, 6); + result = luax_catchexcept(L, [&]() { t->testPoint(x, y, r, px, py); }); + } + else + { + result = luax_catchexcept(L, [&]() { t->testPoint(x, y); }); + } lua_pushboolean(L, result); return 1; } @@ -84,14 +209,143 @@ int w_Shape_computeAABB(lua_State *L) { Shape *t = luax_checkshape(L, 1); lua_remove(L, 1); - return t->computeAABB(L); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->computeAABB(L); }); + return ret; } int w_Shape_computeMass(lua_State *L) { Shape *t = luax_checkshape(L, 1); lua_remove(L, 1); - return t->computeMass(L); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->computeMass(L); }); + return ret; +} + +int w_Shape_setFilterData(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + int v[3]; + v[0] = (int) luaL_checkinteger(L, 2); + v[1] = (int) luaL_checkinteger(L, 3); + v[2] = (int) luaL_checkinteger(L, 4); + luax_catchexcept(L, [&]() { t->setFilterData(v); }); + return 0; +} + +int w_Shape_getFilterData(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + int v[3]; + luax_catchexcept(L, [&]() { t->getFilterData(v); }); + lua_pushinteger(L, v[0]); + lua_pushinteger(L, v[1]); + lua_pushinteger(L, v[2]); + return 3; +} + +int w_Shape_setCategory(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->setCategory(L); }); + return ret; +} + +int w_Shape_getCategory(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getCategory(L); }); + return ret; +} + +int w_Shape_setMask(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->setMask(L); }); + return ret; +} + +int w_Shape_getMask(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getMask(L); }); + return ret; +} + +int w_Shape_setUserData(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->setUserData(L); }); + return ret; +} + +int w_Shape_getUserData(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getUserData(L); }); + return ret; +} + +int w_Shape_getBoundingBox(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getBoundingBox(L); }); + return ret; +} + +int w_Shape_getMassData(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + lua_remove(L, 1); + int ret = 0; + luax_catchexcept(L, [&]() { ret = t->getMassData(L); }); + return ret; +} + +int w_Shape_getGroupIndex(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + int i = 0; + luax_catchexcept(L, [&]() { i = t->getGroupIndex(); }); + lua_pushinteger(L, i); + return 1; +} + +int w_Shape_setGroupIndex(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + int i = (int) luaL_checkinteger(L, 2); + luax_catchexcept(L, [&]() { t->setGroupIndex(i); }); + return 0; +} + +int w_Shape_destroy(lua_State *L) +{ + Shape *t = luax_checkshape(L, 1); + luax_catchexcept(L, [&](){ t->destroy(); }); + return 0; +} + +int w_Shape_isDestroyed(lua_State *L) +{ + Shape *f = luax_checktype(L, 1); + luax_pushboolean(L, !f->isValid()); + return 1; } const luaL_Reg w_Shape_functions[] = @@ -99,10 +353,33 @@ const luaL_Reg w_Shape_functions[] = { "getType", w_Shape_getType }, { "getRadius", w_Shape_getRadius }, { "getChildCount", w_Shape_getChildCount }, + { "setFriction", w_Shape_setFriction }, + { "setRestitution", w_Shape_setRestitution }, + { "setDensity", w_Shape_setDensity }, + { "setSensor", w_Shape_setSensor }, + { "getFriction", w_Shape_getFriction }, + { "getRestitution", w_Shape_getRestitution }, + { "getDensity", w_Shape_getDensity }, + { "getBody", w_Shape_getBody }, + { "isSensor", w_Shape_isSensor }, { "testPoint", w_Shape_testPoint }, { "rayCast", w_Shape_rayCast }, { "computeAABB", w_Shape_computeAABB }, { "computeMass", w_Shape_computeMass }, + { "setFilterData", w_Shape_setFilterData }, + { "getFilterData", w_Shape_getFilterData }, + { "setCategory", w_Shape_setCategory }, + { "getCategory", w_Shape_getCategory }, + { "setMask", w_Shape_setMask }, + { "getMask", w_Shape_getMask }, + { "setUserData", w_Shape_setUserData }, + { "getUserData", w_Shape_getUserData }, + { "getBoundingBox", w_Shape_getBoundingBox }, + { "getMassData", w_Shape_getMassData }, + { "getGroupIndex", w_Shape_getGroupIndex }, + { "setGroupIndex", w_Shape_setGroupIndex }, + { "destroy", w_Shape_destroy }, + { "isDestroyed", w_Shape_isDestroyed }, { 0, 0 } }; diff --git a/src/modules/physics/box2d/wrap_Shape.h b/src/modules/physics/box2d/wrap_Shape.h index e5cd01cbe..960945c1c 100644 --- a/src/modules/physics/box2d/wrap_Shape.h +++ b/src/modules/physics/box2d/wrap_Shape.h @@ -34,6 +34,7 @@ namespace box2d { Shape *luax_checkshape(lua_State *L, int idx); +void luax_pushshape(lua_State *L, Shape *shape); extern "C" int luaopen_shape(lua_State *L); extern const luaL_Reg w_Shape_functions[]; diff --git a/src/modules/physics/box2d/wrap_World.cpp b/src/modules/physics/box2d/wrap_World.cpp index b80b9ae65..1659374df 100644 --- a/src/modules/physics/box2d/wrap_World.cpp +++ b/src/modules/physics/box2d/wrap_World.cpp @@ -178,25 +178,25 @@ int w_World_getContacts(lua_State *L) return ret; } -int w_World_queryFixturesInArea(lua_State *L) +int w_World_queryShapesInArea(lua_State *L) { World *t = luax_checkworld(L, 1); lua_remove(L, 1); - return t->queryFixturesInArea(L); + return t->queryShapesInArea(L); } int w_World_queryBoundingBox(lua_State *L) { - luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryFixturesInArea"); - return w_World_queryFixturesInArea(L); + luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryShapesInArea"); + return w_World_queryShapesInArea(L); } -int w_World_getFixturesInArea(lua_State *L) +int w_World_getShapesInArea(lua_State *L) { World *t = luax_checkworld(L, 1); lua_remove(L, 1); int ret = 0; - luax_catchexcept(L, [&](){ ret = t->getFixturesInArea(L); }); + luax_catchexcept(L, [&](){ ret = t->getShapesInArea(L); }); return ret; } @@ -260,8 +260,8 @@ static const luaL_Reg w_World_functions[] = { "getBodies", w_World_getBodies }, { "getJoints", w_World_getJoints }, { "getContacts", w_World_getContacts }, - { "queryFixturesInArea", w_World_queryFixturesInArea }, - { "getFixturesInArea", w_World_getFixturesInArea }, + { "queryShapesInArea", w_World_queryShapesInArea }, + { "getShapesInArea", w_World_getShapesInArea }, { "rayCast", w_World_rayCast }, { "rayCastAny", w_World_rayCastAny }, { "rayCastClosest", w_World_rayCastClosest }, From b8e2b1b6c52496eb99d83039fea00eaaf522fd46 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 7 Oct 2023 15:19:49 -0300 Subject: [PATCH 031/409] Update Xcode project to account for removed files --- .../xcode/liblove.xcodeproj/project.pbxproj | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 4aab7711e..605e07e02 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -51,6 +51,9 @@ 217DFC111D9F6D490055D849 /* usocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 217DFBD51D9F6D490055D849 /* usocket.c */; }; 217DFC121D9F6D490055D849 /* usocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 217DFBD61D9F6D490055D849 /* usocket.h */; }; D923E7D3296B85B9002FF1B3 /* harfbuzz.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = D923E7D2296B85B9002FF1B3 /* harfbuzz.xcframework */; }; + D943E58E2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; }; + D943E58F2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; }; + D943E5902A24D56000D80361 /* PhysfsIo.h in Headers */ = {isa = PBXBuildFile; fileRef = D943E58D2A24D56000D80361 /* PhysfsIo.h */; }; D9DAB9222961F0EE00C64820 /* HarfbuzzShaper.h in Headers */ = {isa = PBXBuildFile; fileRef = D9DAB9202961F0EE00C64820 /* HarfbuzzShaper.h */; }; D9DAB9232961F0EE00C64820 /* HarfbuzzShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */; }; D9DAB9242961F0EE00C64820 /* HarfbuzzShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */; }; @@ -61,9 +64,6 @@ D9DAB92D2961F10000C64820 /* TextShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9282961F10000C64820 /* TextShaper.cpp */; }; D9DAB92E2961F10000C64820 /* TextShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9282961F10000C64820 /* TextShaper.cpp */; }; D9DAB9322963CD7500C64820 /* harfbuzz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9DAB9312963CD7500C64820 /* harfbuzz.framework */; }; - D943E58E2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; }; - D943E58F2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; }; - D943E5902A24D56000D80361 /* PhysfsIo.h in Headers */ = {isa = PBXBuildFile; fileRef = D943E58D2A24D56000D80361 /* PhysfsIo.h */; }; FA0A3A5F23366CE9001C269E /* floattypes.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0A3A5D23366CE9001C269E /* floattypes.h */; }; FA0A3A6023366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; }; FA0A3A6123366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; }; @@ -407,9 +407,6 @@ FA0B7E091A95902C000E1D17 /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */; }; FA0B7E0A1A95902C000E1D17 /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */; }; FA0B7E0B1A95902C000E1D17 /* EdgeShape.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */; }; - FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */; }; - FA0B7E0D1A95902C000E1D17 /* Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */; }; - FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2C1A95902C000E1D17 /* Fixture.h */; }; FA0B7E0F1A95902C000E1D17 /* FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */; }; FA0B7E101A95902C000E1D17 /* FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */; }; FA0B7E111A95902C000E1D17 /* FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */; }; @@ -473,9 +470,6 @@ FA0B7E4B1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */; }; FA0B7E4C1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */; }; FA0B7E4D1A95902C000E1D17 /* wrap_EdgeShape.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */; }; - FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */; }; - FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */; }; - FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */; }; FA0B7E511A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */; }; FA0B7E521A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */; }; FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */; }; @@ -1406,6 +1400,8 @@ 217DFBD51D9F6D490055D849 /* usocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usocket.c; sourceTree = ""; }; 217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = ""; }; D923E7D2296B85B9002FF1B3 /* harfbuzz.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = harfbuzz.xcframework; path = ios/libraries/harfbuzz.xcframework; sourceTree = ""; }; + D943E58C2A24D56000D80361 /* PhysfsIo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PhysfsIo.cpp; sourceTree = ""; }; + D943E58D2A24D56000D80361 /* PhysfsIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysfsIo.h; sourceTree = ""; }; D9DAB9202961F0EE00C64820 /* HarfbuzzShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HarfbuzzShaper.h; sourceTree = ""; }; D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HarfbuzzShaper.cpp; sourceTree = ""; }; D9DAB9252961F0FF00C64820 /* GenericShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericShaper.h; sourceTree = ""; }; @@ -1413,8 +1409,6 @@ D9DAB9272961F0FF00C64820 /* TextShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextShaper.h; sourceTree = ""; }; D9DAB9282961F10000C64820 /* TextShaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextShaper.cpp; sourceTree = ""; }; D9DAB9312963CD7500C64820 /* harfbuzz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = harfbuzz.framework; path = macosx/Frameworks/harfbuzz.framework; sourceTree = ""; }; - D943E58C2A24D56000D80361 /* PhysfsIo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PhysfsIo.cpp; sourceTree = ""; }; - D943E58D2A24D56000D80361 /* PhysfsIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysfsIo.h; sourceTree = ""; }; FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = ""; }; FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = ""; }; FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = ""; }; @@ -1652,8 +1646,6 @@ FA0B7C281A95902C000E1D17 /* DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DistanceJoint.h; sourceTree = ""; }; FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeShape.cpp; sourceTree = ""; }; FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdgeShape.h; sourceTree = ""; }; - FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Fixture.cpp; sourceTree = ""; }; - FA0B7C2C1A95902C000E1D17 /* Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fixture.h; sourceTree = ""; }; FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrictionJoint.cpp; sourceTree = ""; }; FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrictionJoint.h; sourceTree = ""; }; FA0B7C2F1A95902C000E1D17 /* GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GearJoint.cpp; sourceTree = ""; }; @@ -1696,8 +1688,6 @@ FA0B7C541A95902C000E1D17 /* wrap_DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DistanceJoint.h; sourceTree = ""; }; FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_EdgeShape.cpp; sourceTree = ""; }; FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_EdgeShape.h; sourceTree = ""; }; - FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Fixture.cpp; sourceTree = ""; }; - FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Fixture.h; sourceTree = ""; }; FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_FrictionJoint.cpp; sourceTree = ""; }; FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_FrictionJoint.h; sourceTree = ""; }; FA0B7C5B1A95902C000E1D17 /* wrap_GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_GearJoint.cpp; sourceTree = ""; }; @@ -3165,8 +3155,6 @@ FA0B7C281A95902C000E1D17 /* DistanceJoint.h */, FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */, FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */, - FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */, - FA0B7C2C1A95902C000E1D17 /* Fixture.h */, FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */, FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */, FA0B7C2F1A95902C000E1D17 /* GearJoint.cpp */, @@ -3209,8 +3197,6 @@ FA0B7C541A95902C000E1D17 /* wrap_DistanceJoint.h */, FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */, FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */, - FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */, - FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */, FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */, FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */, FA0B7C5B1A95902C000E1D17 /* wrap_GearJoint.cpp */, @@ -4272,7 +4258,6 @@ FAFEB29B28F210550025D7D0 /* unixdgram.h in Headers */, FA0B7E051A95902C000E1D17 /* Contact.h in Headers */, FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */, - FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */, FA6A2B661F5F7B6B0074C308 /* wrap_Data.h in Headers */, FA18CEE423DBC6E000263725 /* Graphics.h in Headers */, 217DFBE81D9F6D490055D849 /* inet.h in Headers */, @@ -4467,7 +4452,6 @@ FA4F2B7A1DE0125B00CA37D7 /* xxhash.h in Headers */, FA0B7DDE1A95902C000E1D17 /* wrap_BezierCurve.h in Headers */, FA0B7DED1A95902C000E1D17 /* Cursor.h in Headers */, - FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */, FA28EBD71E352DB5003446F4 /* FenceSync.h in Headers */, FADF542C1E3DAADA00012CC0 /* wrap_Mesh.h in Headers */, FAA3A9B01B7D465A00CED060 /* android.h in Headers */, @@ -4707,7 +4691,6 @@ FA3C5E431F8C368C0003C579 /* ShaderStage.cpp in Sources */, FA0B7E191A95902C000E1D17 /* MotorJoint.cpp in Sources */, FAF1406F1E20934C00F898D2 /* Initialize.cpp in Sources */, - FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */, FA0B7EBF1A95902C000E1D17 /* Thread.cpp in Sources */, FACA02F91F5E39790084B28F /* Compressor.cpp in Sources */, FABDAA002552448300B5C523 /* b2_time_of_impact.cpp in Sources */, @@ -4725,7 +4708,6 @@ FA4F2C111DE936FE00CA37D7 /* unix.c in Sources */, FA1BA0A31E16D97500AA2803 /* wrap_Font.cpp in Sources */, FABDA9842552448200B5C523 /* b2_chain_polygon_contact.cpp in Sources */, - FA0B7E0D1A95902C000E1D17 /* Fixture.cpp in Sources */, FADF53FE1E3D74F200012CC0 /* TextBatch.cpp in Sources */, FA0B7D191A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */, FAC271E723B5B5B400C200D3 /* renderstate.cpp in Sources */, @@ -5140,7 +5122,6 @@ FAF140971E20934C00F898D2 /* PpTokens.cpp in Sources */, FAF140A91E20934C00F898D2 /* SymbolTable.cpp in Sources */, FA0B7E181A95902C000E1D17 /* MotorJoint.cpp in Sources */, - FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */, FA18CEC523D3AE6700263725 /* wrap_Buffer.cpp in Sources */, FAF6C9F423C2DE2900D7B5BC /* Logger.cpp in Sources */, FABDA9FF2552448300B5C523 /* b2_time_of_impact.cpp in Sources */, @@ -5159,7 +5140,6 @@ FABDA9832552448200B5C523 /* b2_chain_polygon_contact.cpp in Sources */, FA0B7AD61A958EA3000E1D17 /* win32.c in Sources */, FADF54341E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */, - FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */, FA0B7D181A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */, FA84DE6627791C36002674C6 /* GraphicsReadback.cpp in Sources */, FA0B7CFA1A95902C000E1D17 /* Filesystem.cpp in Sources */, From a1e4b649ce7c840b0a2d46c2162c0da489b91498 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 7 Oct 2023 15:33:01 -0300 Subject: [PATCH 032/409] Fix compile errors on macOS --- src/modules/physics/box2d/World.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/physics/box2d/World.h b/src/modules/physics/box2d/World.h index 2c7eb78b7..9b8af3b89 100644 --- a/src/modules/physics/box2d/World.h +++ b/src/modules/physics/box2d/World.h @@ -42,6 +42,7 @@ namespace box2d class Contact; class Body; +class Shape; class Joint; /** From de3a0c014205696978f86b15026982c400057962 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 7 Oct 2023 15:33:15 -0300 Subject: [PATCH 033/409] Improve error checking in love.physics.new*Shape --- src/modules/physics/box2d/wrap_Physics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index 917cdf812..d54a65f54 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -275,7 +275,7 @@ int w_newFixture(lua_State *L) static Body *luax_optbodyforshape(lua_State *L, int idx, const char *name) { - if (luax_istype(L, idx, Body::type)) + if (lua_isnoneornil(L, idx) || luax_istype(L, idx, Object::type)) return luax_checkbody(L, idx); luax_markdeprecated(L, 1, name, API_FUNCTION_VARIANT, DEPRECATED_REPLACED, "variant with Body parameter"); From 5b4758819ee5b6094d76e56cd888bcce3a01357c Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 7 Oct 2023 15:35:00 -0300 Subject: [PATCH 034/409] nogame screen uses non-deprecated APIs --- src/scripts/nogame.lua | 10 +++++----- src/scripts/nogame.lua.h | 28 ++++++++++++---------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/scripts/nogame.lua b/src/scripts/nogame.lua index ea66f72af..cc4961499 100644 --- a/src/scripts/nogame.lua +++ b/src/scripts/nogame.lua @@ -2948,9 +2948,8 @@ function love.nogame() self.body = love.physics.newBody(world, x, y, "dynamic") self.body:setLinearDamping(0.8) self.body:setAngularDamping(0.8) - self.shape = love.physics.newPolygonShape(-55, -60, 0, 90, 55, -60) - self.fixture = love.physics.newFixture(self.body, self.shape, 1) - self.fixture:setRestitution(0.5) + self.shape = love.physics.newPolygonShape(self.body, -55, -60, 0, 90, 55, -60) + self.shape:setRestitution(0.5) self.img_normal = img_duckloon_normal self.img_blink = img_duckloon_blink self.img = self.img_normal @@ -3041,8 +3040,9 @@ function love.nogame() link.body = love.physics.newBody(world, link.x, link.y, "dynamic") link.body:setLinearDamping(0.5) link.body:setAngularDamping(0.5) - link.shape = love.physics.newCircleShape(link.radius) - link.fixture = love.physics.newFixture(link.body, link.shape, 0.1 / i) + link.shape = love.physics.newCircleShape(link.body, link.radius) + link.shape:setDensity(0.1 / i) + link.body:resetMassData() link.state = State(link.body) -- Note: every link must also be attached to the Duckloon. Otherwise the diff --git a/src/scripts/nogame.lua.h b/src/scripts/nogame.lua.h index 3bcdeb681..b618cd035 100644 --- a/src/scripts/nogame.lua.h +++ b/src/scripts/nogame.lua.h @@ -27,7 +27,7 @@ const unsigned char nogame_lua[] = 0x2d, 0x2d, 0x5b, 0x5b, 0x0a, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, - 0x2d, 0x32, 0x30, 0x32, 0x31, 0x20, 0x4c, 0x4f, 0x56, 0x45, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x2d, 0x32, 0x30, 0x32, 0x33, 0x20, 0x4c, 0x4f, 0x56, 0x45, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, @@ -11440,14 +11440,11 @@ const unsigned char nogame_lua[] = 0x75, 0x6c, 0x61, 0x72, 0x44, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x2e, 0x38, 0x29, 0x0a, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x50, 0x6f, 0x6c, 0x79, 0x67, - 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x70, 0x65, 0x28, 0x2d, 0x35, 0x35, 0x2c, 0x20, 0x2d, 0x36, 0x30, 0x2c, 0x20, - 0x30, 0x2c, 0x20, 0x39, 0x30, 0x2c, 0x20, 0x35, 0x35, 0x2c, 0x20, 0x2d, 0x36, 0x30, 0x29, 0x0a, - 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x3d, 0x20, 0x6c, - 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x46, 0x69, 0x78, - 0x74, 0x75, 0x72, 0x65, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2c, 0x20, 0x73, 0x65, - 0x6c, 0x66, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x2c, 0x20, 0x31, 0x29, 0x0a, - 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x30, 0x2e, 0x35, 0x29, 0x0a, + 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x70, 0x65, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2c, + 0x20, 0x2d, 0x35, 0x35, 0x2c, 0x20, 0x2d, 0x36, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x39, 0x30, 0x2c, 0x20, + 0x35, 0x35, 0x2c, 0x20, 0x2d, 0x36, 0x30, 0x29, 0x0a, + 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x3a, 0x73, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x30, 0x2e, 0x35, 0x29, 0x0a, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x69, 0x6d, 0x67, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x69, 0x6d, 0x67, 0x5f, 0x64, 0x75, 0x63, 0x6b, 0x6c, 0x6f, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x0a, @@ -11619,13 +11616,12 @@ const unsigned char nogame_lua[] = 0x67, 0x75, 0x6c, 0x61, 0x72, 0x44, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x2e, 0x35, 0x29, 0x0a, 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x43, 0x69, 0x72, 0x63, - 0x6c, 0x65, 0x53, 0x68, 0x61, 0x70, 0x65, 0x28, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x75, - 0x73, 0x29, 0x0a, - 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x69, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x3d, 0x20, - 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x46, 0x69, - 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2c, 0x20, 0x6c, - 0x69, 0x6e, 0x6b, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x2c, 0x20, 0x30, 0x2e, 0x31, 0x20, 0x2f, 0x20, 0x69, - 0x29, 0x0a, + 0x6c, 0x65, 0x53, 0x68, 0x61, 0x70, 0x65, 0x28, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2c, + 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x0a, + 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x3a, 0x73, 0x65, 0x74, 0x44, + 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x28, 0x30, 0x2e, 0x31, 0x20, 0x2f, 0x20, 0x69, 0x29, 0x0a, + 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x72, 0x65, 0x73, 0x65, 0x74, + 0x4d, 0x61, 0x73, 0x73, 0x44, 0x61, 0x74, 0x61, 0x28, 0x29, 0x0a, 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x29, 0x0a, 0x0a, From ff45c308f4881505b21adb5bcaafe45c40b3f76a Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 7 Oct 2023 17:03:40 -0300 Subject: [PATCH 035/409] macOS: increase minimum supported OS from 10.9 to 10.13 The most recent macOS SDK fails to link when the deployment target is set to 10.9. --- platform/xcode/liblove.xcodeproj/project.pbxproj | 6 +++--- platform/xcode/love.xcodeproj/project.pbxproj | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/xcode/liblove.xcodeproj/project.pbxproj b/platform/xcode/liblove.xcodeproj/project.pbxproj index 605e07e02..e591d2743 100644 --- a/platform/xcode/liblove.xcodeproj/project.pbxproj +++ b/platform/xcode/liblove.xcodeproj/project.pbxproj @@ -5511,7 +5511,7 @@ ); IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ""; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = NO; SDKROOT = macosx; USE_HEADERMAP = NO; @@ -5577,7 +5577,7 @@ ); IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ""; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; USE_HEADERMAP = NO; @@ -5716,7 +5716,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LIBRARY_SEARCH_PATHS = ""; LLVM_LTO = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = NO; SDKROOT = macosx; USE_HEADERMAP = NO; diff --git a/platform/xcode/love.xcodeproj/project.pbxproj b/platform/xcode/love.xcodeproj/project.pbxproj index 0d7b4911a..00d46f5b2 100644 --- a/platform/xcode/love.xcodeproj/project.pbxproj +++ b/platform/xcode/love.xcodeproj/project.pbxproj @@ -564,7 +564,7 @@ INFOPLIST_FILE = "love-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = love; SDKROOT = macosx; @@ -640,7 +640,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; LLVM_LTO = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = love; SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES; @@ -874,7 +874,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; LLVM_LTO = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = love; SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES; From 1396e2662631921c46d2a452076a808691e6da9d Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 8 Oct 2023 12:32:10 -0300 Subject: [PATCH 036/409] auto.lua: fix consistency on Windows --- src/scripts/auto.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scripts/auto.lua b/src/scripts/auto.lua index ce59487f6..f9fa450ea 100644 --- a/src/scripts/auto.lua +++ b/src/scripts/auto.lua @@ -77,13 +77,14 @@ local function auto(name) local out_data = "" --go through the input file line-by-line for line in src_file:lines() do + line = line:gsub("\r", "") --if the line is non-empty if #line > 0 then --set the counter to -1 --this will start a new line (see tohex) counter = -1 --append the output to what we had, plus a newline character (0x0a is newline) - out_data = ("%s%s0x0a,"):format(out_data, line:gsub("\r", ""):gsub(".", tohex)) + out_data = ("%s%s0x0a,"):format(out_data, line:gsub(".", tohex)) else out_data = out_data .. "\n\t0x0a," end From 112a09ceb78bdd9eacd69b196a75c22275f7fc26 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 8 Oct 2023 12:43:27 -0300 Subject: [PATCH 037/409] Shape:setDensity no longer needs Body:resetMassData unless the Body already has custom mass data. Add Body:hasCustomMassData. If the Body has custom mass data, attaching a Shape to it doesn't automatically reset its mass data. --- src/modules/physics/box2d/Body.cpp | 5 +++++ src/modules/physics/box2d/Body.h | 4 ++++ src/modules/physics/box2d/Shape.cpp | 11 ++++++++++- src/modules/physics/box2d/wrap_Body.cpp | 8 ++++++++ src/modules/physics/box2d/wrap_Physics.cpp | 6 +----- src/scripts/nogame.lua | 1 - src/scripts/nogame.lua.h | 2 -- 7 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index a3e7ee110..a939de73b 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -39,6 +39,7 @@ namespace box2d Body::Body(World *world, b2Vec2 p, Body::Type type) : world(world) + , hasCustomMass(false) { b2BodyDef def; def.position = Physics::scaleDown(p); @@ -249,6 +250,7 @@ void Body::setLinearDamping(float d) void Body::resetMassData() { body->ResetMassData(); + hasCustomMass = false; } void Body::setMassData(float x, float y, float m, float i) @@ -258,6 +260,7 @@ void Body::setMassData(float x, float y, float m, float i) massData.mass = m; massData.I = Physics::scaleDown(Physics::scaleDown(i)); body->SetMassData(&massData); + hasCustomMass = true; } void Body::setMass(float m) @@ -266,6 +269,7 @@ void Body::setMass(float m) body->GetMassData(&data); data.mass = m; body->SetMassData(&data); + hasCustomMass = true; } void Body::setInertia(float i) @@ -275,6 +279,7 @@ void Body::setInertia(float i) massData.mass = body->GetMass(); massData.I = Physics::scaleDown(Physics::scaleDown(i)); body->SetMassData(&massData); + hasCustomMass = true; } void Body::setGravityScale(float scale) diff --git a/src/modules/physics/box2d/Body.h b/src/modules/physics/box2d/Body.h index 1d0b2d770..1c5ae8a37 100644 --- a/src/modules/physics/box2d/Body.h +++ b/src/modules/physics/box2d/Body.h @@ -137,6 +137,8 @@ public: **/ int getMassData(lua_State *L); + bool hasCustomMassData() const { return hasCustomMass; } + /** * Gets the Body's angular damping. **/ @@ -433,6 +435,8 @@ private: // unowned? World *world; + bool hasCustomMass; + // Reference to arbitrary data. Reference* ref = nullptr; diff --git a/src/modules/physics/box2d/Shape.cpp b/src/modules/physics/box2d/Shape.cpp index c47c4c7ff..b7c0ddece 100644 --- a/src/modules/physics/box2d/Shape.cpp +++ b/src/modules/physics/box2d/Shape.cpp @@ -47,9 +47,16 @@ Shape::Shape(Body *body, const b2Shape &shape) b2FixtureDef def; def.shape = &shape; def.userData.pointer = (uintptr_t)this; - def.density = 1.0f; + + // 0 density stops CreateFixture from calling b2Body::ResetMassData(). + def.density = body->hasCustomMassData() ? 0.0f : 1.0f; + fixture = body->body->CreateFixture(&def); this->shape = fixture->GetShape(); + + if (body->hasCustomMassData()) + setDensity(1.0f); + retain(); // Shape::destroy does the release(). } else @@ -188,6 +195,8 @@ void Shape::setDensity(float density) { throwIfFixtureNotValid(); fixture->SetDensity(density); + if (!body->hasCustomMassData()) + body->resetMassData(); } void Shape::setSensor(bool sensor) diff --git a/src/modules/physics/box2d/wrap_Body.cpp b/src/modules/physics/box2d/wrap_Body.cpp index f0d4dd865..44bda7c0e 100644 --- a/src/modules/physics/box2d/wrap_Body.cpp +++ b/src/modules/physics/box2d/wrap_Body.cpp @@ -162,6 +162,13 @@ int w_Body_getMassData(lua_State *L) return t->getMassData(L); } +int w_Body_hasCustomMassData(lua_State *L) +{ + Body *t = luax_checkbody(L, 1); + luax_pushboolean(L, t->hasCustomMassData()); + return 1; +} + int w_Body_getAngularDamping(lua_State *L) { Body *t = luax_checkbody(L, 1); @@ -688,6 +695,7 @@ static const luaL_Reg w_Body_functions[] = { "getMass", w_Body_getMass }, { "getInertia", w_Body_getInertia }, { "getMassData", w_Body_getMassData }, + { "hasCustomMassData", w_Body_hasCustomMassData }, { "getAngularDamping", w_Body_getAngularDamping }, { "getLinearDamping", w_Body_getLinearDamping }, { "getGravityScale", w_Body_getGravityScale }, diff --git a/src/modules/physics/box2d/wrap_Physics.cpp b/src/modules/physics/box2d/wrap_Physics.cpp index d54a65f54..34dfb81ff 100644 --- a/src/modules/physics/box2d/wrap_Physics.cpp +++ b/src/modules/physics/box2d/wrap_Physics.cpp @@ -262,11 +262,7 @@ int w_newFixture(lua_State *L) float density = (float)luaL_optnumber(L, 3, 1.0f); Shape *newShape; - luax_catchexcept(L, [&]() { - newShape = instance()->newAttachedShape(body, shape, density); - newShape->setDensity(density); - body->resetMassData(); - }); + luax_catchexcept(L, [&]() { newShape = instance()->newAttachedShape(body, shape, density); }); luax_pushshape(L, newShape); newShape->release(); diff --git a/src/scripts/nogame.lua b/src/scripts/nogame.lua index cc4961499..39e473140 100644 --- a/src/scripts/nogame.lua +++ b/src/scripts/nogame.lua @@ -3042,7 +3042,6 @@ function love.nogame() link.body:setAngularDamping(0.5) link.shape = love.physics.newCircleShape(link.body, link.radius) link.shape:setDensity(0.1 / i) - link.body:resetMassData() link.state = State(link.body) -- Note: every link must also be attached to the Duckloon. Otherwise the diff --git a/src/scripts/nogame.lua.h b/src/scripts/nogame.lua.h index b618cd035..b467c5eff 100644 --- a/src/scripts/nogame.lua.h +++ b/src/scripts/nogame.lua.h @@ -11620,8 +11620,6 @@ const unsigned char nogame_lua[] = 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x0a, 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x73, 0x68, 0x61, 0x70, 0x65, 0x3a, 0x73, 0x65, 0x74, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x28, 0x30, 0x2e, 0x31, 0x20, 0x2f, 0x20, 0x69, 0x29, 0x0a, - 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x72, 0x65, 0x73, 0x65, 0x74, - 0x4d, 0x61, 0x73, 0x73, 0x44, 0x61, 0x74, 0x61, 0x28, 0x29, 0x0a, 0x09, 0x09, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x28, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x29, 0x0a, 0x0a, From e1948f6e57376a3566fe4de0564b1ffc3d154886 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Sun, 8 Oct 2023 17:12:07 +0100 Subject: [PATCH 038/409] added all graphics 'state' tests --- .github/workflows/main.yml | 51 +++--- testing/classes/TestMethod.lua | 37 +++- testing/classes/TestSuite.lua | 57 ++++-- testing/conf.lua | 4 +- testing/main.lua | 44 +++-- testing/readme.md | 51 +++--- testing/tests/graphics.lua | 321 ++++++++++++++++++++++++++++++--- testing/tests/system.lua | 4 +- testing/tests/window.lua | 58 +++--- testing/todo.md | 36 +++- 10 files changed, 509 insertions(+), 154 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f8ef7a5dd..9fb1f58bf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,6 +49,16 @@ jobs: with: name: love-x86_64-AppImage-debug path: love-${{ github.sha }}.AppImage-debug.tar.gz + - name: Make Runnable + run: chmod a+x love-linux-x86_64.AppImage + - name: Run All Tests + run: xvfb-run love-linux-x86_64.AppImage testing + - name: Love Test Report + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: linux-test-report + path: testing/output/lovetest_runAllTests.md windows-os: runs-on: windows-latest strategy: @@ -208,25 +218,22 @@ jobs: - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - - name: Run All Tests (OpenGL) + - name: Install Mesa + if: steps.vars.outputs.arch != 'ARM64' + run: | + curl.exe -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z + 7z x mesa.7z + mklink opengl32.dll "x64\opengl32.dll" + mklink libglapi.dll "x64\libglapi.dll" + - name: Run All Tests if: steps.vars.outputs.arch != 'ARM64' run: install\lovec.exe testing/main.lua - - name: Love Test Report (OpenGL) + - name: Love Test Report if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: - name: Love Testsuite Windows (OpenGL) - title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-opengl - path: testing/output/lovetest_runAllTests.md - - name: Run All Tests (Vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: install\lovec.exe testing/main.lua --renderers vulkan - - name: Love Test Report (Vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (Vulkan) - title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report-vulkan + name: Love Testsuite Windows + title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report path: testing/output/lovetest_runAllTests.md macOS: runs-on: macos-latest @@ -256,21 +263,13 @@ jobs: with: name: love-macos path: love-macos.zip - - name: Run All Tests (OpenGL) + - name: Run All Tests run: love-macos/love.app/Contents/MacOS/love testing - - name: Love Test Report (OpenGL) + - name: Love Test Report uses: ellraiser/love-test-report@main with: - name: Love Testsuite MacOS (OpenGL) - title: macos-test-report-opengl - path: testing/output/lovetest_runAllTests.md - - name: Run All Tests (metal) - run: love-macos/love.app/Contents/MacOS/love testing --renderers metal - - name: Love Test Report (metal) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite MacOS (Metal) - title: macos-test-report-metal + name: Love Testsuite MacOS + title: macos-test-report path: testing/output/lovetest_runAllTests.md iOS-Simulator: runs-on: macos-latest diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 6f9b182f9..9b355a6bb 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -25,11 +25,19 @@ TestMethod = { result = {}, colors = { red = {1, 0, 0, 1}, + redpale = {1, 0.5, 0.5, 1}, + red07 = {0.7, 0, 0, 1}, green = {0, 1, 0, 1}, + greenhalf = {0, 0.5, 0, 1}, + greenfade = {0, 1, 0, 0.5}, blue = {0, 0, 1, 1}, + bluefade = {0, 0, 1, 0.5}, + yellow = {1, 1, 0, 1}, black = {0, 0, 0, 1}, white = {1, 1, 1, 1} - } + }, + delay = 0, + delayed = false } setmetatable(test, self) self.__index = self @@ -69,6 +77,11 @@ TestMethod = { local coord = pixels[p] local tr, tg, tb, ta = imgdata:getPixel(coord[1], coord[2]) local compare_id = tostring(coord[1]) .. ',' .. tostring(coord[2]) + -- prevent us getting stuff like 0.501960785 for 0.5 red + tr = math.floor((tr*10)+0.5)/10 + tg = math.floor((tg*10)+0.5)/10 + tb = math.floor((tb*10)+0.5)/10 + ta = math.floor((ta*10)+0.5)/10 -- @TODO add some sort pixel tolerance to the coords self:assertEquals(col[1], tr, 'check pixel r for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') self:assertEquals(col[2], tg, 'check pixel g for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') @@ -201,12 +214,19 @@ TestMethod = { -- @desc - quick assert for value not nil -- @param {any} value - value to check not nil -- @return {nil} - assertNotNil = function (self, value) + assertNotNil = function (self, value, err) self:assertNotEquals(nil, value, 'check not nil') + if err ~= nil then + table.insert(self.asserts, { + key = 'assert #' .. tostring(self.count), + passed = false, + message = err, + test = 'assert not nil catch' + }) + end end, - -- @method - TestMethod:skipTest() -- @desc - used to mark this test as skipped for a specific reason -- @param {string} reason - reason why method is being skipped @@ -217,6 +237,17 @@ TestMethod = { end, + -- currently unused + setDelay = function(self, frames) + self.delay = frames + self.delayed = true + love.test.delayed = self + end, + isDelayed = function(self) + return self.delayed + end, + + -- @method - TestMethod:evaluateTest() -- @desc - evaluates the results of all assertions for a final restult -- @return {nil} diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 0396d841b..92094ae88 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -10,6 +10,7 @@ TestSuite = { -- testsuite internals modules = {}, module = nil, + test = nil, testcanvas = nil, current = 1, output = '', @@ -19,6 +20,7 @@ TestSuite = { html = '', mdrows = '', mdfailures = '', + delayed = nil, fakequit = false, windowmode = true, @@ -70,7 +72,8 @@ TestSuite = { if self.module.called[self.module.index] == nil then self.module.called[self.module.index] = true local method = self.module.running[self.module.index] - local test = TestMethod:new(method, self.module) + self.test = TestMethod:new(method, self.module) + TextRun:set('love.' .. self.module.module .. '.' .. method) -- check method exists in love first if self.module.module ~= 'objects' and (love[self.module.module] == nil or love[self.module.module][method] == nil) then @@ -80,26 +83,52 @@ TestSuite = { tested .. matching, ' ==> FAIL (0/0) - call failed - method does not exist' ) - -- otherwise run the test method then eval the asserts + -- otherwise run the test method else - local ok, chunk, err = pcall(self[self.module.module][method], test) + local ok, chunk, err = pcall(self[self.module.module][method], self.test) if ok == false then print("FATAL", chunk, err) - test.fatal = tostring(chunk) .. tostring(err) - end - local ok, chunk, err = pcall(test.evaluateTest, test) - if ok == false then - print("FATAL", chunk, err) - test.fatal = tostring(chunk) .. tostring(err) + self.test.fatal = tostring(chunk) .. tostring(err) end end - -- save having to :release() anything we made in the last test - -- 7251ms > 7543ms - collectgarbage("collect") - -- move onto the next test - self.module.index = self.module.index + 1 + + -- once we've run check delay + eval + else + + -- @TODO use coroutines? + -- if we have a test method that needs a delay + -- we wait for the delay to run out first + if self.delayed ~= nil then + self.delayed.delay = self.delayed.delay - 1 + -- re-run the test method again when delay ends + -- its up to the test to handle the :isDelayed() property + if self.delayed.delay <= 0 then + local ok, chunk, err = pcall(self[self.module.module][self.delayed.method], self.test) + if ok == false then + print("FATAL", chunk, err) + self.test.fatal = tostring(chunk) .. tostring(err) + end + self.delayed = nil + end + else + + -- now we're all done evaluate the test + local ok, chunk, err = pcall(self.test.evaluateTest, self.test) + if ok == false then + print("FATAL", chunk, err) + self.test.fatal = tostring(chunk) .. tostring(err) + end + -- save having to :release() anything we made in the last test + -- 7251ms > 7543ms + collectgarbage("collect") + -- move onto the next test + self.module.index = self.module.index + 1 + + end + end + -- once all tests have run else -- print module results and add to output diff --git a/testing/conf.lua b/testing/conf.lua index f04c2d90a..a5c0de279 100644 --- a/testing/conf.lua +++ b/testing/conf.lua @@ -1,8 +1,8 @@ function love.conf(t) t.console = true t.window.name = 'love.test' - t.window.width = 256 - t.window.height = 256 + t.window.width = 360 + t.window.height = 240 t.window.resizable = true t.renderers = {"opengl"} t.modules.audio = true diff --git a/testing/main.lua b/testing/main.lua index c90040818..292ad82c6 100644 --- a/testing/main.lua +++ b/testing/main.lua @@ -33,7 +33,7 @@ love.load = function(args) -- setup basic img to display if love.window ~= nil then - love.window.setMode(256, 256, { + love.window.setMode(360, 240, { fullscreen = false, resizable = true, centered = true @@ -47,6 +47,9 @@ love.load = function(args) img = nil } Logo.img = love.graphics.newQuad(0, 0, 64, 64, Logo.texture) + Font = love.graphics.newFont('resources/font.ttf', 8, 'normal') + TextCommand = love.graphics.newTextBatch(Font, 'Loading...') + TextRun = love.graphics.newTextBatch(Font, '') end end @@ -63,6 +66,7 @@ love.load = function(args) local testcmd = '--runAllTests' local module = '' local method = '' + local cmderr = 'Invalid flag used' local modules = { 'audio', 'data', 'event', 'filesystem', 'font', 'graphics', 'image', 'math', 'objects', 'physics', 'sound', 'system', @@ -97,9 +101,14 @@ love.load = function(args) if testcmd == '--runSpecificMethod' then local testmodule = TestModule:new(module, method) table.insert(love.test.modules, testmodule) - love.test.module = testmodule - love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"') - love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method + if module ~= '' and method ~= '' then + love.test.module = testmodule + love.test.module:log('grey', '--runSpecificMethod "' .. module .. '" "' .. method .. '"') + love.test.output = 'lovetest_runSpecificMethod_' .. module .. '_' .. method + else + if method == '' then cmderr = 'No valid method specified' end + if module == '' then cmderr = 'No valid module specified' end + end end -- runSpecificModules runs all methods for all the modules given @@ -110,10 +119,13 @@ love.load = function(args) table.insert(love.test.modules, testmodule) table.insert(modulelist, modules[m]) end - - love.test.module = love.test.modules[1] - love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"') - love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_') + if #modulelist > 0 then + love.test.module = love.test.modules[1] + love.test.module:log('grey', '--runSpecificModules "' .. table.concat(modulelist, '" "') .. '"') + love.test.output = 'lovetest_runSpecificModules_' .. table.concat(modulelist, '_') + else + cmderr = 'No modules specified' + end end -- otherwise default runs all methods for all modules @@ -129,12 +141,14 @@ love.load = function(args) -- invalid command if love.test.module == nil then - print("Wrong flags used") + print(cmderr) + love.event.quit(0) + else + -- start first module + TextCommand:set(testcmd) + love.test.module:runTests() end - -- start first module - love.test.module:runTests() - end -- love.update @@ -147,7 +161,11 @@ end -- love.draw -- draw a little logo to the screen love.draw = function() - love.graphics.draw(Logo.texture, Logo.img, 64, 64, 0, 2, 2) + local lw = (love.graphics.getPixelWidth() - 128) / 2 + local lh = (love.graphics.getPixelHeight() - 128) / 2 + love.graphics.draw(Logo.texture, Logo.img, lw, lh, 0, 2, 2) + love.graphics.draw(TextCommand, 4, 12, 0, 2, 2) + love.graphics.draw(TextRun, 4, 32, 0, 2, 2) end diff --git a/testing/readme.md b/testing/readme.md index a156d2675..32842061b 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -12,6 +12,7 @@ Currently written for löve 12 - [x] No platform-specific dependencies / scripts - [x] Ability to run a subset of tests - [x] Ability to easily run an individual test. +- [x] Automatic testing that happens after every commit --- @@ -81,27 +82,25 @@ For sanity-checking, if it's currently not covered or we're not sure how to test ## Coverage This is the status of all module tests currently. "objects" is a special module to cover any object specific tests, i.e. testing a File object functions as expected -```lua --- [x] audio 26 PASSED | 0 FAILED | 0 SKIPPED --- [x] data 7 PASSED | 0 FAILED | 3 SKIPPED [SEE BELOW] --- [x] event 4 PASSED | 0 FAILED | 2 SKIPPED [SEE BELOW] --- [x] filesystem 27 PASSED | 0 FAILED | 2 SKIPPED --- [x] font 4 PASSED | 0 FAILED | 1 SKIPPED [SEE BELOW] --- [ ] graphics 65 PASSED | 0 FAILED | 31 SKIPPED [SEE BELOW] --- [x] image 3 PASSED | 0 FAILED | 0 SKIPPED --- [x] math 17 PASSED | 0 FAILED | 0 SKIPPED --- [x] physics 22 PASSED | 0 FAILED | 0 SKIPPED --- [x] sound 2 PASSED | 0 FAILED | 0 SKIPPED --- [x] system 6 PASSED | 0 FAILED | 2 SKIPPED --- [x] thread 3 PASSED | 0 FAILED | 0 SKIPPED --- [x] timer 6 PASSED | 0 FAILED | 0 SKIPPED --- [x] video 1 PASSED | 0 FAILED | 0 SKIPPED --- [x] window 32 PASSED | 2 FAILED | 2 SKIPPED [SEE BELOW] - --- [ ] objects STILL TO BE DONE --------------------------------------------------------------------------------- --- [x] totals 226 PASSED | 4 FAILED | 43 SKIPPED -``` +| Module | Passed | Failed | Skipped | Time | +| --------------------- | ------ | ------ | ------- | ------ | +| 🟢 love.audio | 26 | 0 | 0 | 2.602s | +| 🟢 love.data | 7 | 0 | 3 | 1.003s | +| 🟢 love.event | 4 | 0 | 2 | 0.599s | +| 🟢 love.filesystem | 27 | 0 | 2 | 2.900s | +| 🟢 love.font | 4 | 0 | 1 | 0.500s | +| 🟢 love.graphics | 81 | 0 | 15 | 10.678s | +| 🟢 love.image | 3 | 0 | 0 | 0.300s | +| 🟢 love.math | 17 | 0 | 0 | 1.678s | +| 🟢 love.objects | 1 | 0 | 0 | 0.121s | +| 🟢 love.physics | 22 | 0 | 0 | 2.197s | +| 🟢 love.sound | 2 | 0 | 0 | 0.200s | +| 🟢 love.system | 6 | 0 | 2 | 0.802s | +| 🟢 love.thread | 3 | 0 | 0 | 0.300s | +| 🟢 love.timer | 6 | 0 | 0 | 2.358s | +| 🟢 love.video | 1 | 0 | 0 | 0.100s | +| 🟢 love.window | 34 | 0 | 2 | 8.050s | +**271** tests were completed in **34.387s** with **244** passed, **0** failed, and **27** skipped The following modules are not covered as we can't really emulate input nicely: `joystick`, `keyboard`, `mouse`, and `touch` @@ -113,23 +112,17 @@ Modules with some small bits needed or needing sense checking: - **love.data** - packing methods need writing cos i dont really get what they are - **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check - **love.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected -- **love.graphics** - still need to do tests for the drawing and state methods +- **love.graphics** - still need to do tests for the main drawing methods - **love.image** - ideally isCompressed should have an example of all compressed files love can take - **love.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back - **love.objects** - not started properly yet - ---- - -## Failures -- **love.window.isMaximized()** - returns false after calling love.window.maximize? -- **love.window.maximize()** - same as above +- **love.graphics.setStencilTest** - deprecated, replaced by setStencilMode() --- ## Stretch Goals - [ ] Tests can compare visual results to a reference image - [ ] Ability to see all visual results at a glance -- [ ] Automatic testing that happens after every commit - [ ] Ability to test loading different combinations of modules - [ ] Performance tests diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua index 2b8726e5e..5e054d1f3 100644 --- a/testing/tests/graphics.lua +++ b/testing/tests/graphics.lua @@ -112,11 +112,10 @@ love.test.graphics.rectangle = function(test) love.graphics.setCanvas() local imgdata1 = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) -- test, check red bg and blue central square - local comparepixels = { + test:assertPixels(imgdata1, { red = {{0,0},{15,0},{15,15},{0,15}}, blue = {{6,6},{9,6},{9,9},{6,9}} - } - test:assertPixels(imgdata1, comparepixels, 'fill') + }, 'fill') -- clear canvas to do some line testing love.graphics.setCanvas(canvas) love.graphics.clear(0, 0, 0, 1) @@ -126,16 +125,19 @@ love.test.graphics.rectangle = function(test) love.graphics.rectangle('line', 1, 1, 2, 15) -- 3x16 left aligned blue outline love.graphics.setColor(0, 1, 0, 1) love.graphics.rectangle('line', 11, 1, 5, 15) -- 6x16 right aligned green outline + love.graphics.setColor(1, 1, 1, 1) love.graphics.setCanvas() local imgdata2 = love.graphics.readbackTexture(canvas, {1, 1, 0, 0, 16, 16}) -- -- check corners and inner corners - comparepixels = { + test:assertPixels(imgdata2, { red = {{3,0},{9,0},{3,15,9,15}}, blue = {{0,0},{2,0},{0,15},{2,15}}, green = {{10,0},{15,0},{10,15},{15,15}}, - black = {{1,1},{1,14},{3,1},{9,1},{3,14},{9,14},{11,1},{14,1},{11,14},{14,14}} - } - test:assertPixels(imgdata2, comparepixels, 'line') + black = { + {1,1},{1,14},{3,1},{9,1},{3,14}, + {9,14},{11,1},{14,1},{11,14},{14,14} + } + }, 'line') end @@ -147,10 +149,15 @@ end -- love.graphics.captureScreenshot --- @NOTE could test this but not with current setup as we need to wait for the --- draw frame to finish before we could assert the file was created love.test.graphics.captureScreenshot = function(test) - test:skipTest('cant test this worked (easily)') + if test:isDelayed() == false then + love.graphics.captureScreenshot('example-screenshot.png') + test:setDelay(10) + -- need to wait until end of the frame for the screenshot + else + test:assertNotNil(love.filesystem.openFile('example-screenshot.png', 'r')) + love.filesystem.remove('example-screenshot.png') + end end @@ -611,34 +618,117 @@ love.test.graphics.setBackgroundColor = function(test) test:assertEquals(0, g, 'check set bg g') test:assertEquals(0, b, 'check set bg b') test:assertEquals(1, a, 'check set bg a') + love.graphics.setBackgroundColor(0, 0, 0, 1) end -- love.graphics.setBlendMode love.test.graphics.setBlendMode = function(test) - -- set mode, write to canvas, check output - test:skipTest('test method needs writing') + -- create fully white canvas, then draw diff. pixels through blendmodes + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0.5, 0.5, 0.5, 1) + love.graphics.setBlendMode('add', 'alphamultiply') + love.graphics.setColor(1, 0, 0, 1) + love.graphics.points({1,1}) + love.graphics.setBlendMode('subtract', 'alphamultiply') + love.graphics.setColor(1, 1, 1, 0.5) + love.graphics.points({16,1}) + love.graphics.setBlendMode('multiply', 'premultiplied') + love.graphics.setColor(0, 1, 0, 1) + love.graphics.points({16,16}) + love.graphics.setBlendMode('replace', 'premultiplied') + love.graphics.setColor(0, 0, 1, 0.5) + love.graphics.points({1,16}) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + -- check the 4 corners + test:assertPixels(imgdata, { + redpale = {{0,0}}, + black = {{15,0}}, + greenhalf = {{15,15}}, + bluefade = {{0,15}} + }, 'blend mode') + love.graphics.setBlendMode('alpha', 'alphamultiply') -- reset end -- love.graphics.setCanvas love.test.graphics.setCanvas = function(test) -- make 2 canvas, set to each, draw one to the other, check output - test:skipTest('test method needs writing') + local canvas1 = love.graphics.newCanvas(16, 16) + local canvas2 = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas1) + test:assertEquals(canvas1, love.graphics.getCanvas(), 'check canvas 1 set') + love.graphics.clear(1, 0, 0, 1) + love.graphics.setCanvas(canvas2) + test:assertEquals(canvas2, love.graphics.getCanvas(), 'check canvas 2 set') + love.graphics.clear(0, 0, 0, 1) + love.graphics.draw(canvas1, 0, 0) + love.graphics.setCanvas() + test:assertEquals(nil, love.graphics.getCanvas(), 'check no canvas set') + local imgdata = love.graphics.readbackTexture(canvas2, {16, 0, 0, 0, 16, 16}) + -- check 2nd canvas is red + test:assertPixels(imgdata, { + red = {{0,0},{15,0},{15,15},{0,15}} + }, 'set canvas') end -- love.graphics.setColor love.test.graphics.setColor = function(test) -- set colors, draw rect, check color - test:skipTest('test method needs writing') + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(1, 0, 0, 1) + local r, g, b, a = love.graphics.getColor() + test:assertEquals(1, r, 'check r set') + test:assertEquals(0, g, 'check g set') + test:assertEquals(0, b, 'check b set') + test:assertEquals(1, a, 'check a set') + love.graphics.points({{1,1},{6,1},{11,1},{16,1}}) + love.graphics.setColor(1, 1, 0, 1) + love.graphics.points({{1,2},{6,2},{11,2},{16,2}}) + love.graphics.setColor(0, 1, 0, 0.5) + love.graphics.points({{1,3},{6,3},{11,3},{16,3}}) + love.graphics.setColor(0, 0, 1, 1) + love.graphics.points({{1,4},{6,4},{11,4},{16,4}}) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + red = {{0,0},{5,0},{10,0},{15,0}}, + yellow = {{0,1},{5,1},{10,1},{15,1}}, + greenhalf = {{0,2},{5,2},{10,2},{15,2}}, + blue = {{0,3},{5,3},{10,3},{15,3}} + }, 'set color') end -- love.graphics.setColorMask love.test.graphics.setColorMask = function(test) -- set mask, draw stuff, check output pixels - test:skipTest('test method needs writing') + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + -- mask off blue + love.graphics.setColorMask(true, true, false, true) + local r, g, b, a = love.graphics.getColorMask() + test:assertEquals(r, true, 'check r mask') + test:assertEquals(g, true, 'check g mask') + test:assertEquals(b, false, 'check b mask') + test:assertEquals(a, true, 'check a mask') + -- draw "black" which should then turn to yellow + love.graphics.setColor(1, 1, 1, 1) + love.graphics.rectangle('fill', 0, 0, 16, 16) + love.graphics.setColorMask(true, true, true, true) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + yellow = {{0,0},{0,15},{15,15},{15,0}} + }, 'set color mask') end @@ -656,67 +746,243 @@ end -- love.graphics.setDepthMode love.test.graphics.setDepthMode = function(test) - test:skipTest('test method needs writing') + -- check documented modes are valid + local comparemode, write = love.graphics.getDepthMode() + local modes = { + 'equal', 'notequal', 'less', 'lequal', 'gequal', + 'greater', 'never', 'always' + } + for m=1,#modes do + love.graphics.setDepthMode(modes[m], true) + test:assertEquals(modes[m], love.graphics.getDepthMode(), 'check depth mode ' .. modes[m] .. ' set') + end + love.graphics.setDepthMode(comparemode, write) + -- @TODO better graphics drawing specific test end -- love.graphics.setFont love.test.graphics.setFont = function(test) - test:skipTest('test method needs writing') + -- set font doesnt return anything so draw with the test font + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setFont(Font) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(1, 0, 0, 1) + love.graphics.print('love', 0, 3) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + red = { + {0,0},{0,6},{2,6},{6,2}, + {4,4},{8,4},{6,6},{10,2}, + {14,2},{12,6} + } + }, 'set font for print') end -- love.graphics.setFrontFaceWinding love.test.graphics.setFrontFaceWinding = function(test) - test:skipTest('test method needs writing') + -- check documented modes are valid + local original = love.graphics.getFrontFaceWinding() + love.graphics.setFrontFaceWinding('cw') + test:assertEquals('cw', love.graphics.getFrontFaceWinding(), 'check ffw cw set') + love.graphics.setFrontFaceWinding('ccw') + test:assertEquals('ccw', love.graphics.getFrontFaceWinding(), 'check ffw ccw set') + love.graphics.setFrontFaceWinding(original) + -- @TODO better graphics drawing specific test end -- love.graphics.setLineJoin love.test.graphics.setLineJoin = function(test) - test:skipTest('test method needs writing') + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setFont(Font) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + local line = {0,1,8,1,8,8} + love.graphics.setLineStyle('rough') + love.graphics.setLineWidth(2) + love.graphics.setColor(1, 0, 0) + love.graphics.setLineJoin('bevel') + love.graphics.line(line) + love.graphics.translate(0, 4) + love.graphics.setColor(1, 1, 0) + love.graphics.setLineJoin('none') + love.graphics.line(line) + love.graphics.translate(0, 4) + love.graphics.setColor(0, 0, 1) + love.graphics.setLineJoin('miter') + love.graphics.line(line) + love.graphics.setColor(1, 1, 1) + love.graphics.setLineWidth(1) + love.graphics.origin() + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + black = {{8,0}}, + red = {{8,4}}, + yellow = {{8,7}}, + blue = {{8,8}} + }, 'set line join') end -- love.graphics.setLineStyle love.test.graphics.setLineStyle = function(test) - test:skipTest('test method needs writing') + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setFont(Font) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(1, 0, 0) + local line = {0,1,16,1} + love.graphics.setLineStyle('rough') + love.graphics.line(line) + love.graphics.translate(0, 4) + love.graphics.setLineStyle('smooth') + love.graphics.line(line) + love.graphics.setLineStyle('rough') + love.graphics.setColor(1, 1, 1) + love.graphics.origin() + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + red = {{0,0},{7,0},{15,0}}, + red07 = {{0,4},{7,4},{15,4}} + }, 'set line style') end -- love.graphics.setLineWidth love.test.graphics.setLineWidth = function(test) - test:skipTest('test method needs writing') + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setFont(Font) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + local line = {0,1,8,1,8,8} + love.graphics.setColor(1, 0, 0) + love.graphics.setLineWidth(2) + love.graphics.line(line) + love.graphics.translate(0, 4) + love.graphics.setColor(1, 1, 0) + love.graphics.setLineWidth(3) + love.graphics.line(line) + love.graphics.translate(0, 4) + love.graphics.setColor(0, 0, 1) + love.graphics.setLineWidth(4) + love.graphics.line(line) + love.graphics.setColor(1, 1, 1) + love.graphics.setLineWidth(1) + love.graphics.origin() + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + black = {{0,2},{6,2},{0,6},{5,6},{0,11},{5,11}}, + red = {{0,0},{0,1},{7,2},{8,2}}, + yellow = {{0,3},{0,5},{6,6},{8,6}}, + blue = {{0,7},{0,10},{6,15},{9,15}} + }, 'set line width') end -- love.graphics.setMeshCullMode love.test.graphics.setMeshCullMode = function(test) - test:skipTest('test method needs writing') + -- check documented modes are valid + local original = love.graphics.getMeshCullMode() + local modes = {'back', 'front', 'none'} + for m=1,#modes do + love.graphics.setMeshCullMode(modes[m]) + test:assertEquals(modes[m], love.graphics.getMeshCullMode(), 'check mesh cull mode ' .. modes[m] .. ' was set') + end + love.graphics.setMeshCullMode(original) + -- @TODO better graphics drawing specific test end -- love.graphics.setScissor love.test.graphics.setScissor = function(test) - test:skipTest('test method needs writing') + -- make a scissor for the left half + -- then we should be able to fill the canvas with red and only left is filled + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.origin() + love.graphics.setScissor(0, 0, 8, 16) + love.graphics.clear(1, 0, 0, 1) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setScissor() + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + red = {{0,0},{7,0},{0,15},{7,15}}, + black ={{8,0},{8,15},{15,0},{15,15}} + }, 'set scissor') end -- love.graphics.setShader love.test.graphics.setShader = function(test) - test:skipTest('test method needs writing') + -- make a shader that will only ever draw yellow + local pixelcode = 'vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex, texture_coords); return vec4(1.0,1.0,0.0,1.0);}' + local vertexcode = 'vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform_projection * vertex_position; }' + local shader = love.graphics.newShader(pixelcode, vertexcode) + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setShader(shader) + -- draw red rectangle + love.graphics.setColor(1, 0, 0, 1) + love.graphics.rectangle('fill', 0, 0, 16, 16) + love.graphics.setShader() + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + yellow = {{0,0},{15,0},{0,15},{15,15}}, + }, 'check shader set to yellow') end -- love.graphics.setStencilTest -love.test.graphics.setStencilMode = function(test) - test:skipTest('test method needs writing') +love.test.graphics.setStencilTest = function(test) + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas({canvas, stencil=true}) + love.graphics.clear(0, 0, 0, 1) + love.graphics.stencil(function() + love.graphics.circle('fill', 8, 8, 6) + end, 'replace', 1) + love.graphics.setStencilTest('greater', 0) + love.graphics.setColor(1, 0, 0, 1) + love.graphics.rectangle('fill', 0, 0, 16, 16) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setStencilTest() + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + red = {{6,2},{9,2},{2,6},{2,9},{13,6},{9,6},{6,13},{9,13}} + }, 'check stencil test') end -- love.graphics.setWireframe love.test.graphics.setWireframe = function(test) - test:skipTest('test method needs writing') + -- check wireframe outlines + love.graphics.setWireframe(true) + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(1, 1, 0, 1) + love.graphics.rectangle('fill', 2, 2, 13, 13) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setWireframe(false) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + yellow = {{1,14},{14,1},{14,14},{2,2},{13,13}}, + black = {{2,13},{13,2}} + }, 'set wireframe') end @@ -860,7 +1126,6 @@ love.test.graphics.rotate = function(test) love.graphics.setCanvas() local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) test:assertPixels(imgdata, { red = {{0,0},{3,0},{3,3},{0,3}} }, 'rotate 90') - imgdata:encode('png', 'rotate.png') end diff --git a/testing/tests/system.lua b/testing/tests/system.lua index 89b8eb400..432352ec5 100644 --- a/testing/tests/system.lua +++ b/testing/tests/system.lua @@ -30,10 +30,10 @@ love.test.system.getPowerInfo = function(test) test:assertMatch(states, state, 'check value matches') -- if percent/seconds check within expected range if percent ~= nil then - test:assertRange(percent, 0, 100, 'check value within range') + test:assertRange(percent, 0, 100, 'check battery percent within range') end if seconds ~= nil then - test:assertRange(seconds, 0, 100, 'check value within range') + test:assertNotNil(seconds) end end diff --git a/testing/tests/window.lua b/testing/tests/window.lua index bb656dea8..ae2cfdb9e 100644 --- a/testing/tests/window.lua +++ b/testing/tests/window.lua @@ -5,15 +5,13 @@ love.test.window.close = function(test) -- closing window should cause graphics to not be active love.window.close() - local active = false - if love.graphics ~= nil then - active = love.graphics.isActive() - end - test:assertEquals(false, active, 'check window active') - love.window.setMode(256, 256) -- reset + local active = love.graphics.isActive() + test:assertEquals(false, active, 'check window not active') + love.window.updateMode(360, 240) -- reset + active = love.graphics.isActive() + test:assertEquals(true, active, 'check window active again') end - -- love.window.fromPixels love.test.window.fromPixels = function(test) -- check dpi/pixel ratio as expected @@ -93,8 +91,8 @@ end -- @NOTE could prob add more checks on the flags here based on conf.lua love.test.window.getMode = function(test) local w, h, flags = love.window.getMode() - test:assertEquals(256, w, 'check w') - test:assertEquals(256, h, 'check h') + test:assertEquals(360, w, 'check w') + test:assertEquals(240, h, 'check h') test:assertEquals(false, flags["fullscreen"], 'check fullscreen') end @@ -169,13 +167,14 @@ end -- love.window.isMaximized love.test.window.isMaximized = function(test) - -- check minimized to start - love.window.minimize() - test:assertEquals(false, love.window.isMaximized(), 'check window maximized') - -- try to mazimize - love.window.maximize() - test:assertEquals(true, love.window.isMaximized(), 'check window not maximized') - love.window.restore() + if test:isDelayed() == false then + love.window.maximize() + test:setDelay(10) + else + -- on MACOS maximize wont get recognised immedietely so wait a few frames + test:assertEquals(true, love.window.isMaximized(), 'check window now maximized') + love.window.restore() + end end @@ -197,7 +196,7 @@ love.test.window.isOpen = function(test) -- try closing love.window.close() test:assertEquals(false, love.window.isOpen(), 'check window closed') - love.window.setMode(256, 256) -- reset + love.window.updateMode(360, 240) -- reset end @@ -208,16 +207,21 @@ love.test.window.isVisible = function(test) -- check closing makes window not visible love.window.close() test:assertEquals(false, love.window.isVisible(), 'check window not visible') - love.window.setMode(256, 256) -- reset + love.window.updateMode(360, 240) -- reset end -- love.window.maximize love.test.window.maximize = function(test) - -- check maximizing is set - love.window.maximize() - test:assertEquals(true, love.window.isMaximized(), 'check window maximized') - love.window.restore() + if test:isDelayed() == false then + -- check maximizing is set + love.window.maximize() + test:setDelay(10) + else + -- on macos we need to wait a few frames + test:assertEquals(true, love.window.isMaximized(), 'check window maximized') + love.window.restore() + end end @@ -293,7 +297,7 @@ love.test.window.setMode = function(test) test:assertEquals(512, height, 'check window h match') test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen') test:assertEquals(false, flags["resizable"], 'check window not resizeable') - love.window.setMode(256, 256, { + love.window.setMode(360, 240, { fullscreen = false, resizable = true }) @@ -353,14 +357,14 @@ love.test.window.updateMode = function(test) resizable = false }) -- update mode with some props but not others - love.window.updateMode(256, 256, nil) + love.window.updateMode(360, 240, nil) -- check only changed values changed local width, height, flags = love.window.getMode() - test:assertEquals(256, width, 'check window w match') - test:assertEquals(256, height, 'check window h match') + test:assertEquals(360, width, 'check window w match') + test:assertEquals(240, height, 'check window h match') test:assertEquals(false, flags["fullscreen"], 'check window not fullscreen') test:assertEquals(false, flags["resizable"], 'check window not resizeable') - love.window.setMode(256, 256, { -- reset + love.window.setMode(360, 240, { -- reset fullscreen = false, resizable = true }) diff --git a/testing/todo.md b/testing/todo.md index 480c19e7a..37eac6bb7 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -1,18 +1,34 @@ `/Applications/love_12.app/Contents/MacOS/love ./testing` -## CI -- [ ] ignore test suite for windows AMD -- [ ] add test run to linux (opengl+vulkan) + ios builds (opengl+metal) - ## TESTSUITE -- [ ] finish graphics state methods +- [ ] setStencilMode to replace setStencilTest - [ ] start graphics drawing methods - [ ] start object methods +## GRAPHICS +Methods that need a better actual graphics check if possible: +- [ ] setDepthMode +- [ ] setFrontFaceWinding +- [ ] setMeshCullMode + ## FUTURE -- [ ] pass in err string returns to the test output - maybe even assertNotNil could use the second value automatically - test:assertNotNil(love.filesystem.openFile('file2', 'r')) wouldn't have to change -- [ ] some joystick/input stuff could be at least nil checked maybe? - [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) - could add platform as global to command and then use in tests? \ No newline at end of file + could add platform as global to command and then use in tests? +- [ ] use coroutines for the delay action? i.e. wrap each test call in coroutine + and then every test can use coroutine.yield() if needed +- [ ] could nil check some joystick and keyboard methods? + +## GITHUB ACTION CI +- [ ] linux needs to run xvfb-run with the appimage +- [ ] windows can try installing mesa for opengl replacement +- [ ] ios test run? + +Can't run --renderers metal on github action images: +Run love-macos/love.app/Contents/MacOS/love testing --renderers metal +Cannot create Metal renderer: Metal is not supported on this system. +Cannot create graphics: no supported renderer on this system. +Error: Cannot create graphics: no supported renderer on this system. + +Can't run test suite on windows as it stands: +Unable to create renderer +This program requires a graphics card and video drivers which support OpenGL 2.1 or OpenGL ES 2. From 27c45696972869c8d6fbe2b9bd315f50a35aee6a Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 8 Oct 2023 14:06:55 -0300 Subject: [PATCH 039/409] love.physics: clean up some internal collision processing code --- src/modules/physics/box2d/World.cpp | 30 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/modules/physics/box2d/World.cpp b/src/modules/physics/box2d/World.cpp index b90c4a3c7..1ec53926e 100644 --- a/src/modules/physics/box2d/World.cpp +++ b/src/modules/physics/box2d/World.cpp @@ -114,22 +114,6 @@ World::ContactFilter::~ContactFilter() bool World::ContactFilter::process(Shape *a, Shape *b) { - // Handle masks, reimplemented from the manual - int filterA[3], filterB[3]; - // [0] categoryBits - // [1] maskBits - // [2] groupIndex - a->getFilterData(filterA); - b->getFilterData(filterB); - - if (filterA[2] != 0 && // 0 is the default group, so this does not count - filterA[2] == filterB[2]) // if they are in the same group - return filterA[2] > 0; // Negative indexes mean you don't collide - - if ((filterA[1] & filterB[0]) == 0 || - (filterB[1] & filterA[0]) == 0) - return false; // A and B aren't set to collide - if (ref != nullptr && L != nullptr) { ref->push(L); @@ -138,6 +122,7 @@ bool World::ContactFilter::process(Shape *a, Shape *b) lua_call(L, 2, 1); return luax_toboolean(L, -1); } + return true; } @@ -384,11 +369,24 @@ void World::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse) bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB) { + const b2Filter &filterA = fixtureA->GetFilterData(); + const b2Filter &filterB = fixtureB->GetFilterData(); + + // From b2_world_callbacks.cpp + // 0 is the default group index. If they're customized to be the same group, + // allow collisions if it's positive and disallow if it's negative. + if (filterA.groupIndex != 0 && filterA.groupIndex == filterB.groupIndex) + return filterA.groupIndex > 0; + + if ((filterA.maskBits & filterB.categoryBits) == 0 || (filterA.categoryBits & filterB.maskBits) == 0) + return false; + // Shapes should be memoized, if we created them Shape *a = (Shape *)(fixtureA->GetUserData().pointer); Shape *b = (Shape *)(fixtureB->GetUserData().pointer); if (!a || !b) throw love::Exception("A Shape has escaped Memoizer!"); + return filter.process(a, b); } From c7c8f25284a3d99b10276fd0ce16dbcb501c985b Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Sun, 8 Oct 2023 18:25:00 +0100 Subject: [PATCH 040/409] added objects module placeholders --- .github/workflows/main.yml | 14 +- testing/tests/data.lua | 6 +- testing/tests/event.lua | 2 +- testing/tests/graphics.lua | 30 +-- testing/tests/objects.lua | 366 ++++++++++++++++++++++++++++++------- 5 files changed, 326 insertions(+), 92 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9fb1f58bf..4dbfab58d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -50,9 +50,9 @@ jobs: name: love-x86_64-AppImage-debug path: love-${{ github.sha }}.AppImage-debug.tar.gz - name: Make Runnable - run: chmod a+x love-linux-x86_64.AppImage + run: chmod a+x love-${{ github.sha }}.AppImage - name: Run All Tests - run: xvfb-run love-linux-x86_64.AppImage testing + run: xvfb-run love-${{ github.sha }}.AppImage testing - name: Love Test Report uses: ellraiser/love-test-report@main with: @@ -218,13 +218,11 @@ jobs: - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - - name: Install Mesa + - name: Install Mesa if: steps.vars.outputs.arch != 'ARM64' - run: | - curl.exe -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z - 7z x mesa.7z - mklink opengl32.dll "x64\opengl32.dll" - mklink libglapi.dll "x64\libglapi.dll" + uses: ssciwr/setup-mesa-dist-win@v1 + with: + version: '23.2.1' - name: Run All Tests if: steps.vars.outputs.arch != 'ARM64' run: install\lovec.exe testing/main.lua diff --git a/testing/tests/data.lua b/testing/tests/data.lua index 76abdf5c7..dac5f3c06 100644 --- a/testing/tests/data.lua +++ b/testing/tests/data.lua @@ -121,7 +121,7 @@ end -- love.data.getPackedSize -- @NOTE I don't really get what lua packing types are so skipping for now - ell love.test.data.getPackedSize = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end @@ -161,12 +161,12 @@ end -- love.data.pack -- @NOTE I don't really get what lua packing types are so skipping for now - ell love.test.data.pack = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.data.unpack -- @NOTE I don't really get what lua packing types are so skipping for now - ell love.test.data.unpack = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end diff --git a/testing/tests/event.lua b/testing/tests/event.lua index 56650250f..ff667c394 100644 --- a/testing/tests/event.lua +++ b/testing/tests/event.lua @@ -69,5 +69,5 @@ end -- love.event.wait -- @NOTE not sure best way to test this one love.test.event.wait = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua index 5e054d1f3..8ace6eaea 100644 --- a/testing/tests/graphics.lua +++ b/testing/tests/graphics.lua @@ -10,91 +10,91 @@ -- love.graphics.arc love.test.graphics.arc = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.circle love.test.graphics.circle = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.clear love.test.graphics.clear = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.discard love.test.graphics.discard = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.draw love.test.graphics.draw = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.drawInstanced love.test.graphics.drawInstanced = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.drawLayer love.test.graphics.drawLayer = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.ellipse love.test.graphics.ellipse = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.flushBatch love.test.graphics.flushBatch = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.line love.test.graphics.line = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.points love.test.graphics.points = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.polygon love.test.graphics.polygon = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.present love.test.graphics.present = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.print love.test.graphics.print = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end -- love.graphics.printf love.test.graphics.printf = function(test) - test:skipTest('test method needs writing') + test:skipTest('test class needs writing') end diff --git a/testing/tests/objects.lua b/testing/tests/objects.lua index 6ccd9dae0..2a03544b8 100644 --- a/testing/tests/objects.lua +++ b/testing/tests/objects.lua @@ -1,6 +1,93 @@ -- objects put in their own test methods to test all attributes and class methods +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------AUDIO--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- RecordingDevice (love.audio.getRecordingDevices) +love.test.objects.RecordingDevice = function(test) + test:skipTest('test class needs writing') +end + + +-- Source (love.audio.newSource) +love.test.objects.Source = function(test) + test:skipTest('test class needs writing') + -- local source1 = love.audio.newSource('resources/click.ogg', 'static') + --source1:clone() + --source1:getChannelCount() + --source1:getDuration() + --source1:isRelative() + --source1:queue() + --source1:getFreeBufferCount() + --source1:getType() + --source1:isPlaying() + --source1:play() + --source1:pause() + --source1:stop() + --source1:seek() + --source1:tell() + --source1:isLooping() + --source1:setLooping() + --source1:setAirAbsorption() + --source1:getAirAbsorption() + --source1:setAttenuationDistances() + --source1:getAttenuationDistances() + --source1:setCone() + --source1:getCone() + --source1:setDirection() + --source1:getDirection() + --source1:setEffect() + --source1:getEffect() + --source1:getActiveEffects() + --source1:setFilter() + --source1:getFilter() + --source1:setPitch() + --source1:getPitch() + --source1:setPosition() + --source1:getPosition() + --source1:setRelative() + --source1:setRolloff() + --source1:getRolloff() + --source1:setVelocity() + --source1:getVelocity() + --source1:setVolume() + --source1:getVolume() + --source1:setVolumeLimits() + --source1:getVolumeLimits() +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------DATA---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- ByteData (love.data.newByteData) +love.test.objects.ByteData = function(test) + test:skipTest('test class needs writing') +end + + +-- CompressedData (love.data.compress) +love.test.objects.CompressedData = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +---------------------------------FILESYSTEM------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- File (love.filesystem.newFile) love.test.objects.File = function(test) @@ -88,88 +175,237 @@ love.test.objects.File = function(test) end --- Source (love.audio.newSource) --- love.test.objects.Source = function(test) - -- local source1 = love.audio.newSource('resources/click.ogg', 'static') - --source1:clone() - --source1:getChannelCount() - --source1:getDuration() - --source1:isRelative() - --source1:queue() - --source1:getFreeBufferCount() - --source1:getType() - --source1:isPlaying() - --source1:play() - --source1:pause() - --source1:stop() - --source1:seek() - --source1:tell() - --source1:isLooping() - --source1:setLooping() - --source1:setAirAbsorption() - --source1:getAirAbsorption() - --source1:setAttenuationDistances() - --source1:getAttenuationDistances() - --source1:setCone() - --source1:getCone() - --source1:setDirection() - --source1:getDirection() - --source1:setEffect() - --source1:getEffect() - --source1:getActiveEffects() - --source1:setFilter() - --source1:getFilter() - --source1:setPitch() - --source1:getPitch() - --source1:setPosition() - --source1:getPosition() - --source1:setRelative() - --source1:setRolloff() - --source1:getRolloff() - --source1:setVelocity() - --source1:getVelocity() - --source1:setVolume() - --source1:getVolume() - --source1:setVolumeLimits() - --source1:getVolumeLimits() --- end - -- FileData (love.filesystem.newFileData) +love.test.objects.FileData = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------FONT---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- --- ByteData (love.data.newByteData) --- DataView (love.data.newDataView) --- FontData (love.font.newFontData) -- GlyphData (love.font.newGlyphData) +love.test.objects.GlyphData = function(test) + test:skipTest('test class needs writing') +end + + -- Rasterizer (love.font.newRasterizer) +love.test.objects.Rasterizer = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +---------------------------------GRAPHICS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- Canvas (love.graphics.newCanvas) +love.test.objects.Canvas = function(test) + test:skipTest('test class needs writing') +end + + +-- Font (love.graphics.newFont) +love.test.objects.Font = function(test) + test:skipTest('test class needs writing') +end + + +-- Image (love.graphics.newImage) +love.test.objects.Image = function(test) + test:skipTest('test class needs writing') +end + + +-- Mesh (love.graphics.newMesh) +love.test.objects.Mesh = function(test) + test:skipTest('test class needs writing') +end + + +-- ParticleSystem (love.graphics.newParticleSystem) +love.test.objects.ParticleSystem = function(test) + test:skipTest('test class needs writing') +end + + +-- Quad (love.graphics.newQuad) +love.test.objects.Quad = function(test) + test:skipTest('test class needs writing') +end + + +-- Shader (love.graphics.newShader) +love.test.objects.Shader = function(test) + test:skipTest('test class needs writing') +end + + +-- SpriteBatch (love.graphics.newSpriteBatch) +love.test.objects.SpriteBatch = function(test) + test:skipTest('test class needs writing') +end + + +-- Text (love.graphics.newTextBatch) +love.test.objects.Text = function(test) + test:skipTest('test class needs writing') +end + + +-- Texture (love.graphics.newTexture) +love.test.objects.Texture = function(test) + test:skipTest('test class needs writing') +end + + +-- Video (love.graphics.newVideo) +love.test.objects.Video = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-----------------------------------IMAGE---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + -- CompressedImageData (love.image.newCompressedImageData) +love.test.objects.CompressedImageData = function(test) + test:skipTest('test class needs writing') +end + + -- ImageData (love.image.newImageData) +love.test.objects.ImageData = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------MATH---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + -- BezierCurve (love.math.newBezierCurve) +love.test.objects.BezierCurve = function(test) + test:skipTest('test class needs writing') +end + + -- RandomGenerator (love.math.RandomGenerator) +love.test.objects.RandomGenerator = function(test) + test:skipTest('test class needs writing') +end + + -- Transform (love.math.Transform) +love.test.objects.Transform = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------PHYSICS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- Body (love.physics.newBody) +love.test.objects.Body = function(test) + test:skipTest('test class needs writing') +end + + +-- Contact (love.physics.World:getContacts) +love.test.objects.Contact = function(test) + test:skipTest('test class needs writing') +end + + +-- Fixture (love.physics.newFixture) +love.test.objects.Fixture = function(test) + test:skipTest('test class needs writing') +end + + +-- Joint (love.physics.newDistanceJoint) +love.test.objects.Joint = function(test) + test:skipTest('test class needs writing') +end + + +-- Shape (love.physics.newCircleShape) +love.test.objects.Shape = function(test) + test:skipTest('test class needs writing') +end + + +-- World (love.physics.newWorld) +love.test.objects.World = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-----------------------------------SOUND---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + -- Decoder (love.sound.newDecoder) +love.test.objects.Decoder = function(test) + test:skipTest('test class needs writing') +end + + -- SoundData (love.sound.newSoundData) +love.test.objects.SoundData = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------THREAD---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + -- Channel (love.thread.newChannel) +love.test.objects.Channel = function(test) + test:skipTest('test class needs writing') +end + + -- Thread (love.thread.newThread) +love.test.objects.Thread = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +-----------------------------------VIDEO---------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + -- VideoStream (love.thread.newVideoStream) - --- all the stuff from love.physics! barf - --- (love.graphics objs) --- Canvas --- Font --- Image --- Framebugger --- Mesh --- ParticleSystem --- PixelEffect --- Quad --- Shader --- SpriteBatch --- Text --- Video +love.test.objects.VideoStream = function(test) + test:skipTest('test class needs writing') +end From add23a4ab0817573470481e446b077ea22174637 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:11:07 +0100 Subject: [PATCH 041/409] fix mesa install --- .github/workflows/main.yml | 15 +++++++------- testing/classes/TestModule.lua | 2 +- testing/classes/TestSuite.lua | 2 +- testing/examples/lovetest_runAllTests.md | 26 ++++++++++++++++++++++++ testing/readme.md | 16 +++++++-------- testing/todo.md | 12 ++++------- 6 files changed, 47 insertions(+), 26 deletions(-) create mode 100644 testing/examples/lovetest_runAllTests.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4dbfab58d..7b0801aab 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,7 +52,7 @@ jobs: - name: Make Runnable run: chmod a+x love-${{ github.sha }}.AppImage - name: Run All Tests - run: xvfb-run love-${{ github.sha }}.AppImage testing + run: xvfb-run ./love-${{ github.sha }}.AppImage testing - name: Love Test Report uses: ellraiser/love-test-report@main with: @@ -215,17 +215,18 @@ jobs: with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb + - name: Install Mesa + if: steps.vars.outputs.arch != 'ARM64' + run: | + curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z + 7z x mesa.7z -o* + powershell.exe mesa\systemwidedeploy.cmd 1 - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - - name: Install Mesa - if: steps.vars.outputs.arch != 'ARM64' - uses: ssciwr/setup-mesa-dist-win@v1 - with: - version: '23.2.1' - name: Run All Tests if: steps.vars.outputs.arch != 'ARM64' - run: install\lovec.exe testing/main.lua + run: powershell.exe install/lovec.exe testing - name: Love Test Report if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main diff --git a/testing/classes/TestModule.lua b/testing/classes/TestModule.lua index fa71ddb74..89fd1f7fa 100644 --- a/testing/classes/TestModule.lua +++ b/testing/classes/TestModule.lua @@ -12,7 +12,7 @@ TestModule = { local testmodule = { timer = 0, time = 0, - delay = 0.1, + delay = 0.01, spacer = ' ', colors = { PASS = 'green', FAIL = 'red', SKIP = 'grey' diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 92094ae88..8d9ce368c 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -58,7 +58,7 @@ TestSuite = { -- @return {nil} runSuite = function(self, delta) - -- stagger 0.1s between tests + -- stagger between tests if self.module ~= nil then self.module.timer = self.module.timer + delta if self.module.timer >= self.module.delay then diff --git a/testing/examples/lovetest_runAllTests.md b/testing/examples/lovetest_runAllTests.md new file mode 100644 index 000000000..4fabcde1d --- /dev/null +++ b/testing/examples/lovetest_runAllTests.md @@ -0,0 +1,26 @@ + + +**305** tests were completed in **37.853s** with **244** passed, **0** failed, and **61** skipped + +### Report +| Module | Passed | Failed | Skipped | Time | +| --------------------- | ------ | ------ | ------- | ------ | +| 🟢 love.audio | 26 | 0 | 0 | 2.605s | +| 🟢 love.data | 7 | 0 | 3 | 1.003s | +| 🟢 love.event | 4 | 0 | 2 | 0.600s | +| 🟢 love.filesystem | 27 | 0 | 2 | 3.030s | +| 🟢 love.font | 4 | 0 | 1 | 0.511s | +| 🟢 love.graphics | 81 | 0 | 15 | 10.599s | +| 🟢 love.image | 3 | 0 | 0 | 0.299s | +| 🟢 love.math | 17 | 0 | 0 | 1.821s | +| 🟢 love.objects | 1 | 0 | 34 | 3.603s | +| 🟢 love.physics | 22 | 0 | 0 | 2.222s | +| 🟢 love.sound | 2 | 0 | 0 | 0.199s | +| 🟢 love.system | 6 | 0 | 2 | 0.844s | +| 🟢 love.thread | 3 | 0 | 0 | 0.318s | +| 🟢 love.timer | 6 | 0 | 0 | 2.309s | +| 🟢 love.video | 1 | 0 | 0 | 0.114s | +| 🟢 love.window | 34 | 0 | 2 | 7.778s | + + +### Failures diff --git a/testing/readme.md b/testing/readme.md index 32842061b..f322f7dd5 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -35,9 +35,10 @@ If you want to specify only 1 specific method only you can use: All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level. -An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in the `/output` directory, along with a `HTML` file with a summary of all tests (including visuals for love.graphics tests) - you will need to make sure the command is run with read/write permissions for the source directory. -> Note that this can only be viewed properly locally as the generated images are written to the save directory. -> An example of both types of output can be found in the `/examples` folder +An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in the `/output` directory, along with a `HTML` and a `Markdown` file with a summary of all tests (including visuals for love.graphics tests). +> An example of both types of output can be found in the `/examples` folder + +The Markdown file can be used with [this github action](https://github.com/ellraiser/love-test-report) if you want to output the report results to your CI. --- @@ -81,7 +82,6 @@ For sanity-checking, if it's currently not covered or we're not sure how to test ## Coverage This is the status of all module tests currently. -"objects" is a special module to cover any object specific tests, i.e. testing a File object functions as expected | Module | Passed | Failed | Skipped | Time | | --------------------- | ------ | ------ | ------- | ------ | | 🟢 love.audio | 26 | 0 | 0 | 2.602s | @@ -92,22 +92,20 @@ This is the status of all module tests currently. | 🟢 love.graphics | 81 | 0 | 15 | 10.678s | | 🟢 love.image | 3 | 0 | 0 | 0.300s | | 🟢 love.math | 17 | 0 | 0 | 1.678s | -| 🟢 love.objects | 1 | 0 | 0 | 0.121s | | 🟢 love.physics | 22 | 0 | 0 | 2.197s | | 🟢 love.sound | 2 | 0 | 0 | 0.200s | | 🟢 love.system | 6 | 0 | 2 | 0.802s | | 🟢 love.thread | 3 | 0 | 0 | 0.300s | | 🟢 love.timer | 6 | 0 | 0 | 2.358s | | 🟢 love.video | 1 | 0 | 0 | 0.100s | -| 🟢 love.window | 34 | 0 | 2 | 8.050s | -**271** tests were completed in **34.387s** with **244** passed, **0** failed, and **27** skipped +| 🟢 love.window | 34 | 0 | 2 | 8.050s | The following modules are not covered as we can't really emulate input nicely: `joystick`, `keyboard`, `mouse`, and `touch` --- -## Todo / Skipped +## Todo Modules with some small bits needed or needing sense checking: - **love.data** - packing methods need writing cos i dont really get what they are - **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check @@ -115,7 +113,7 @@ Modules with some small bits needed or needing sense checking: - **love.graphics** - still need to do tests for the main drawing methods - **love.image** - ideally isCompressed should have an example of all compressed files love can take - **love.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back -- **love.objects** - not started properly yet +- **love.*.objects** - all objects tests still to be done - **love.graphics.setStencilTest** - deprecated, replaced by setStencilMode() --- diff --git a/testing/todo.md b/testing/todo.md index 37eac6bb7..5634cbca7 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -3,32 +3,28 @@ ## TESTSUITE - [ ] setStencilMode to replace setStencilTest - [ ] start graphics drawing methods +- [ ] move object methods to respective modules - [ ] start object methods ## GRAPHICS -Methods that need a better actual graphics check if possible: +Methods that need a actual graphic pixel checks if possible: - [ ] setDepthMode - [ ] setFrontFaceWinding - [ ] setMeshCullMode ## FUTURE - [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) - could add platform as global to command and then use in tests? - [ ] use coroutines for the delay action? i.e. wrap each test call in coroutine - and then every test can use coroutine.yield() if needed - [ ] could nil check some joystick and keyboard methods? ## GITHUB ACTION CI - [ ] linux needs to run xvfb-run with the appimage -- [ ] windows can try installing mesa for opengl replacement +- [ ] try vulkan on windows/linux - [ ] ios test run? +## NOTES Can't run --renderers metal on github action images: Run love-macos/love.app/Contents/MacOS/love testing --renderers metal Cannot create Metal renderer: Metal is not supported on this system. Cannot create graphics: no supported renderer on this system. Error: Cannot create graphics: no supported renderer on this system. - -Can't run test suite on windows as it stands: -Unable to create renderer -This program requires a graphics card and video drivers which support OpenGL 2.1 or OpenGL ES 2. From b8cbb62bc315f6ff52e4f5e0c9b4a2b0d3aa6b7d Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 8 Oct 2023 21:08:59 -0300 Subject: [PATCH 042/409] opengl: scissor and color mask no longer affects love.graphics.clear. This makes it more consistent with other backends. --- src/modules/graphics/opengl/Graphics.cpp | 44 ++++++--------------- src/modules/graphics/opengl/OpenGL.cpp | 49 ++++++++++++++++++++++++ src/modules/graphics/opengl/OpenGL.h | 19 +++++++++ src/modules/graphics/opengl/Texture.cpp | 43 ++++++++------------- 4 files changed, 95 insertions(+), 60 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 664d26fa7..c2e5222dd 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -922,36 +922,23 @@ void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth flags |= GL_COLOR_BUFFER_BIT; } - uint32 stencilwrites = gl.getStencilWriteMask(); - if (stencil.hasValue) { - if (stencilwrites != LOVE_UINT32_MAX) - gl.setStencilWriteMask(LOVE_UINT32_MAX); - glClearStencil(stencil.value); flags |= GL_STENCIL_BUFFER_BIT; } - bool hadDepthWrites = gl.hasDepthWrites(); - if (depth.hasValue) { - if (!hadDepthWrites) // glDepthMask also affects glClear. - gl.setDepthWrites(true); - gl.clearDepth(depth.value); flags |= GL_DEPTH_BUFFER_BIT; } if (flags != 0) + { + OpenGL::CleanClearState cs(flags); glClear(flags); - - if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX) - gl.setStencilWriteMask(stencilwrites); - - if (depth.hasValue && !hadDepthWrites) - gl.setDepthWrites(hadDepthWrites); + } if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current) { @@ -1041,36 +1028,23 @@ void Graphics::clear(const std::vector &colors, OptionalInt sten GLbitfield flags = 0; - uint32 stencilwrites = gl.getStencilWriteMask(); - if (stencil.hasValue) { - if (stencilwrites != LOVE_UINT32_MAX) - gl.setStencilWriteMask(LOVE_UINT32_MAX); - glClearStencil(stencil.value); flags |= GL_STENCIL_BUFFER_BIT; } - bool hadDepthWrites = gl.hasDepthWrites(); - if (depth.hasValue) { - if (!hadDepthWrites) // glDepthMask also affects glClear. - gl.setDepthWrites(true); - gl.clearDepth(depth.value); flags |= GL_DEPTH_BUFFER_BIT; } if (flags != 0) + { + OpenGL::CleanClearState cs(flags); glClear(flags); - - if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX) - gl.setStencilWriteMask(stencilwrites); - - if (depth.hasValue && !hadDepthWrites) - gl.setDepthWrites(hadDepthWrites); + } if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current) { @@ -1568,7 +1542,11 @@ void Graphics::setColorMask(ColorChannelMask mask) { flushBatchedDraws(); - glColorMask(mask.r, mask.g, mask.b, mask.a); + uint32 maskbits = + ((mask.r ? 1 : 0) << 1) | ((mask.g ? 1 : 0) << 2) | + ((mask.g ? 1 : 0) << 3) | ((mask.a ? 1 : 0) << 4); + + gl.setColorWriteMask(maskbits); states.back().colorMask = mask; } diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index b169a06a9..df3a0b9b8 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -91,12 +91,49 @@ OpenGL::TempDebugGroup::~TempDebugGroup() } } +OpenGL::CleanClearState::CleanClearState(GLbitfield clearFlags) + : clearFlags(clearFlags) + , colorWriteMask(gl.getColorWriteMask()) + , stencilWriteMask(gl.getStencilWriteMask()) + , depthWrites(gl.hasDepthWrites()) + , scissor(gl.isStateEnabled(ENABLE_SCISSOR_TEST)) +{ + if (clearFlags & GL_COLOR_BUFFER_BIT) + gl.setColorWriteMask(LOVE_UINT32_MAX); + + if (clearFlags & GL_DEPTH_BUFFER_BIT) + gl.setDepthWrites(false); + + if (clearFlags & GL_STENCIL_BUFFER_BIT) + gl.setStencilWriteMask(LOVE_UINT32_MAX); + + if (clearFlags != 0) + gl.setEnableState(ENABLE_SCISSOR_TEST, false); +} + +OpenGL::CleanClearState::~CleanClearState() +{ + if (clearFlags & GL_COLOR_BUFFER_BIT) + gl.setColorWriteMask(colorWriteMask); + + if (clearFlags & GL_DEPTH_BUFFER_BIT) + gl.setDepthWrites(depthWrites); + + if (clearFlags & GL_STENCIL_BUFFER_BIT) + gl.setStencilWriteMask(stencilWriteMask); + + if (clearFlags != 0) + gl.setEnableState(ENABLE_SCISSOR_TEST, scissor); +} + OpenGL::OpenGL() : stats() + , bugs() , contextInitialized(false) , pixelShaderHighpSupported(false) , baseVertexSupported(false) , maxAnisotropy(1.0f) + , maxLODBias(0.0f) , max2DTextureSize(0) , max3DTextureSize(0) , maxCubeTextureSize(0) @@ -284,6 +321,7 @@ void OpenGL::setupContext() setDepthWrites(state.depthWritesEnabled); setStencilWriteMask(state.stencilWriteMask); + setColorWriteMask(state.colorWriteMask); createDefaultTexture(); @@ -1125,6 +1163,17 @@ uint32 OpenGL::getStencilWriteMask() const return state.stencilWriteMask; } +void OpenGL::setColorWriteMask(uint32 mask) +{ + glColorMask(mask & (1 << 0), mask & (1 << 1), mask & (1 << 2), mask & (1 << 3)); + state.colorWriteMask = mask; +} + +uint32 OpenGL::getColorWriteMask() const +{ + return state.colorWriteMask; +} + void OpenGL::useProgram(GLuint program) { glUseProgram(program); diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 6f2d26746..3690c6baa 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -124,6 +124,21 @@ public: ~TempDebugGroup(); }; + // glClear() is affected by various OpenGL state... + class CleanClearState + { + public: + CleanClearState(GLbitfield clearFlags); + ~CleanClearState(); + + private: + GLenum clearFlags; + uint32 colorWriteMask; + uint32 stencilWriteMask; + bool depthWrites; + bool scissor; + }; + struct Stats { int shaderSwitches; @@ -301,6 +316,9 @@ public: void setStencilWriteMask(uint32 mask); uint32 getStencilWriteMask() const; + void setColorWriteMask(uint32 mask); + uint32 getColorWriteMask() const; + /** * Calls glUseProgram. **/ @@ -528,6 +546,7 @@ private: bool depthWritesEnabled = true; uint32 stencilWriteMask = LOVE_UINT32_MAX; + uint32 colorWriteMask = LOVE_UINT32_MAX; GLuint boundFramebuffers[2]; diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index 70fdbd344..01a451e8f 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -80,31 +80,22 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo if (clear) { - if (isPixelFormatDepthStencil(format)) + bool ds = isPixelFormatDepthStencil(format); + + GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT; + OpenGL::CleanClearState cleanClearState(clearflags); + + if (ds) { - bool hadDepthWrites = gl.hasDepthWrites(); - if (!hadDepthWrites) // glDepthMask also affects glClear. - gl.setDepthWrites(true); - - uint32 stencilwrite = gl.getStencilWriteMask(); - if (stencilwrite != LOVE_UINT32_MAX) - gl.setStencilWriteMask(LOVE_UINT32_MAX); - gl.clearDepth(1.0); glClearStencil(0); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - if (!hadDepthWrites) - gl.setDepthWrites(hadDepthWrites); - - if (stencilwrite != LOVE_UINT32_MAX) - gl.setStencilWriteMask(stencilwrite); } else { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); } + + glClear(clearflags); } } } @@ -167,25 +158,23 @@ static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat p if (status == GL_FRAMEBUFFER_COMPLETE) { - if (isPixelFormatDepthStencil(pixelformat)) - { - bool hadDepthWrites = gl.hasDepthWrites(); - if (!hadDepthWrites) // glDepthMask also affects glClear. - gl.setDepthWrites(true); + bool ds = isPixelFormatDepthStencil(pixelformat); + GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT; + OpenGL::CleanClearState cleanClearState(clearflags); + + if (ds) + { gl.clearDepth(1.0); glClearStencil(0); - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - if (!hadDepthWrites) - gl.setDepthWrites(hadDepthWrites); } else { // Initialize the buffer to transparent black. glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); } + + glClear(clearflags); } else { From 2789e5eabf642d10aee8ad69486722a2d698a291 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 8 Oct 2023 21:36:10 -0300 Subject: [PATCH 043/409] opengl: fix clearing integer format Canvases. --- src/modules/graphics/opengl/Graphics.cpp | 24 ++++++++++ src/modules/graphics/opengl/Texture.cpp | 57 ++++++++++++++++++------ 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index c2e5222dd..790afa564 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -909,6 +909,30 @@ void Graphics::endPass(bool presenting) void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth) { + if (c.hasValue) + { + bool hasintegerformat = false; + + const auto &rts = states.back().renderTargets; + for (const auto &rt : rts.colors) + { + if (rt.texture.get() && isPixelFormatInteger(rt.texture->getPixelFormat())) + hasintegerformat = true; + } + + // This variant of clear() uses glClear() which can't clear integer formats, + // so we switch to the MRT variant if needed. + if (hasintegerformat) + { + std::vector colors(rts.colors.size()); + for (size_t i = 0; i < colors.size(); i++) + colors[i] = c; + + clear(colors, stencil, depth); + return; + } + } + if (c.hasValue || stencil.hasValue || depth.hasValue) flushBatchedDraws(); diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index 01a451e8f..1b6eb69f1 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -78,7 +78,21 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo gl.framebufferTexture(attachment, texType, texture, mip, layer, face); } - if (clear) + if (clear && isPixelFormatInteger(format)) + { + PixelFormatType datatype = getPixelFormatInfo(format).dataType; + if (datatype == PIXELFORMATTYPE_SINT) + { + const GLint carray[] = { 0, 0, 0, 0 }; + glClearBufferiv(GL_COLOR, 0, carray); + } + else + { + const GLuint carray[] = { 0, 0, 0, 0 }; + glClearBufferuiv(GL_COLOR, 0, carray); + } + } + else if (clear) { bool ds = isPixelFormatDepthStencil(format); @@ -158,23 +172,40 @@ static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat p if (status == GL_FRAMEBUFFER_COMPLETE) { - bool ds = isPixelFormatDepthStencil(pixelformat); - - GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT; - OpenGL::CleanClearState cleanClearState(clearflags); - - if (ds) + if (isPixelFormatInteger(pixelformat)) { - gl.clearDepth(1.0); - glClearStencil(0); + PixelFormatType datatype = getPixelFormatInfo(pixelformat).dataType; + if (datatype == PIXELFORMATTYPE_SINT) + { + const GLint carray[] = { 0, 0, 0, 0 }; + glClearBufferiv(GL_COLOR, 0, carray); + } + else + { + const GLuint carray[] = { 0, 0, 0, 0 }; + glClearBufferuiv(GL_COLOR, 0, carray); + } } else { - // Initialize the buffer to transparent black. - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - } + bool ds = isPixelFormatDepthStencil(pixelformat); - glClear(clearflags); + GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT; + OpenGL::CleanClearState cleanClearState(clearflags); + + if (ds) + { + gl.clearDepth(1.0); + glClearStencil(0); + } + else + { + // Initialize the buffer to transparent black. + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } + + glClear(clearflags); + } } else { From 8f8afe3de592190ce94f8c0263c27b0563087e99 Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 9 Oct 2023 15:31:23 +0200 Subject: [PATCH 044/409] vulkan: fix crash when using love.window.close() --- src/modules/graphics/vulkan/Graphics.cpp | 274 +++++++++--------- src/modules/graphics/vulkan/Graphics.h | 15 +- .../graphics/vulkan/GraphicsReadback.cpp | 6 +- 3 files changed, 158 insertions(+), 137 deletions(-) diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 8a4f7500f..2432dad27 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -65,22 +65,88 @@ const char *Graphics::getName() const return "love.graphics.vulkan"; } -const VkDevice Graphics::getDevice() const +VkDevice Graphics::getDevice() const { return device; } -const VmaAllocator Graphics::getVmaAllocator() const +VmaAllocator Graphics::getVmaAllocator() const { return vmaAllocator; } +static void checkOptionalInstanceExtensions(OptionalInstanceExtensions& ext) +{ + uint32_t count; + + vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); + + std::vector extensions(count); + + vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data()); + + for (const auto& extension : extensions) + { + if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) + ext.physicalDeviceProperties2 = true; + } +} + Graphics::Graphics() { if (SDL_Vulkan_LoadLibrary(nullptr)) throw love::Exception("could not find vulkan"); volkInitializeCustom((PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr()); + + if (isDebugEnabled() && !checkValidationSupport()) + throw love::Exception("validation layers requested, but not available"); + + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "LOVE"; + appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else? + appInfo.pEngineName = "LOVE Game Framework"; + appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV); + appInfo.apiVersion = VK_API_VERSION_1_3; + + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + createInfo.pNext = nullptr; + + // GetInstanceExtensions works with a null window parameter as long as + // SDL_Vulkan_LoadLibrary has been called (which we do earlier). + unsigned int count; + if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, nullptr) != SDL_TRUE) + throw love::Exception("couldn't retrieve sdl vulkan extensions"); + + std::vector extensions = {}; + + checkOptionalInstanceExtensions(optionalInstanceExtensions); + + if (optionalInstanceExtensions.physicalDeviceProperties2) + extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + + size_t additional_extension_count = extensions.size(); + extensions.resize(additional_extension_count + count); + + if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, extensions.data() + additional_extension_count) != SDL_TRUE) + throw love::Exception("couldn't retrieve sdl vulkan extensions"); + + createInfo.enabledExtensionCount = static_cast(extensions.size()); + createInfo.ppEnabledExtensionNames = extensions.data(); + + if (isDebugEnabled()) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + } + + if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) + throw love::Exception("couldn't create vulkan instance"); + + volkLoadInstance(instance); } Graphics::~Graphics() @@ -88,6 +154,10 @@ Graphics::~Graphics() defaultConstantColor.set(nullptr); defaultTexture.set(nullptr); + Volatile::unloadAll(); + cleanup(); + vkDestroyInstance(instance, nullptr); + SDL_Vulkan_UnloadLibrary(); } @@ -302,14 +372,14 @@ void Graphics::discard(const std::vector &colorbuffers, bool depthstencil) startRenderPass(); } -void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData) +void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallbackData) { flushBatchedDraws(); if (renderPassState.active) endRenderPass(); - if (present) + if (submitMode == SUBMIT_PRESENT) { if (pendingScreenshotCallbacks.empty()) Vulkan::cmdTransitionImageLayout( @@ -435,7 +505,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData) VkFence fence = VK_NULL_HANDLE; - if (present) + if (submitMode == SUBMIT_PRESENT) { submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; @@ -447,7 +517,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData) if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS) throw love::Exception("failed to submit draw command buffer"); - if (!present) + if (submitMode == SUBMIT_NOPRESENT || submitMode == SUBMIT_RESTART) { vkQueueWaitIdle(graphicsQueue); @@ -458,7 +528,8 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData) callbacks.clear(); } - startRecordingGraphicsCommands(); + if (submitMode == SUBMIT_RESTART) + startRecordingGraphicsCommands(); } } @@ -475,7 +546,7 @@ void Graphics::present(void *screenshotCallbackdata) deprecations.draw(this); - submitGpuCommands(true, screenshotCallbackdata); + submitGpuCommands(SUBMIT_PRESENT, screenshotCallbackdata); VkPresentInfoKHR presentInfo{}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; @@ -540,64 +611,80 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int readbackCallbacks.clear(); readbackCallbacks.resize(MAX_FRAMES_IN_FLIGHT); - createVulkanInstance(); + bool createBaseObjects = physicalDevice == VK_NULL_HANDLE; + createSurface(); - pickPhysicalDevice(); - createLogicalDevice(); - createPipelineCache(); - initVMA(); - initCapabilities(); + + if (createBaseObjects) + { + pickPhysicalDevice(); + createLogicalDevice(); + createPipelineCache(); + initVMA(); + initCapabilities(); + } + + msaaSamples = getMsaaCount(requestedMsaa); + createSwapChain(); createImageViews(); createScreenshotCallbackBuffers(); - createSyncObjects(); createColorResources(); createDepthResources(); transitionColorDepthLayouts = true; - createCommandPool(); - createCommandBuffers(); + + if (createBaseObjects) + { + createCommandPool(); + createCommandBuffers(); + createSyncObjects(); + } beginFrame(); - if (batchedDrawState.vb[0] == nullptr) + if (createBaseObjects) { - // Initial sizes that should be good enough for most cases. It will - // resize to fit if needed, later. - batchedDrawState.vb[0] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1); - batchedDrawState.vb[1] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1); - batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); - } + if (batchedDrawState.vb[0] == nullptr) + { + // Initial sizes that should be good enough for most cases. It will + // resize to fit if needed, later. + batchedDrawState.vb[0] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1); + batchedDrawState.vb[1] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1); + batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX); + } - // sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0) - if (defaultConstantTexCoord == nullptr) - { - float zeroTexCoord[2] = { 0.0f, 0.0f }; - Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2); - Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC); - defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1); - } + // sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0) + if (defaultConstantTexCoord == nullptr) + { + float zeroTexCoord[2] = { 0.0f, 0.0f }; + Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC); + defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1); + } - // sometimes the VertexColor is not set, so we manually adjust it to white color - if (defaultConstantColor == nullptr) - { - uint8 whiteColor[] = { 255, 255, 255, 255 }; - Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4); - Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC); - defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1); - } + // sometimes the VertexColor is not set, so we manually adjust it to white color + if (defaultConstantColor == nullptr) + { + uint8 whiteColor[] = { 255, 255, 255, 255 }; + Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4); + Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC); + defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1); + } - createDefaultTexture(); - createDefaultShaders(); - Shader::current = Shader::standardShaders[Shader::StandardShader::STANDARD_DEFAULT]; - createQuadIndexBuffer(); - createFanIndexBuffer(); + createDefaultTexture(); + createDefaultShaders(); + Shader::current = Shader::standardShaders[Shader::StandardShader::STANDARD_DEFAULT]; + createQuadIndexBuffer(); + createFanIndexBuffer(); + + frameCounter = 0; + currentFrame = 0; + } restoreState(states.back()); Vulkan::resetShaderSwitches(); - frameCounter = 0; - currentFrame = 0; created = true; drawCalls = 0; drawCallsBatched = 0; @@ -659,14 +746,12 @@ void Graphics::getAPIStats(int &shaderswitches) const void Graphics::unSetMode() { - renderPassUsages.clear(); - framebufferUsages.clear(); - pipelineUsages.clear(); - + submitGpuCommands(SUBMIT_NOPRESENT); + created = false; - vkDeviceWaitIdle(device); - Volatile::unloadAll(); - cleanup(); + + cleanupSwapChain(); + vkDestroySurfaceKHR(instance, surface, nullptr); } void Graphics::setActive(bool enable) @@ -1332,75 +1417,6 @@ const OptionalDeviceExtensions &Graphics::getEnabledOptionalDeviceExtensions() c return optionalDeviceExtensions; } -static void checkOptionalInstanceExtensions(OptionalInstanceExtensions &ext) -{ - uint32_t count; - - vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); - - std::vector extensions(count); - - vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data()); - - for (const auto &extension : extensions) - { - if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) - ext.physicalDeviceProperties2 = true; - } -} - -void Graphics::createVulkanInstance() -{ - if (isDebugEnabled() && !checkValidationSupport()) - throw love::Exception("validation layers requested, but not available"); - - VkApplicationInfo appInfo{}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "LOVE"; - appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else? - appInfo.pEngineName = "LOVE Game Framework"; - appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV); - appInfo.apiVersion = VK_API_VERSION_1_3; - - VkInstanceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - createInfo.pNext = nullptr; - - // GetInstanceExtensions works with a null window parameter as long as - // SDL_Vulkan_LoadLibrary has been called (which we do earlier). - unsigned int count; - if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, nullptr) != SDL_TRUE) - throw love::Exception("couldn't retrieve sdl vulkan extensions"); - - std::vector extensions = {}; - - checkOptionalInstanceExtensions(optionalInstanceExtensions); - - if (optionalInstanceExtensions.physicalDeviceProperties2) - extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - - size_t additional_extension_count = extensions.size(); - extensions.resize(additional_extension_count + count); - - if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, extensions.data() + additional_extension_count) != SDL_TRUE) - throw love::Exception("couldn't retrieve sdl vulkan extensions"); - - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); - - if (isDebugEnabled()) - { - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); - } - - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) - throw love::Exception("couldn't create vulkan instance"); - - volkLoadInstance(instance); -} - bool Graphics::checkValidationSupport() { uint32_t layerCount; @@ -1458,7 +1474,6 @@ void Graphics::pickPhysicalDevice() minUniformBufferOffsetAlignment = properties.limits.minUniformBufferOffsetAlignment; deviceApiVersion = properties.apiVersion; - msaaSamples = getMsaaCount(requestedMsaa); depthStencilFormat = findDepthFormat(); } @@ -3040,8 +3055,6 @@ void Graphics::createDefaultTexture() void Graphics::cleanup() { - cleanupSwapChain(); - for (auto &cleanUpFns : cleanUpFunctions) for (auto &cleanUpFn : cleanUpFns) cleanUpFn(); @@ -3076,8 +3089,6 @@ void Graphics::cleanup() vkDestroyCommandPool(device, commandPool, nullptr); vkDestroyPipelineCache(device, pipelineCache, nullptr); vkDestroyDevice(device, nullptr); - vkDestroySurfaceKHR(instance, surface, nullptr); - vkDestroyInstance(instance, nullptr); } void Graphics::cleanupSwapChain() @@ -3087,8 +3098,11 @@ void Graphics::cleanupSwapChain() vmaDestroyBuffer(vmaAllocator, readbackBuffer.buffer, readbackBuffer.allocation); vmaDestroyImage(vmaAllocator, readbackBuffer.image, readbackBuffer.imageAllocation); } - vkDestroyImageView(device, colorImageView, nullptr); - vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation); + if (colorImage) + { + vkDestroyImageView(device, colorImageView, nullptr); + vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation); + } vkDestroyImageView(device, depthImageView, nullptr); vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation); for (const auto &swapChainImageView : swapChainImageViews) diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 04161b9e8..7d90542b8 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -256,6 +256,14 @@ struct ScreenshotReadbackBuffer VmaAllocation imageAllocation; }; +enum SubmitMode +{ + SUBMIT_PRESENT, + SUBMIT_NOPRESENT, + SUBMIT_RESTART, + SUBMIT_MAXENUM, +}; + class Graphics final : public love::graphics::Graphics { public: @@ -300,12 +308,12 @@ public: // internal functions. - const VkDevice getDevice() const; - const VmaAllocator getVmaAllocator() const; + VkDevice getDevice() const; + VmaAllocator getVmaAllocator() const; VkCommandBuffer getCommandBufferForDataTransfer(); void queueCleanUp(std::function cleanUp); void addReadbackCallback(std::function callback); - void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr); + void submitGpuCommands(SubmitMode, void *screenshotCallbackData = nullptr); const VkDeviceSize getMinUniformBufferOffsetAlignment() const; VkSampler getCachedSampler(const SamplerState &sampler); void setComputeShader(Shader *computeShader); @@ -326,7 +334,6 @@ protected: void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override; private: - void createVulkanInstance(); bool checkValidationSupport(); void pickPhysicalDevice(); int rateDeviceSuitability(VkPhysicalDevice device); diff --git a/src/modules/graphics/vulkan/GraphicsReadback.cpp b/src/modules/graphics/vulkan/GraphicsReadback.cpp index 51a8a01b8..257a3b219 100644 --- a/src/modules/graphics/vulkan/GraphicsReadback.cpp +++ b/src/modules/graphics/vulkan/GraphicsReadback.cpp @@ -44,7 +44,7 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod if (method == READBACK_IMMEDIATE) { - vgfx->submitGpuCommands(false); + vgfx->submitGpuCommands(SUBMIT_RESTART); if (stagingBuffer.get()) { status = readbackBuffer(stagingBuffer, 0, size); gfx->releaseTemporaryBuffer(stagingBuffer); @@ -79,7 +79,7 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod }); if (method == READBACK_IMMEDIATE) - vgfx->submitGpuCommands(false); + vgfx->submitGpuCommands(SUBMIT_RESTART); } GraphicsReadback::~GraphicsReadback() @@ -89,7 +89,7 @@ GraphicsReadback::~GraphicsReadback() void GraphicsReadback::wait() { if (status == STATUS_WAITING) - vgfx->submitGpuCommands(false); + vgfx->submitGpuCommands(SUBMIT_RESTART); } void GraphicsReadback::update() From 51d5b4851566e1f82ab625c841b3b106ef90b869 Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 9 Oct 2023 15:32:17 +0200 Subject: [PATCH 045/409] vulkan: fix incorrect device extension --- src/modules/graphics/vulkan/Graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 2432dad27..3fddecbce 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -1588,7 +1588,7 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option optionalDeviceExtensions.memoryRequirements2 = true; if (strcmp(extension.extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0) optionalDeviceExtensions.dedicatedAllocation = true; - if (strcmp(extension.extensionName, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0) + if (strcmp(extension.extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0) optionalDeviceExtensions.memoryBudget = true; if (strcmp(extension.extensionName, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) == 0) optionalDeviceExtensions.shaderFloatControls = true; From 21182d1428c681d138783b94fac903b67fd56bc9 Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 9 Oct 2023 16:04:25 +0200 Subject: [PATCH 046/409] vulkan: fix memory leak --- src/modules/graphics/vulkan/Graphics.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 3fddecbce..b51db2154 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -151,6 +151,7 @@ Graphics::Graphics() Graphics::~Graphics() { + defaultConstantTexCoord.set(nullptr); defaultConstantColor.set(nullptr); defaultTexture.set(nullptr); From cf26e39d1b0d7a075bfc7b060a78e67b69bdb5f0 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 9 Oct 2023 13:13:37 -0300 Subject: [PATCH 047/409] vulkan: potential fix for compressed textures with mipmaps --- src/modules/graphics/vulkan/Texture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 60c55b9a8..6ae53c1c1 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -150,7 +150,7 @@ bool Texture::loadVolatile() createTextureImageView(); textureSampler = vgfx->getCachedSampler(samplerState); - if (!isPixelFormatDepthStencil(format) && mipmapCount > 1 && getMipmapsMode() != MIPMAPS_NONE) + if (!isPixelFormatDepthStencil(format) && slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE) generateMipmaps(); if (renderTarget) From 4787d500787f752b1922116f9d7dbee3f1d1520c Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 9 Oct 2023 14:10:24 -0300 Subject: [PATCH 048/409] opengl: fix color mask --- src/modules/graphics/opengl/Graphics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 790afa564..a0d05f6ec 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1567,8 +1567,8 @@ void Graphics::setColorMask(ColorChannelMask mask) flushBatchedDraws(); uint32 maskbits = - ((mask.r ? 1 : 0) << 1) | ((mask.g ? 1 : 0) << 2) | - ((mask.g ? 1 : 0) << 3) | ((mask.a ? 1 : 0) << 4); + ((mask.r ? 1 : 0) << 0) | ((mask.g ? 1 : 0) << 1) | + ((mask.g ? 1 : 0) << 2) | ((mask.a ? 1 : 0) << 3); gl.setColorWriteMask(maskbits); states.back().colorMask = mask; From 88272c68558c1c0dc3af8b37a0157c62c45629da Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 9 Oct 2023 20:07:32 +0200 Subject: [PATCH 049/409] vulkan: correctly identify boolean uniforms --- src/modules/graphics/Shader.cpp | 10 +++++++++- src/modules/graphics/vulkan/Shader.cpp | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/modules/graphics/Shader.cpp b/src/modules/graphics/Shader.cpp index f6c314420..5ace1031d 100644 --- a/src/modules/graphics/Shader.cpp +++ b/src/modules/graphics/Shader.cpp @@ -1010,8 +1010,16 @@ bool Shader::validateInternal(StrongRef stages[], std::string &err, values[i].u = convertData((*constarray)[i]); } break; - case glslang::EbtInt: case glslang::EbtBool: + u.dataType = DATA_BASETYPE_BOOL; + if (constarray != nullptr) + { + values.resize(constarray->size()); + for (int i = 0; i < constarray->size(); i++) + values[i].u = convertData((*constarray)[i]); + } + break; + case glslang::EbtInt: default: u.dataType = DATA_BASETYPE_INT; if (constarray != nullptr) diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 3ad661164..932a4f7c8 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -614,6 +614,9 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: std::string name = basename + comp.get_member_name(type.self, uindex); + if (name == "Debug") + float x = 1.0f; + switch (memberType.basetype) { case SPIRType::Struct: @@ -656,6 +659,9 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: if (reflectionIt != validationReflection.localUniforms.end()) { const auto &localUniform = reflectionIt->second; + if (localUniform.dataType == DATA_BASETYPE_BOOL) + u.baseType = UNIFORM_BOOL; + const auto &values = localUniform.initializerValues; if (!values.empty()) memcpy( From 2749209fc7220d85d050b6cccc7a63a5da034d2e Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 9 Oct 2023 20:12:13 +0200 Subject: [PATCH 050/409] vulkan: fix crash when using wrong uniform name --- src/modules/graphics/vulkan/Shader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 932a4f7c8..086aad259 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -551,7 +551,8 @@ int Shader::getVertexAttributeIndex(const std::string &name) const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const { - return &uniformInfos.at(name); + const auto it = uniformInfos.find(name); + return it != uniformInfos.end() ? &(it->second) : nullptr; } const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const From 8958d155abbb7625b4783cad5e17f58cc750a66b Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 9 Oct 2023 15:13:03 -0300 Subject: [PATCH 051/409] opengl: Fix blue component of love.graphics.setColorMask --- src/modules/graphics/opengl/Graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index a0d05f6ec..50f0a3e79 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1568,7 +1568,7 @@ void Graphics::setColorMask(ColorChannelMask mask) uint32 maskbits = ((mask.r ? 1 : 0) << 0) | ((mask.g ? 1 : 0) << 1) | - ((mask.g ? 1 : 0) << 2) | ((mask.a ? 1 : 0) << 3); + ((mask.b ? 1 : 0) << 2) | ((mask.a ? 1 : 0) << 3); gl.setColorWriteMask(maskbits); states.back().colorMask = mask; From 5dc7b7d05b4783af0081a5fdf516dfe7161390e6 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 9 Oct 2023 15:13:47 -0300 Subject: [PATCH 052/409] remove some redundant OpenGL API calls when clearing Canvases --- src/modules/graphics/opengl/OpenGL.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index df3a0b9b8..ad8a4b66e 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -98,31 +98,31 @@ OpenGL::CleanClearState::CleanClearState(GLbitfield clearFlags) , depthWrites(gl.hasDepthWrites()) , scissor(gl.isStateEnabled(ENABLE_SCISSOR_TEST)) { - if (clearFlags & GL_COLOR_BUFFER_BIT) + if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX) gl.setColorWriteMask(LOVE_UINT32_MAX); - if (clearFlags & GL_DEPTH_BUFFER_BIT) + if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && depthWrites) gl.setDepthWrites(false); - if (clearFlags & GL_STENCIL_BUFFER_BIT) + if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF) gl.setStencilWriteMask(LOVE_UINT32_MAX); - if (clearFlags != 0) + if (clearFlags != 0 && scissor) gl.setEnableState(ENABLE_SCISSOR_TEST, false); } OpenGL::CleanClearState::~CleanClearState() { - if (clearFlags & GL_COLOR_BUFFER_BIT) + if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX) gl.setColorWriteMask(colorWriteMask); - if (clearFlags & GL_DEPTH_BUFFER_BIT) + if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && depthWrites) gl.setDepthWrites(depthWrites); - if (clearFlags & GL_STENCIL_BUFFER_BIT) + if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF) gl.setStencilWriteMask(stencilWriteMask); - if (clearFlags != 0) + if (clearFlags != 0 && scissor) gl.setEnableState(ENABLE_SCISSOR_TEST, scissor); } From 88f6bb880e4c9bdd4f44590700e15be81f980e10 Mon Sep 17 00:00:00 2001 From: niki Date: Mon, 9 Oct 2023 20:16:01 +0200 Subject: [PATCH 053/409] remove debug code --- src/modules/graphics/vulkan/Shader.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 086aad259..473623f42 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -615,9 +615,6 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross:: std::string name = basename + comp.get_member_name(type.self, uindex); - if (name == "Debug") - float x = 1.0f; - switch (memberType.basetype) { case SPIRType::Struct: From f477b8085f945eeeadb4cede78c68aa0089d04d5 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Mon, 9 Oct 2023 22:32:41 +0100 Subject: [PATCH 054/409] finish graphics module + HTML image comparison - added mostly all graphics draw tests - added a basic set of "expected" images (generated from successful tests) - HTML output now shows the expected vs actual generated images for each of the graphics tests applicable --- .github/workflows/main.yml | 33 +- .gitignore | 1 + testing/classes/TestMethod.lua | 38 ++- testing/classes/TestModule.lua | 2 +- testing/classes/TestSuite.lua | 2 - testing/main.lua | 3 + testing/output/actual/notes.txt | 2 + .../love.test.graphics.applyTransform-1.png | Bin 0 -> 89 bytes .../expected/love.test.graphics.arc-1.png | Bin 0 -> 245 bytes .../expected/love.test.graphics.arc-2.png | Bin 0 -> 204 bytes .../expected/love.test.graphics.arc-3.png | Bin 0 -> 223 bytes .../expected/love.test.graphics.circle-1.png | Bin 0 -> 212 bytes .../expected/love.test.graphics.clear-1.png | Bin 0 -> 84 bytes .../expected/love.test.graphics.draw-1.png | Bin 0 -> 221 bytes .../love.test.graphics.drawLayer-1.png | Bin 0 -> 386 bytes .../expected/love.test.graphics.ellipse-1.png | Bin 0 -> 185 bytes .../love.test.graphics.intersectScissor-1.png | Bin 0 -> 91 bytes .../expected/love.test.graphics.line-1.png | Bin 0 -> 139 bytes .../expected/love.test.graphics.origin-1.png | Bin 0 -> 90 bytes .../expected/love.test.graphics.points-1.png | Bin 0 -> 111 bytes .../expected/love.test.graphics.polygon-1.png | Bin 0 -> 154 bytes .../expected/love.test.graphics.pop-1.png | Bin 0 -> 90 bytes .../expected/love.test.graphics.print-1.png | Bin 0 -> 154 bytes .../expected/love.test.graphics.printf-1.png | Bin 0 -> 196 bytes .../expected/love.test.graphics.push-1.png | Bin 0 -> 91 bytes .../love.test.graphics.rectangle-1.png | Bin 0 -> 92 bytes .../love.test.graphics.rectangle-2.png | Bin 0 -> 103 bytes .../love.test.graphics.replaceTransform-1.png | Bin 0 -> 89 bytes .../expected/love.test.graphics.rotate-1.png | Bin 0 -> 91 bytes .../love.test.graphics.setBlendMode-1.png | Bin 0 -> 123 bytes .../love.test.graphics.setCanvas-1.png | Bin 0 -> 84 bytes .../love.test.graphics.setColor-1.png | Bin 0 -> 128 bytes .../love.test.graphics.setColorMask-1.png | Bin 0 -> 99 bytes .../expected/love.test.graphics.setFont-1.png | Bin 0 -> 106 bytes .../love.test.graphics.setLineJoin-1.png | Bin 0 -> 122 bytes .../love.test.graphics.setLineStyle-1.png | Bin 0 -> 102 bytes .../love.test.graphics.setLineWidth-1.png | Bin 0 -> 118 bytes .../love.test.graphics.setScissor-1.png | Bin 0 -> 89 bytes .../love.test.graphics.setShader-1.png | Bin 0 -> 84 bytes .../love.test.graphics.setStencilTest-1.png | Bin 0 -> 107 bytes .../love.test.graphics.setWireframe-1.png | Bin 0 -> 128 bytes .../expected/love.test.graphics.shear-1.png | Bin 0 -> 98 bytes .../expected/love.test.graphics.shear-2.png | Bin 0 -> 101 bytes .../love.test.graphics.translate-1.png | Bin 0 -> 93 bytes testing/output/expected/notes.txt | 2 + testing/output/{readme.md => notes.txt} | 0 testing/resources/loveinv.png | Bin 0 -> 680 bytes testing/tests/graphics.lua | 310 +++++++++++++++++- testing/todo.md | 5 +- 49 files changed, 366 insertions(+), 32 deletions(-) create mode 100644 testing/output/actual/notes.txt create mode 100644 testing/output/expected/love.test.graphics.applyTransform-1.png create mode 100644 testing/output/expected/love.test.graphics.arc-1.png create mode 100644 testing/output/expected/love.test.graphics.arc-2.png create mode 100644 testing/output/expected/love.test.graphics.arc-3.png create mode 100644 testing/output/expected/love.test.graphics.circle-1.png create mode 100644 testing/output/expected/love.test.graphics.clear-1.png create mode 100644 testing/output/expected/love.test.graphics.draw-1.png create mode 100644 testing/output/expected/love.test.graphics.drawLayer-1.png create mode 100644 testing/output/expected/love.test.graphics.ellipse-1.png create mode 100644 testing/output/expected/love.test.graphics.intersectScissor-1.png create mode 100644 testing/output/expected/love.test.graphics.line-1.png create mode 100644 testing/output/expected/love.test.graphics.origin-1.png create mode 100644 testing/output/expected/love.test.graphics.points-1.png create mode 100644 testing/output/expected/love.test.graphics.polygon-1.png create mode 100644 testing/output/expected/love.test.graphics.pop-1.png create mode 100644 testing/output/expected/love.test.graphics.print-1.png create mode 100644 testing/output/expected/love.test.graphics.printf-1.png create mode 100644 testing/output/expected/love.test.graphics.push-1.png create mode 100644 testing/output/expected/love.test.graphics.rectangle-1.png create mode 100644 testing/output/expected/love.test.graphics.rectangle-2.png create mode 100644 testing/output/expected/love.test.graphics.replaceTransform-1.png create mode 100644 testing/output/expected/love.test.graphics.rotate-1.png create mode 100644 testing/output/expected/love.test.graphics.setBlendMode-1.png create mode 100644 testing/output/expected/love.test.graphics.setCanvas-1.png create mode 100644 testing/output/expected/love.test.graphics.setColor-1.png create mode 100644 testing/output/expected/love.test.graphics.setColorMask-1.png create mode 100644 testing/output/expected/love.test.graphics.setFont-1.png create mode 100644 testing/output/expected/love.test.graphics.setLineJoin-1.png create mode 100644 testing/output/expected/love.test.graphics.setLineStyle-1.png create mode 100644 testing/output/expected/love.test.graphics.setLineWidth-1.png create mode 100644 testing/output/expected/love.test.graphics.setScissor-1.png create mode 100644 testing/output/expected/love.test.graphics.setShader-1.png create mode 100644 testing/output/expected/love.test.graphics.setStencilTest-1.png create mode 100644 testing/output/expected/love.test.graphics.setWireframe-1.png create mode 100644 testing/output/expected/love.test.graphics.shear-1.png create mode 100644 testing/output/expected/love.test.graphics.shear-2.png create mode 100644 testing/output/expected/love.test.graphics.translate-1.png create mode 100644 testing/output/expected/notes.txt rename testing/output/{readme.md => notes.txt} (100%) create mode 100644 testing/resources/loveinv.png diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b0801aab..5229bdaf8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: linux-os: runs-on: ubuntu-20.04 + timeout-minutes: 60 steps: - name: Update APT run: sudo apt-get update @@ -50,9 +51,12 @@ jobs: name: love-x86_64-AppImage-debug path: love-${{ github.sha }}.AppImage-debug.tar.gz - name: Make Runnable - run: chmod a+x love-${{ github.sha }}.AppImage + run: | + chmod a+x love-${{ github.sha }}.AppImage + echo "ready to run" + ls - name: Run All Tests - run: xvfb-run ./love-${{ github.sha }}.AppImage testing + run: xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua - name: Love Test Report uses: ellraiser/love-test-report@main with: @@ -61,6 +65,7 @@ jobs: path: testing/output/lovetest_runAllTests.md windows-os: runs-on: windows-latest + timeout-minutes: 60 strategy: matrix: platform: [Win32, x64, ARM64] @@ -214,9 +219,21 @@ jobs: uses: actions/upload-artifact@v3 with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg - path: pdb/Release/*.pdb + path: pdb/Release/*.pdb + - name: Install Scream + shell: powershell + run: | + Start-Service audio* + Invoke-WebRequest https://github.com/duncanthrax/scream/releases/download/3.6/Scream3.6.zip -OutFile C:\Scream3.6.zip + Extract-7Zip -Path C:\Scream3.6.zip -DestinationPath C:\Scream + $cert = (Get-AuthenticodeSignature C:\Scream\Install\driver\Scream.sys).SignerCertificate + $store = [System.Security.Cryptography.X509Certificates.X509Store]::new("TrustedPublisher", "LocalMachine") + $store.Open("ReadWrite") + $store.Add($cert) + $store.Close() + cd C:\Scream\Install\driver + C:\Scream\Install\helpers\devcon install Scream.inf *Scream - name: Install Mesa - if: steps.vars.outputs.arch != 'ARM64' run: | curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z 7z x mesa.7z -o* @@ -226,7 +243,9 @@ jobs: run: cmake --build build --config Release --target install - name: Run All Tests if: steps.vars.outputs.arch != 'ARM64' - run: powershell.exe install/lovec.exe testing + run: | + dir + powershell.exe ./install/lovec.exe ./testing/main.lua - name: Love Test Report if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main @@ -236,6 +255,7 @@ jobs: path: testing/output/lovetest_runAllTests.md macOS: runs-on: macos-latest + timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 @@ -263,7 +283,7 @@ jobs: name: love-macos path: love-macos.zip - name: Run All Tests - run: love-macos/love.app/Contents/MacOS/love testing + run: love-macos/love.app/Contents/MacOS/love testing/main.lua - name: Love Test Report uses: ellraiser/love-test-report@main with: @@ -272,6 +292,7 @@ jobs: path: testing/output/lovetest_runAllTests.md iOS-Simulator: runs-on: macos-latest + timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index f84038cd7..3f5288d45 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,4 @@ stamp-h1 /testing/output/*.xml /testing/output/*.html /testing/output/*.md +/testing/output/actual/*.png diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 9b355a6bb..ad3a742e6 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -33,9 +33,13 @@ TestMethod = { blue = {0, 0, 1, 1}, bluefade = {0, 0, 1, 0.5}, yellow = {1, 1, 0, 1}, + pink = {1, 0, 1, 1}, black = {0, 0, 0, 1}, - white = {1, 1, 1, 1} + white = {1, 1, 1, 1}, + lovepink = {214/255, 86/255, 151/255, 1}, + loveblue = {83/255, 168/255, 220/255, 1} }, + imgs = 1, delay = 0, delayed = false } @@ -82,6 +86,10 @@ TestMethod = { tg = math.floor((tg*10)+0.5)/10 tb = math.floor((tb*10)+0.5)/10 ta = math.floor((ta*10)+0.5)/10 + col[1] = math.floor((col[1]*10)+0.5)/10 + col[2] = math.floor((col[2]*10)+0.5)/10 + col[3] = math.floor((col[3]*10)+0.5)/10 + col[4] = math.floor((col[4]*10)+0.5)/10 -- @TODO add some sort pixel tolerance to the coords self:assertEquals(col[1], tr, 'check pixel r for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') self:assertEquals(col[2], tg, 'check pixel g for ' .. i .. ' at ' .. compare_id .. '(' .. label .. ')') @@ -227,6 +235,14 @@ TestMethod = { end, + exportImg = function(self, imgdata) + local path = 'tempoutput/actual/love.test.graphics.' .. + self.method .. '-' .. tostring(self.imgs) .. '.png' + imgdata:encode('png', path) + self.imgs = self.imgs + 1 + end, + + -- @method - TestMethod:skipTest() -- @desc - used to mark this test as skipped for a specific reason -- @param {string} reason - reason why method is being skipped @@ -356,11 +372,21 @@ TestMethod = { -- unused currently, adds a preview image for certain graphics methods to the output local preview = '' - -- if self.testmodule.module == 'graphics' then - -- local filename = 'love_test_graphics_rectangle' - -- preview = '
    ' .. '

    Expected

    ' .. - -- '

    Actual

    ' - -- end + if self.testmodule.module == 'graphics' then + local filename = 'love.test.graphics.' .. self.method + if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-1.png', 'r') then + preview = '
    ' .. '

    Expected

    ' .. + '
    ' .. '

    Actual

    ' + end + if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-2.png', 'r') then + preview = preview .. '
    ' .. '

    Expected

    ' .. + '
    ' .. '

    Actual

    ' + end + if love.filesystem.openFile('tempoutput/actual/' .. filename .. '-3.png', 'r') then + preview = preview .. '
    ' .. '

    Expected

    ' .. + '
    ' .. '

    Actual

    ' + end + end -- append HTML for the test class result local status = '🔴' diff --git a/testing/classes/TestModule.lua b/testing/classes/TestModule.lua index 89fd1f7fa..dae7d82ed 100644 --- a/testing/classes/TestModule.lua +++ b/testing/classes/TestModule.lua @@ -88,7 +88,7 @@ TestModule = { if self.failed == 0 then status = '🟢' end -- add md row to main output love.test.mdrows = love.test.mdrows .. '| ' .. status .. - ' love.' .. self.module .. + ' ' .. self.module .. ' | ' .. tostring(self.passed) .. ' | ' .. tostring(self.failed) .. ' | ' .. tostring(self.skipped) .. diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 8d9ce368c..cbe171c31 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -187,8 +187,6 @@ TestSuite = { '
  • 🟡 ' .. tostring(self.totals[3]) .. ' Skipped
  • ' .. '
  • ' .. finaltime .. 's


' - -- @TODO use mountFullPath to write output to src? - love.filesystem.mountFullPath(love.filesystem.getSource() .. "/output", "tempoutput", "readwrite") love.filesystem.write('tempoutput/' .. self.output .. '.xml', xml .. self.xml .. '') love.filesystem.write('tempoutput/' .. self.output .. '.html', html .. self.html .. '') love.filesystem.write('tempoutput/' .. self.output .. '.md', md) diff --git a/testing/main.lua b/testing/main.lua index 292ad82c6..523d536d6 100644 --- a/testing/main.lua +++ b/testing/main.lua @@ -53,6 +53,9 @@ love.load = function(args) end end + -- mount for output later + love.filesystem.mountFullPath(love.filesystem.getSource() .. "/output", "tempoutput", "readwrite") + -- get all args with any comma lists split out as seperate local arglist = {} for a=1,#args do diff --git a/testing/output/actual/notes.txt b/testing/output/actual/notes.txt new file mode 100644 index 000000000..2716b1df8 --- /dev/null +++ b/testing/output/actual/notes.txt @@ -0,0 +1,2 @@ +# Actual Graphics Output +The images generated by the tests \ No newline at end of file diff --git a/testing/output/expected/love.test.graphics.applyTransform-1.png b/testing/output/expected/love.test.graphics.applyTransform-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f80ad8f855197459002a951418f9f3634fb4fb80 GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9E0F%rz##p<7bL>x>Eakt hF()}8AVGnZfr0e{gJSsX)Tclh22WQ%mvv4FO#qOZ5*7de literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.arc-1.png b/testing/output/expected/love.test.graphics.arc-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f95e65bb33dc252eb431a6b7164b2b30ff5773aa GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^S0Mc#1Q`A^Fho4oUk2na z@pN$vshE>{!I0~ag8=J=`56M*x|7abyQlm{km*@Er&!n{RTh6i8%HVq#J(rI*X)xO z6#O>#&z+l?&XAJQ;OaVsPpEZnYr`#Lri@e?xqV@w~2ZFHYN= zuhJ4NS~;&*9a_v7<|Lgdal^H?uGv<9qG_3v{7sJ6(*pPMpRjh8n8@GunByvUx_rQn npC=Bz@b1|2TWHgadk5G*9Wpmg`o*jbbT5OatDnm{r-UW||0G#e literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.arc-2.png b/testing/output/expected/love.test.graphics.arc-2.png new file mode 100644 index 0000000000000000000000000000000000000000..f0ae7e649bb82c4412e1cb92901f75f97965acdf GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^S0Mc#2tXtQ<6_YWAivtv z#WAE}PH*2v!3G5$*Zs?{MeX44OL%P8_kcsJO1zopr04vs06951J literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.circle-1.png b/testing/output/expected/love.test.graphics.circle-1.png new file mode 100644 index 0000000000000000000000000000000000000000..dbc1304073622223d5f2bb98ed77014719033eb0 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv{s5m4S0Mc#h(G|uvRvry4iswe zba4!+m{U9HwBP{+4wtRWTbVuC5AtpKKdWhx+a}|i()nUf78l3bbv51o)ahb*E5c*L z#tEDm-jgqJyIo3D;JUUTRK!64LAs4+KtXANw#VrO(`*_fyh2YiE!|qh5O#n)V^RGF z&&EX`)@1TTwLeU#i4j;MFs&!O!TF%(#~aVAZTM5HlPCPzv=QhQ22WQ%mvv4FO#mnc BPe=d& literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.clear-1.png b/testing/output/expected/love.test.graphics.clear-1.png new file mode 100644 index 0000000000000000000000000000000000000000..315c7a936f3dc201ea118e957e50a50e5f26b1f7 GIT binary patch literal 84 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;bAV5X>;L}@UB|w-0=Yb%E{-7; dbCMGjc!4|v21c>YSr>sU22WQ%mvv4FO#qBk5)l9Z literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.draw-1.png b/testing/output/expected/love.test.graphics.draw-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6318b14a4830af9a595dc40007227bb527446c7f GIT binary patch literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*K1+Z|1&TIuekI7|NmQB z3#EbLJ)SO(Ar*64&l&PH8wj{uWGv5&`DvqOz92#GrCRxk!WEOmTz&R1cfHs&X{mm8 zs=dghj-B#`Nw30RhR&bCZdAV|(JgUmnU2H?<)A`=pS5oH3w(n19$`Bd8W|<)ne||j zX;#0-F57EzEm86@>0dazZ4)=D&-*U^apAus`Ib80T8_@!a6?$E`cRU;^>c1l*IDI0 S;zl5MF?hQAxvX0!Gc6!x4C*Kq=@Op3OT}aP{sdam9~I zJC`uzUZjf@k#^=@RA@>s^xhhV19!Q}${Fgx7OcuCTy6_{Ht{dMpun2kEX(B;Gxy7XHik*j zjB+CGZzE))W_4WZ{?vG;Kz)|z#fCc_n-naRHvbVe_&kkASNdF*MV^a$!2)L^W-A7( dWAzdu;=9Vqo-SlubpdE6gQu&X%Q~loCIGzfJB9!N literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.intersectScissor-1.png b/testing/output/expected/love.test.graphics.intersectScissor-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7c40b8c9e8c4c8aeda3f0e8668d425043bee5049 GIT binary patch literal 91 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9>wh4Ffx&UH5J*D6)5S5Q jVovgd|K}Op|8puc#J-bJgTe~DWM4f&OH;7 literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.line-1.png b/testing/output/expected/love.test.graphics.line-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6fa77e263a1a310f430b69fe165a461122dd46ed GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9oB=)|uK)it{0Fib7&sPtECf=v zo-U3d6?2jWczJmfKSXWKQgptwDs(Q7*Q+}JDGSJi2&t;ucLK6T!h$e;r literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.origin-1.png b/testing/output/expected/love.test.graphics.origin-1.png new file mode 100644 index 0000000000000000000000000000000000000000..e018bbfbc4bf35f890c70e81e0aa15c5e1d21d21 GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9>wh4Ffx&UH5J-aG)5S5Q iVovgk|K~rYn_BGKs0d4pj>AVc_5(ahpq&kg_;GkCiCxvX
wh4Ffx&UH5J-aG)5S5Q iVovgk|K~r=*%m~z_9kWNcr}cvv&fmXYh3Ob6Mw<&;$Tsggnsz literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.push-1.png b/testing/output/expected/love.test.graphics.push-1.png new file mode 100644 index 0000000000000000000000000000000000000000..58ace03b31caf4aa1e1ceae60811a2cd1342efd5 GIT binary patch literal 91 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9>wh4Ffx&UH5J*D6)5S5Q jVoq|xhV%o>QWpdnG?wh4F;eXD;zkNVj(9^{+ kq+(8T!U2Xe>;fD>weHuLc|T^Xt^uj?boFyt=akR{047)!8vpx>Eakt hF()}8AVGnZfr0e{gJSsX)Tclh22WQ%mvv4FO#qOZ5*7de literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.rotate-1.png b/testing/output/expected/love.test.graphics.rotate-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7c40b8c9e8c4c8aeda3f0e8668d425043bee5049 GIT binary patch literal 91 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9>wh4Ffx&UH5J*D6)5S5Q jVovgd|K}Op|8puc#J-bJgTe~DWM4f&OH;7 literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setBlendMode-1.png b/testing/output/expected/love.test.graphics.setBlendMode-1.png new file mode 100644 index 0000000000000000000000000000000000000000..71ad3bdd94807a7db7a898e8f9ed2b2325871cd0 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHV5AX?b{oeorjEsy74F4G#7$n`r z;(<~uB|(0{|NsB5Zf!s$uV`#o%R<% OB@CXfelF{r5}E)E&>(vN literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setCanvas-1.png b/testing/output/expected/love.test.graphics.setCanvas-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a97348e509ee00fea8cf1432a82a5b89df82c91a GIT binary patch literal 84 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;bAV5X>wg9Y$w!>#KrWA`i(^Q| doa6)rULenafl;h;)fw97*a7OIYC53K!inzr>n`SsmY<~U_d}bfPjaA1y>gb7ZWF&qs9VeW`>R0oZ5*i RzOsW1@^tlcS?83{1OPg!9~S@s literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setColorMask-1.png b/testing/output/expected/love.test.graphics.setColorMask-1.png new file mode 100644 index 0000000000000000000000000000000000000000..254f834f807f381374e51f249e36e74ffcdd595f GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le v|NNi-(4LvKp;PGWVzwSBgRBDyMhpx|vzcWNpM1UxsF1wh4Ffx&UH5J*Da)5S5Q zVovgg|K~USw?Evso9A}&L5>|Gz_k!R?dO&7D4LHh{Evy85}Sb4q9e0Pq?g Ai2wiq literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setLineJoin-1.png b/testing/output/expected/love.test.graphics.setLineJoin-1.png new file mode 100644 index 0000000000000000000000000000000000000000..76397bdbe9e4cb23caefb88287bf919b8d6d9da6 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9JOMr-uK$4y28RD2>OVu!Q9B^5 z>FMGaQZXkvA%TN8H6cNOH)%)oHszVuc`#g7d@ OO$?r{elF{r5}E*@EFo6_ literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setLineStyle-1.png b/testing/output/expected/love.test.graphics.setLineStyle-1.png new file mode 100644 index 0000000000000000000000000000000000000000..9df1b38176469edd331bb69b5c15855e6b536363 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9oB=)|uK$4y28K-x3_Rb?e+9B6 vJY5_^D&{07Ff;}zI4FfNGPXEOR`6k9s9i2LRov399HiXS)z4*}Q$iB}1wt1E literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setLineWidth-1.png b/testing/output/expected/love.test.graphics.setLineWidth-1.png new file mode 100644 index 0000000000000000000000000000000000000000..ce30d2cfe919586b3897bd2956f0f14623c430a8 GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9JOMr-uK$4y28RD2>OVu!Q9B^5 z>gnPbQZXkvAwhsQl|gu+qC?WvRVz=pWQa`o@&CUzo1j$xTn2^(cNGKgcU4XSY4>#X Kb6Mw<&;$TWV<9O3 literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setScissor-1.png b/testing/output/expected/love.test.graphics.setScissor-1.png new file mode 100644 index 0000000000000000000000000000000000000000..202f26d04f4fd146dd215e9d609c5d286939c111 GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9>wh4Ffx&UH5J-a0)5S5Q hVoq|xkMj;(Oblhm`9D5sSG)mI;pyt_~=6Vm_y literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setShader-1.png b/testing/output/expected/love.test.graphics.setShader-1.png new file mode 100644 index 0000000000000000000000000000000000000000..315c7a936f3dc201ea118e957e50a50e5f26b1f7 GIT binary patch literal 84 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;bAV5X>;L}@UB|w-0=Yb%E{-7; dbCMGjc!4|v21c>YSr>sU22WQ%mvv4FO#qBk5)l9Z literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setStencilTest-1.png b/testing/output/expected/love.test.graphics.setStencilTest-1.png new file mode 100644 index 0000000000000000000000000000000000000000..773650483e3fc116451895a7d9a769351601bfcc GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9E0F%rz##p<7bK$K>Eakt zF()~Jf%zFT&mVb-C-n^z{>rm7bucV#;5xv-pf{E0tZnl~U!YnBPgg&ebxsLQ0AyGi A5&!@I literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setWireframe-1.png b/testing/output/expected/love.test.graphics.setWireframe-1.png new file mode 100644 index 0000000000000000000000000000000000000000..ceea66531e124bd8a373e27a938f70537b8a89c5 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9E0F&GpP}P+K>(0t>gnPb zQZa}3)J9&Qa+izqwMD#?BaR5RUg9vDC=pZfm04rD>N1H%-D;~o9OO-(Q*flQ_J8dX XTXsI7l5JOj1~7QK`njxgN@xNAeg7o< literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.shear-1.png b/testing/output/expected/love.test.graphics.shear-1.png new file mode 100644 index 0000000000000000000000000000000000000000..36a779c57416abdc435ab92f97dcd8a83d87af63 GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9E0F%rz##p<7bGI?>Eakt rF(-LNLc)aPgoONrgqi~mEDQ{Rtc?GiTT}l5l`wd^`njxgN@xNAg6J0G literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.shear-2.png b/testing/output/expected/love.test.graphics.shear-2.png new file mode 100644 index 0000000000000000000000000000000000000000..3d1873ea5604756786337a8e5c2f1541c57b4f8d GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9E0F%rz##p<7bGI(>Eakt uF()}8At8fdF>}Hc1~;|@6$ZBz3=GW|m=BhJINbwh4Ffx&UH5J*DE)5S5Q mVovgkf9F5Qb1p126kxbAN$%#^nTJe3syto&T-G@yGywn}=@wi7 literal 0 HcmV?d00001 diff --git a/testing/output/expected/notes.txt b/testing/output/expected/notes.txt new file mode 100644 index 000000000..25b54bba5 --- /dev/null +++ b/testing/output/expected/notes.txt @@ -0,0 +1,2 @@ +# Expected Graphics Output +The images expected by the tests \ No newline at end of file diff --git a/testing/output/readme.md b/testing/output/notes.txt similarity index 100% rename from testing/output/readme.md rename to testing/output/notes.txt diff --git a/testing/resources/loveinv.png b/testing/resources/loveinv.png new file mode 100644 index 0000000000000000000000000000000000000000..7be943a20fb70f11f5969fa6548bf70cc90608dc GIT binary patch literal 680 zcmV;Z0$2TsP)Px%Vo5|nRCt{2o7+*tFc3vAv;sfS4h*3LsDmP)1i}Cf&9(vG=YF z@%7T0>Fr z7M27`Bhl~{h6Hy5z2Gfg3CEs;d&2|3`_;Yc9GV5p0p8+~&{RHifxmlw+j@QebX(0+ zT>*1}A4^LmR2gf5e_owz{=Qs)(T+*4{xCI_Q2fPO_#s4^DX5xb_6Y#WB@}&$32#Y( zYL3alTS_Ekzo3A(7*NeIAFGF&)5%KM`=Juv6Q+d859SJQVM!Pr2IoA~wPtFF+_B;v z>LOEH1;B14Y*oO2yz*(%N^so_{fBG>9KzMN469(NfZiw2I|nadYe?|?ADH_Op<#wY z;ZgzV8-Jk+SXUnyseoQfRU$HWKR~+~vZ$+|_3BUE3{h`~Eh-6Yct9{AVqr^AzyqQw zF$+tA3LX$nidwu9l<8FF4Q!4>;Ecn1otzc3R;9!U75J^LcMP@BnFvOfLyuc!0P_ zDp~>q9w0B1i;}>C2LuZx)e@NSfM}_#N&*`m5H6NxOHjZA;^p!z2`YFXV8eu0f)XAG z+A`BBK@ATCZkno<5CIPaZ<{NX5Cso(*f^P!5D5=-+&Y_zhz4J> Date: Mon, 9 Oct 2023 20:22:04 -0300 Subject: [PATCH 055/409] vulkan: don't hold onto ImageData references after loading an image. Reduces CPU memory usage. --- src/modules/graphics/vulkan/Texture.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 6ae53c1c1..8a979789c 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -41,6 +41,10 @@ Texture::Texture(love::graphics::Graphics *gfx, const Settings &settings, const slices = *data; loadVolatile(); + + // ImageData is referenced by the first loadVolatile call, but we don't + // hang on to it after that so we can save memory. + slices.clear(); } bool Texture::loadVolatile() From ba693500c439b7bf5d7b9bb2f8b34d7331793453 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Wed, 11 Oct 2023 22:05:33 -0300 Subject: [PATCH 056/409] Fix love.font.newBMFontRasterizer when it's given a single file param. --- src/modules/font/wrap_Font.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/font/wrap_Font.cpp b/src/modules/font/wrap_Font.cpp index 1ed3149a1..ffbb720fe 100644 --- a/src/modules/font/wrap_Font.cpp +++ b/src/modules/font/wrap_Font.cpp @@ -154,7 +154,7 @@ int w_newBMFontRasterizer(lua_State *L) lua_pop(L, 1); } } - else + else if (!lua_isnoneornil(L, 2)) { convimagedata(L, 2); image::ImageData *id = luax_checktype(L, 2); From 0b0bef31add03f6bd68c5ba029fb31fb498743a3 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Thu, 12 Oct 2023 13:33:28 +0800 Subject: [PATCH 057/409] Linux: Install libcurl4-openssl-dev before building. --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 50c0236c1..f3922d769 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,8 @@ jobs: libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ - libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev + libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ + libcurl4-openssl-dev - name: Checkout love-appimage-source uses: actions/checkout@v3 with: From 386586835851c586c5482b73898b5eb7249d7670 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Fri, 13 Oct 2023 21:41:32 -0300 Subject: [PATCH 058/409] Fix creating a linear rgba8 canvas when gamma correct rendering is on. Fixes #1973 --- src/modules/graphics/Texture.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index e9b7ab1f7..d70bf1d8b 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -168,7 +168,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) , computeWrite(settings.computeWrite) , readable(true) , mipmapsMode(settings.mipmaps) - , sRGB(isGammaCorrect() && !settings.linear) + , sRGB(false) , width(settings.width) , height(settings.height) , depth(settings.type == TEXTURE_VOLUME ? settings.layers : 1) @@ -204,7 +204,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) love::image::ImageDataBase *slice = slices->get(0, 0); format = slice->getFormat(); - if (sRGB) + if (isGammaCorrect() && !settings.linear) format = getSRGBPixelFormat(format); pixelWidth = slice->getWidth(); @@ -236,6 +236,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) readable = !renderTarget || !isPixelFormatDepthStencil(format); format = gfx->getSizedFormat(format, renderTarget, readable); + sRGB = isPixelFormatSRGB(format) || (isCompressed() && isGammaCorrect() && !settings.linear); if (mipmapsMode == MIPMAPS_AUTO && isCompressed()) mipmapsMode = MIPMAPS_MANUAL; From 983ea6c0e6885b169e2c89ad145fc1c6a220f931 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Fri, 13 Oct 2023 21:53:45 -0300 Subject: [PATCH 059/409] Remove explicit support for systems that don't support rgba8 canvases. This is just a very small number of really old OpenGL ES 2 drivers. --- src/modules/graphics/Graphics.cpp | 16 ++++++++++++ src/modules/graphics/Graphics.h | 2 +- src/modules/graphics/Texture.cpp | 2 +- src/modules/graphics/metal/Graphics.h | 1 - src/modules/graphics/metal/Graphics.mm | 23 ++---------------- src/modules/graphics/opengl/Graphics.cpp | 31 ++---------------------- src/modules/graphics/opengl/Graphics.h | 1 - src/modules/graphics/vulkan/Graphics.cpp | 21 +--------------- src/modules/graphics/vulkan/Graphics.h | 1 - 9 files changed, 23 insertions(+), 75 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 098c886cc..be2b979e0 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -2389,6 +2389,22 @@ const Graphics::Capabilities &Graphics::getCapabilities() const return capabilities; } +PixelFormat Graphics::getSizedFormat(PixelFormat format) const +{ + switch (format) + { + case PIXELFORMAT_NORMAL: + if (isGammaCorrect()) + return PIXELFORMAT_RGBA8_UNORM_sRGB; + else + return PIXELFORMAT_RGBA8_UNORM; + case PIXELFORMAT_HDR: + return PIXELFORMAT_RGBA16_FLOAT; + default: + return format; + } +} + Graphics::Stats Graphics::getStats() const { Stats stats; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 456e5d28f..f9a51eab3 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -819,7 +819,7 @@ public: /** * Converts PIXELFORMAT_NORMAL and PIXELFORMAT_HDR into a real format. **/ - virtual PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const = 0; + PixelFormat getSizedFormat(PixelFormat format) const; /** * Gets whether the specified pixel format usage is supported. diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index d70bf1d8b..5cda31dae 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -235,7 +235,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) else readable = !renderTarget || !isPixelFormatDepthStencil(format); - format = gfx->getSizedFormat(format, renderTarget, readable); + format = gfx->getSizedFormat(format); sRGB = isPixelFormatSRGB(format) || (isCompressed() && isGammaCorrect() && !settings.linear); if (mipmapsMode == MIPMAPS_AUTO && isCompressed()) diff --git a/src/modules/graphics/metal/Graphics.h b/src/modules/graphics/metal/Graphics.h index ab2e8fc2b..ea8894f4c 100644 --- a/src/modules/graphics/metal/Graphics.h +++ b/src/modules/graphics/metal/Graphics.h @@ -110,7 +110,6 @@ public: void setWireframe(bool enable) override; - PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override; bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override; Renderer getRenderer() const override; bool usesGLSLES() const override; diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index f07433cd6..ca6c76b82 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -1864,28 +1864,9 @@ void Graphics::setWireframe(bool enable) } } -PixelFormat Graphics::getSizedFormat(PixelFormat format, bool /*rendertarget*/, bool /*readable*/) const -{ - switch (format) - { - case PIXELFORMAT_NORMAL: - if (isGammaCorrect()) - return PIXELFORMAT_RGBA8_UNORM_sRGB; - else - return PIXELFORMAT_RGBA8_UNORM; - case PIXELFORMAT_HDR: - return PIXELFORMAT_RGBA16_FLOAT; - default: - return format; - } -} - bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) { - bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0; - bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0; - - format = getSizedFormat(format, rendertarget, readable); + format = getSizedFormat(format); if (sRGB) format = getSRGBPixelFormat(format); @@ -1902,7 +1883,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG uint32 flags = PIXELFORMATUSAGEFLAGS_NONE; - if (isPixelFormatCompressed(format) && rendertarget) + if (isPixelFormatCompressed(format) && (usage & rt) != 0) return false; // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 50f0a3e79..651978742 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1734,31 +1734,6 @@ void Graphics::initCapabilities() } } -PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const -{ - uint32 requiredflags = 0; - if (rendertarget) - requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET; - if (readable) - requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE; - - switch (format) - { - case PIXELFORMAT_NORMAL: - if (isGammaCorrect()) - return PIXELFORMAT_RGBA8_UNORM_sRGB; - else if ((OpenGL::getPixelFormatUsageFlags(PIXELFORMAT_RGBA8_UNORM) & requiredflags) != requiredflags) - // 32-bit render targets don't have guaranteed support on GLES2. - return PIXELFORMAT_RGBA4_UNORM; - else - return PIXELFORMAT_RGBA8_UNORM; - case PIXELFORMAT_HDR: - return PIXELFORMAT_RGBA16_FLOAT; - default: - return format; - } -} - uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable) { uint32 usage = OpenGL::getPixelFormatUsageFlags(format); @@ -1844,11 +1819,9 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG if (sRGB) format = getSRGBPixelFormat(format); - bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0; + format = getSizedFormat(format); + bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0; - - format = getSizedFormat(format, rendertarget, readable); - return (usage & pixelFormatUsage[format][readable ? 1 : 0]) == usage; } diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 997239c15..d27c96791 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -106,7 +106,6 @@ public: void setWireframe(bool enable) override; - PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override; bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override; Renderer getRenderer() const override; bool usesGLSLES() const override; diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index b51db2154..39228f335 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -1057,28 +1057,9 @@ void Graphics::setWireframe(bool enable) states.back().wireframe = enable; } -PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const -{ - switch (format) - { - case PIXELFORMAT_NORMAL: - if (isGammaCorrect()) - return PIXELFORMAT_RGBA8_UNORM_sRGB; - else - return PIXELFORMAT_RGBA8_UNORM; - case PIXELFORMAT_HDR: - return PIXELFORMAT_RGBA16_FLOAT; - default: - return format; - } -} - bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) { - bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0; - bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0; - - format = getSizedFormat(format, rendertarget, readable); + format = getSizedFormat(format); auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB); diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 7d90542b8..69ae238b5 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -297,7 +297,6 @@ public: void setBlendState(const BlendState &blend) override; void setPointSize(float size) override; void setWireframe(bool enable) override; - PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override; bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) override; Renderer getRenderer() const override; bool usesGLSLES() const override; From 9eec1754e76d150067d02787a18a912b9e7d3132 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 14 Oct 2023 10:30:51 -0300 Subject: [PATCH 060/409] opengl: fix clearing the depth buffer. --- src/modules/graphics/opengl/OpenGL.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index ad8a4b66e..9166b8c9f 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -101,8 +101,8 @@ OpenGL::CleanClearState::CleanClearState(GLbitfield clearFlags) if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX) gl.setColorWriteMask(LOVE_UINT32_MAX); - if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && depthWrites) - gl.setDepthWrites(false); + if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && !depthWrites) + gl.setDepthWrites(true); if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF) gl.setStencilWriteMask(LOVE_UINT32_MAX); @@ -116,7 +116,7 @@ OpenGL::CleanClearState::~CleanClearState() if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX) gl.setColorWriteMask(colorWriteMask); - if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && depthWrites) + if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && !depthWrites) gl.setDepthWrites(depthWrites); if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF) From 09d0ace4b68cc7c28252dd9c3e6d1c78970fc000 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Sat, 14 Oct 2023 18:18:53 +0100 Subject: [PATCH 061/409] finished a bunch of modules - finished audio module - finished data module - finished filesystem module - finished font module (note: glphy test fails, but seems to be a 12.0 issue) - finished image module - finished maths module - finished sound module - finished thread module - finished video module - fixed pcall error not showing in results for invalid test code --- .github/workflows/main.yml | 177 ++- testing/classes/TestMethod.lua | 65 +- testing/classes/TestSuite.lua | 11 +- testing/examples/lovetest_runAllTests.html | 2 +- testing/examples/lovetest_runAllTests.md | 38 +- testing/examples/lovetest_runAllTests.xml | 1239 +++++++++++--------- testing/main.lua | 28 +- testing/readme.md | 117 +- testing/resources/alsoft.conf | 4 + testing/resources/clickmono.ogg | Bin 0 -> 3883 bytes testing/tests/audio.lua | 170 ++- testing/tests/data.lua | 86 +- testing/tests/event.lua | 9 +- testing/tests/filesystem.lua | 104 +- testing/tests/font.lua | 74 +- testing/tests/graphics.lua | 217 +++- testing/tests/image.lua | 79 +- testing/tests/math.lua | 156 ++- testing/tests/objects.lua | 411 ------- testing/tests/physics.lua | 88 +- testing/tests/sound.lua | 70 +- testing/tests/system.lua | 7 + testing/tests/thread.lua | 108 +- testing/tests/timer.lua | 7 + testing/tests/video.lua | 36 +- testing/tests/window.lua | 86 +- testing/todo.md | 43 +- 27 files changed, 2169 insertions(+), 1263 deletions(-) create mode 100644 testing/resources/alsoft.conf create mode 100644 testing/resources/clickmono.ogg delete mode 100644 testing/tests/objects.lua diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5229bdaf8..9ce1d327b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,8 +3,10 @@ on: [push, pull_request] jobs: linux-os: - runs-on: ubuntu-20.04 - timeout-minutes: 60 + runs-on: ubuntu-22.04 + env: + ALSOFT_CONF: resources/alsoft.conf + DISPLAY: :99 steps: - name: Update APT run: sudo apt-get update @@ -16,7 +18,9 @@ jobs: libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ - libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev + libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ + libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ + vulkan-validationlayers - name: Checkout love-appimage-source uses: actions/checkout@v3 with: @@ -55,17 +59,82 @@ jobs: chmod a+x love-${{ github.sha }}.AppImage echo "ready to run" ls - - name: Run All Tests + - name: Start xvfb and openbox + run: | + echo "Starting XVFB on $DISPLAY" + Xvfb $DISPLAY -screen 0, 360x240x24 & + echo "XVFBPID=$!" >> $GITHUB_ENV + # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) + sleep 3 + openbox & + echo "OPENBOXPID=$!" >> $GITHUB_ENV + # linux opengl tests + - name: Run All Tests (opengl) run: xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua - - name: Love Test Report + - name: Love Test Report (opengl) uses: ellraiser/love-test-report@main with: name: Love Testsuite Linux - title: linux-test-report + title: test-report-linux-opengl path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengl) + run: | + 7z a -tzip test-output-linux-opengl.zip testing/output/ + - name: Artifact Test Output (opengl) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-opengl + path: test-output-linux-opengl.zip + # linux opengles tests + - name: Run Test Suite (opengles) + run: | + export LOVE_GRAPHICS_USE_OPENGLES=1 + xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua + - name: Love Test Report (opengles) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-opengles + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengles) + run: | + 7z a -tzip test-output-linux-opengles.zip testing/output/ + - name: Artifact Test Output (opengles) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-opengles + path: test-output-linux-opengles.zip + # linux vulkan tests + - name: Run Test Suite (vulkan) + run: | + export LOVE_GRAPHICS_DEBUG=1 + xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua --runAllTests --renderers vulkan + - name: Love Test Report (vulkan) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-vulkan + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (vulkan) + run: | + 7z a -tzip test-output-linux-vulkan.zip testing/output/ + - name: Artifact Test Output (vulkan) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-vulkan + path: test-output-linux-vulkan.zip + - name: Stop xvfb and openbox + # should always stop xvfb and openbox even if other steps failed + if: always() + run: | + kill $XVFBPID + kill $OPENBOXPID windows-os: runs-on: windows-latest - timeout-minutes: 60 + env: + ALSOFT_CONF: resources/alsoft.conf + VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json + VULKAN_SDK: C:/VulkanSDK/1.3.231.1 strategy: matrix: platform: [Win32, x64, ARM64] @@ -220,19 +289,6 @@ jobs: with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb - - name: Install Scream - shell: powershell - run: | - Start-Service audio* - Invoke-WebRequest https://github.com/duncanthrax/scream/releases/download/3.6/Scream3.6.zip -OutFile C:\Scream3.6.zip - Extract-7Zip -Path C:\Scream3.6.zip -DestinationPath C:\Scream - $cert = (Get-AuthenticodeSignature C:\Scream\Install\driver\Scream.sys).SignerCertificate - $store = [System.Security.Cryptography.X509Certificates.X509Store]::new("TrustedPublisher", "LocalMachine") - $store.Open("ReadWrite") - $store.Add($cert) - $store.Close() - cd C:\Scream\Install\driver - C:\Scream\Install\helpers\devcon install Scream.inf *Scream - name: Install Mesa run: | curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z @@ -241,21 +297,78 @@ jobs: - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - - name: Run All Tests + - name: Run Tests (opengl) if: steps.vars.outputs.arch != 'ARM64' run: | dir powershell.exe ./install/lovec.exe ./testing/main.lua - - name: Love Test Report + # windows opengl test + - name: Love Test Report (opengl) if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: - name: Love Testsuite Windows - title: windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-test-report + name: Love Testsuite Windows (opengl) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengl) + run: | + 7z a -tzip test-output-windows-opengl.zip testing/output/ + - name: Artifact Test Output (opengl) + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-opengl + path: test-output-windows-opengl.zip + # windows opengles test + - name: Run Tests (opengles) + run: | + $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 + powershell.exe ./install/lovec.exe ./testing/main.lua + - name: Love Test Report (opengles) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (opengles) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengles) + run: | + 7z a -tzip test-output-windows-opengles.zip testing/output/ + - name: Artifact Test Output (opengles) + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-opengles + path: test-output-windows-opengles.zip + - name: Install Vulkan + run: | + curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe + ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma + curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip + 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" + reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 + powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary + # windows vulkan tests + - name: Run Tests (vulkan) + run: | + $ENV:LOVE_GRAPHICS_DEBUG=1 + powershell.exe ./install/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan + - name: Love Test Report (vulkan) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (vulkan) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (vulkan) + run: | + 7z a -tzip test-output-windows-vulkan.zip testing/output + - name: Artifact Test Output (vulkan) + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-vulkan + path: test-output-windows-vulkan.zip macOS: runs-on: macos-latest - timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 @@ -282,17 +395,25 @@ jobs: with: name: love-macos path: love-macos.zip - - name: Run All Tests + # macos opengl tests + - name: Run Tests run: love-macos/love.app/Contents/MacOS/love testing/main.lua - name: Love Test Report uses: ellraiser/love-test-report@main with: name: Love Testsuite MacOS - title: macos-test-report + title: test-report-macos path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output + run: | + 7z a -tzip test-output-macos-opengl.zip testing/output/ + - name: Artifact Test Output + uses: actions/upload-artifact@v3 + with: + name: test-output-macos-opengl + path: test-output-macos-opengl.zip iOS-Simulator: runs-on: macos-latest - timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index ad3a742e6..4c7705693 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -41,7 +41,8 @@ TestMethod = { }, imgs = 1, delay = 0, - delayed = false + delayed = false, + store = {} } setmetatable(test, self) self.__index = self @@ -58,11 +59,11 @@ TestMethod = { assertEquals = function(self, expected, actual, label) self.count = self.count + 1 table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = expected == actual, message = 'expected \'' .. tostring(expected) .. '\' got \'' .. tostring(actual) .. '\'', - test = label + test = label or 'no label given' }) end, @@ -109,11 +110,11 @@ TestMethod = { assertNotEquals = function(self, expected, actual, label) self.count = self.count + 1 table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = expected ~= actual, message = 'avoiding \'' .. tostring(expected) .. '\' got \'' .. tostring(actual) .. '\'', - test = label + test = label or 'no label given' }) end, @@ -128,11 +129,11 @@ TestMethod = { assertRange = function(self, actual, min, max, label) self.count = self.count + 1 table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = actual >= min and actual <= max, message = 'value \'' .. tostring(actual) .. '\' out of range \'' .. tostring(min) .. '-' .. tostring(max) .. '\'', - test = label + test = label or 'no label given' }) end, @@ -150,11 +151,11 @@ TestMethod = { if list[l] == actual then found = true end; end table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = found == true, message = 'value \'' .. tostring(actual) .. '\' not found in \'' .. table.concat(list, ',') .. '\'', - test = label + test = label or 'no label given' }) end, @@ -172,11 +173,11 @@ TestMethod = { passing = actual >= target end table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = passing, message = 'value \'' .. tostring(actual) .. '\' not >= \'' .. tostring(target) .. '\'', - test = label + test = label or 'no label given' }) end, @@ -194,11 +195,11 @@ TestMethod = { passing = actual <= target end table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = passing, message = 'value \'' .. tostring(actual) .. '\' not <= \'' .. tostring(target) .. '\'', - test = label + test = label or 'no label given' }) end, @@ -206,7 +207,7 @@ TestMethod = { -- @method - TestMethod:assertObject() -- @desc - used to check a table is a love object, this runs 3 seperate -- tests to check table has the basic properties of an object - -- @note - actual object functionality tests are done in the objects module + -- @note - actual object functionality tests have their own methods -- @param {table} obj - table to check is a valid love object -- @return {nil} assertObject = function(self, obj) @@ -218,6 +219,29 @@ TestMethod = { end, + -- @method - TestMethod:assertCoords() + -- @desc - used to check a pair of values (usually coordinates) + -- @param {table} obj - table to check is a valid love object + -- @return {nil} + assertCoords = function(self, expected, actual, label) + self.count = self.count + 1 + local passing = false + if expected ~= nil and actual ~= nil then + if expected[1] == actual[1] and expected[2] == actual[2] then + passing = true + end + end + table.insert(self.asserts, { + key = 'assert ' .. tostring(self.count), + passed = passing, + message = 'expected \'' .. tostring(expected[1]) .. 'x,' .. + tostring(expected[2]) .. 'y\' got \'' .. + tostring(actual[1]) .. 'x,' .. tostring(actual[2]) .. 'y\'', + test = label or 'no label given' + }) + end, + + -- @method - TestMethod:assertNotNil() -- @desc - quick assert for value not nil -- @param {any} value - value to check not nil @@ -226,7 +250,7 @@ TestMethod = { self:assertNotEquals(nil, value, 'check not nil') if err ~= nil then table.insert(self.asserts, { - key = 'assert #' .. tostring(self.count), + key = 'assert ' .. tostring(self.count), passed = false, message = err, test = 'assert not nil catch' @@ -235,6 +259,10 @@ TestMethod = { end, + -- @method - TestMethod:exportImg() + -- @desc - used to export actual test img results to compare to the expected + -- @param {table} imgdata - imgdata to save as a png + -- @return {nil} exportImg = function(self, imgdata) local path = 'tempoutput/actual/love.test.graphics.' .. self.method .. '-' .. tostring(self.imgs) .. '.png' @@ -320,12 +348,17 @@ TestMethod = { if failure['test'] ~= nil then key = key .. ' [' .. failure['test'] .. ']' end + local msg = failure['message'] + if self.fatal ~= '' then + key = 'code' + msg = self.fatal + end self.result = { total = total, result = 'FAIL', passed = false, key = key, - message = failure['message'] + message = msg } end end diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index cbe171c31..4ac04a4be 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -35,7 +35,6 @@ TestSuite = { joystick = {}, math = {}, mouse = {}, - objects = {}, -- special for all object class contructor tests physics = {}, sound = {}, system = {}, @@ -76,7 +75,7 @@ TestSuite = { TextRun:set('love.' .. self.module.module .. '.' .. method) -- check method exists in love first - if self.module.module ~= 'objects' and (love[self.module.module] == nil or love[self.module.module][method] == nil) then + if love[self.module.module] == nil then local tested = 'love.' .. self.module.module .. '.' .. method .. '()' local matching = string.sub(self.module.spacer, string.len(tested), 40) self.module:log(self.module.colors['FAIL'], @@ -87,7 +86,7 @@ TestSuite = { else local ok, chunk, err = pcall(self[self.module.module][method], self.test) if ok == false then - print("FATAL", chunk, err) + self.test.passed = false self.test.fatal = tostring(chunk) .. tostring(err) end end @@ -105,7 +104,7 @@ TestSuite = { if self.delayed.delay <= 0 then local ok, chunk, err = pcall(self[self.module.module][self.delayed.method], self.test) if ok == false then - print("FATAL", chunk, err) + self.test.passed = false self.test.fatal = tostring(chunk) .. tostring(err) end self.delayed = nil @@ -115,7 +114,7 @@ TestSuite = { -- now we're all done evaluate the test local ok, chunk, err = pcall(self.test.evaluateTest, self.test) if ok == false then - print("FATAL", chunk, err) + self.test.passed = false self.test.fatal = tostring(chunk) .. tostring(err) end -- save having to :release() anything we made in the last test @@ -169,7 +168,7 @@ TestSuite = { tostring(self.totals[1]) .. '** passed, **' .. tostring(self.totals[2]) .. '** failed, and **' .. tostring(self.totals[3]) .. '** skipped\n\n### Report\n' .. - '| Module | Passed | Failed | Skipped | Time |\n' .. + '| Module | Pass | Fail | Skip | Time |\n' .. '| --------------------- | ------ | ------ | ------- | ------ |\n' .. self.mdrows .. '\n\n### Failures\n' .. self.mdfailures diff --git a/testing/examples/lovetest_runAllTests.html b/testing/examples/lovetest_runAllTests.html index ac9b12d58..641d05999 100644 --- a/testing/examples/lovetest_runAllTests.html +++ b/testing/examples/lovetest_runAllTests.html @@ -1 +1 @@ -

🔴 love.test

  • 🟢 226 Tests
  • 🔴 2 Failures
  • 🟡 43 Skipped
  • 7.563s


🟢 love.audio

  • 🟢 26 Tests
  • 🔴 0 Failures
  • 🟡 0 Skipped
  • 0.006s


    • MethodTimeDetails
      🟢getActiveEffects0.000s
      🟢getActiveSourceCount0.001s
      🟢getDistanceModel0.000s
      🟢getDopplerScale0.000s
      🟢getEffect0.000s
      🟢getMaxSceneEffects0.000s
      🟢getMaxSourceEffects0.000s
      🟢getOrientation0.000s
      🟢getPosition0.000s
      🟢getRecordingDevices0.000s
      🟢getVelocity0.000s
      🟢getVolume0.000s
      🟢isEffectsSupported0.000s
      🟢newQueueableSource0.000s
      🟢newSource0.001s
      🟢pause0.001s
      🟢play0.001s
      🟢setDistanceModel0.000s
      🟢setDopplerScale0.000s
      🟢setEffect0.000s
      🟢setMixWithSystem0.000s
      🟢setOrientation0.000s
      🟢setPosition0.000s
      🟢setVelocity0.000s
      🟢setVolume0.000s
      🟢stop0.001s

      🟢 love.data

      • 🟢 7 Tests
      • 🔴 0 Failures
      • 🟡 3 Skipped
      • 0.001s


        • MethodTimeDetails
          🟢compress0.000s
          🟢decode0.000s
          🟢decompress0.000s
          🟢encode0.000s
          🟡getPackedSize0.000stest method needs writing
          🟢hash0.000s
          🟢newByteData0.000s
          🟢newDataView0.000s
          🟡pack0.000stest method needs writing
          🟡unpack0.000stest method needs writing

          🟢 love.event

          • 🟢 4 Tests
          • 🔴 0 Failures
          • 🟡 2 Skipped
          • 0.000s


            • MethodTimeDetails
              🟢clear0.000s
              🟢poll0.000s
              🟡pump0.000snot sure can be tested as used internally
              🟢push0.000s
              🟢quit0.000s
              🟡wait0.000stest method needs writing

              🟢 love.filesystem

              • 🟢 27 Tests
              • 🔴 0 Failures
              • 🟡 2 Skipped
              • 0.018s


                • MethodTimeDetails
                  🟢append0.002s
                  🟢areSymlinksEnabled0.000s
                  🟢createDirectory0.001s
                  🟢getAppdataDirectory0.000s
                  🟢getCRequirePath0.000s
                  🟢getDirectoryItems0.002s
                  🟢getIdentity0.000s
                  🟢getInfo0.002s
                  🟢getRealDirectory0.001s
                  🟢getRequirePath0.000s
                  🟢getSaveDirectory0.000s
                  🟡getSource0.000snot sure can be tested as used internally
                  🟢getSourceBaseDirectory0.000s
                  🟢getUserDirectory0.000s
                  🟢getWorkingDirectory0.000s
                  🟢isFused0.000s
                  🟢lines0.001s
                  🟢load0.001s
                  🟢mount0.002s
                  🟢newFileData0.000s
                  🟢openFile0.000s
                  🟢read0.000s
                  🟢remove0.002s
                  🟢setCRequirePath0.000s
                  🟢setIdentity0.000s
                  🟢setRequirePath0.000s
                  🟡setSource0.000snot sure can be tested as used internally
                  🟢unmount0.002s
                  🟢write0.002s

                  🟢 love.font

                  • 🟢 4 Tests
                  • 🔴 0 Failures
                  • 🟡 1 Skipped
                  • 0.002s


                    • MethodTimeDetails
                      🟡newBMFontRasterizer0.000swiki and source dont match, not sure expected usage
                      🟢newGlyphData0.001s
                      🟢newImageRasterizer0.000s
                      🟢newRasterizer0.000s
                      🟢newTrueTypeRasterizer0.000s

                      🟢 love.graphics

                      • 🟢 65 Tests
                      • 🔴 0 Failures
                      • 🟡 31 Skipped
                      • 0.079s


                        • MethodTimeDetails
                          🟢applyTransform0.002s
                          🟡arc0.000stest method needs writing
                          🟡captureScreenshot0.000scant test this worked (easily)
                          🟡circle0.000stest method needs writing
                          🟡clear0.000stest method needs writing
                          🟡discard0.000stest method needs writing
                          🟡draw0.000stest method needs writing
                          🟡drawInstanced0.000stest method needs writing
                          🟡drawLayer0.000stest method needs writing
                          🟡ellipse0.000stest method needs writing
                          🟡flushBatch0.000stest method needs writing
                          🟢getBackgroundColor0.000s
                          🟢getBlendMode0.000s
                          🟢getCanvas0.000s
                          🟢getColor0.000s
                          🟢getColorMask0.000s
                          🟢getDPIScale0.000s
                          🟢getDefaultFilter0.000s
                          🟢getDepthMode0.000s
                          🟢getDimensions0.000s
                          🟢getFont0.001s
                          🟢getFrontFaceWinding0.000s
                          🟢getHeight0.000s
                          🟢getLineJoin0.000s
                          🟢getLineStyle0.000s
                          🟢getLineWidth0.000s
                          🟢getMeshCullMode0.000s
                          🟢getPixelDimensions0.000s
                          🟢getPixelHeight0.000s
                          🟢getPixelWidth0.000s
                          🟢getPointSize0.000s
                          🟢getRendererInfo0.000s
                          🟢getScissor0.000s
                          🟢getShader0.000s
                          🟢getStackDepth0.000s
                          🟢getStats0.000s
                          🟢getStencilMode0.000s
                          🟢getSupported0.000s
                          🟢getSystemLimits0.000s
                          🟢getTextureFormats0.001s
                          🟢getTextureTypes0.000s
                          🟢getWidth0.000s
                          🟢intersectScissor0.003s
                          🟢inverseTransformPoint0.000s
                          🟢isActive0.000s
                          🟢isGammaCorrect0.000s
                          🟢isWireframe0.000s
                          🟡line0.000stest method needs writing
                          🟢newArrayImage0.002s
                          🟢newCanvas0.001s
                          🟢newCubeImage0.003s
                          🟢newFont0.001s
                          🟢newImage0.001s
                          🟢newImageFont0.001s
                          🟢newMesh0.000s
                          🟢newParticleSystem0.002s
                          🟢newQuad0.002s
                          🟢newShader0.015s
                          🟢newSpriteBatch0.001s
                          🟢newTextBatch0.002s
                          🟢newVideo0.004s
                          🟢newVolumeImage0.001s
                          🟢origin0.000s
                          🟡points0.000stest method needs writing
                          🟡polygon0.000stest method needs writing
                          🟢pop0.001s
                          🟡present0.000stest method needs writing
                          🟡print0.000stest method needs writing
                          🟡printf0.000stest method needs writing
                          🟢push0.002s
                          🟢rectangle0.007s
                          🟢replaceTransform0.002s
                          🟢reset0.001s
                          🟢rotate0.004s
                          🟢scale0.002s
                          🟢setBackgroundColor0.000s
                          🟡setBlendMode0.001stest method needs writing
                          🟡setCanvas0.000stest method needs writing
                          🟡setColor0.000stest method needs writing
                          🟡setColorMask0.000stest method needs writing
                          🟢setDefaultFilter0.000s
                          🟡setDepthMode0.000stest method needs writing
                          🟡setFont0.000stest method needs writing
                          🟡setFrontFaceWinding0.000stest method needs writing
                          🟡setLineJoin0.000stest method needs writing
                          🟡setLineStyle0.000stest method needs writing
                          🟡setLineWidth0.000stest method needs writing
                          🟡setMeshCullMode0.000stest method needs writing
                          🟡setScissor0.000stest method needs writing
                          🟡setShader0.000stest method needs writing
                          🟡setStencilMode0.000stest method needs writing
                          🟡setWireframe0.000stest method needs writing
                          🟢shear0.002s
                          🟢transformPoint0.000s
                          🟢translate0.001s
                          🟢validateShader0.010s

                          🟢 love.image

                          • 🟢 3 Tests
                          • 🔴 0 Failures
                          • 🟡 0 Skipped
                          • 0.002s


                            • MethodTimeDetails
                              🟢isCompressed0.001s
                              🟢newCompressedData0.001s
                              🟢newImageData0.000s

                              🟢 love.math

                              • 🟢 17 Tests
                              • 🔴 0 Failures
                              • 🟡 0 Skipped
                              • 0.003s


                                • MethodTimeDetails
                                  🟢colorFromBytes0.000s
                                  🟢colorToBytes0.001s
                                  🟢gammaToLinear0.000s
                                  🟢getRandomSeed0.000s
                                  🟢getRandomState0.000s
                                  🟢isConvex0.000s
                                  🟢linearToGamma0.000s
                                  🟢newBezierCurve0.000s
                                  🟢newRandomGenerator0.000s
                                  🟢newTransform0.000s
                                  🟢perlinNoise0.000s
                                  🟢random0.000s
                                  🟢randomNormal0.000s
                                  🟢setRandomSeed0.000s
                                  🟢setRandomState0.000s
                                  🟢simplexNoise0.000s
                                  🟢triangulate0.000s

                                  🟢 love.objects

                                  • 🟢 1 Tests
                                  • 🔴 0 Failures
                                  • 🟡 0 Skipped
                                  • 0.008s


                                    • MethodTimeDetails
                                      🟢File0.008s

                                      🟢 love.physics

                                      • 🟢 22 Tests
                                      • 🔴 0 Failures
                                      • 🟡 0 Skipped
                                      • 0.005s


                                        • MethodTimeDetails
                                          🟢getDistance0.000s
                                          🟢getMeter0.000s
                                          🟢newBody0.000s
                                          🟢newChainShape0.000s
                                          🟢newCircleShape0.000s
                                          🟢newDistanceJoint0.000s
                                          🟢newEdgeShape0.000s
                                          🟢newFixture0.000s
                                          🟢newFrictionJoint0.000s
                                          🟢newGearJoint0.000s
                                          🟢newMotorJoint0.000s
                                          🟢newMouseJoint0.000s
                                          🟢newPolygonShape0.000s
                                          🟢newPrismaticJoint0.000s
                                          🟢newPulleyJoint0.000s
                                          🟢newRectangleShape0.001s
                                          🟢newRevoluteJoint0.000s
                                          🟢newRopeJoint0.000s
                                          🟢newWeldJoint0.000s
                                          🟢newWheelJoint0.001s
                                          🟢newWorld0.000s
                                          🟢setMeter0.000s

                                          🟢 love.sound

                                          • 🟢 2 Tests
                                          • 🔴 0 Failures
                                          • 🟡 0 Skipped
                                          • 0.004s


                                            • MethodTimeDetails
                                              🟢newDecoder0.001s
                                              🟢newSoundData0.003s

                                              🟢 love.system

                                              • 🟢 6 Tests
                                              • 🔴 0 Failures
                                              • 🟡 2 Skipped
                                              • 0.007s


                                                • MethodTimeDetails
                                                  🟢getClipboardText0.006s
                                                  🟢getOS0.000s
                                                  🟢getPowerInfo0.000s
                                                  🟢getProcessorCount0.000s
                                                  🟢hasBackgroundMusic0.000s
                                                  🟡openURL0.000scant test this worked
                                                  🟢setClipboardText0.001s
                                                  🟡vibrate0.000scant test this worked

                                                  🟢 love.thread

                                                  • 🟢 3 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 0 Skipped
                                                  • 0.002s


                                                    • MethodTimeDetails
                                                      🟢getChannel0.000s
                                                      🟢newChannel0.000s
                                                      🟢newThread0.001s

                                                      🟢 love.timer

                                                      • 🟢 6 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 0 Skipped
                                                      • 2.002s


                                                        • MethodTimeDetails
                                                          🟢getAverageDelta0.000s
                                                          🟢getDelta0.000s
                                                          🟢getFPS0.000s
                                                          🟢getTime1.001s
                                                          🟢sleep1.001s
                                                          🟢step0.000s

                                                          🟢 love.video

                                                          • 🟢 1 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 0 Skipped
                                                          • 0.005s


                                                            • MethodTimeDetails
                                                              🟢newVideoStream0.005s

                                                              🔴 love.window

                                                              • 🟢 32 Tests
                                                              • 🔴 2 Failures
                                                              • 🟡 2 Skipped
                                                              • 5.419s


                                                                • MethodTimeDetails
                                                                  🟢close0.037s
                                                                  🟢fromPixels0.000s
                                                                  🟢getDPIScale0.000s
                                                                  🟢getDesktopDimensions0.000s
                                                                  🟢getDisplayCount0.000s
                                                                  🟢getDisplayName0.000s
                                                                  🟢getDisplayOrientation0.000s
                                                                  🟢getFullscreen1.347s
                                                                  🟢getFullscreenModes0.001s
                                                                  🟢getIcon0.004s
                                                                  🟢getMode0.000s
                                                                  🟢getPosition0.001s
                                                                  🟢getSafeArea0.000s
                                                                  🟢getTitle0.001s
                                                                  🟢getVSync0.000s
                                                                  🟢hasFocus0.000s
                                                                  🟢hasMouseFocus0.000s
                                                                  🟢isDisplaySleepEnabled0.000s
                                                                  🔴isMaximized0.640sassert #2 [check window not maximized] expected 'true' got 'false'
                                                                  🟢isMinimized0.645s
                                                                  🟢isOpen0.036s
                                                                  🟢isVisible0.031s
                                                                  🔴maximize0.000sassert #1 [check window maximized] expected 'true' got 'false'
                                                                  🟢minimize0.646s
                                                                  🟡requestAttention0.000scant test this worked
                                                                  🟢restore0.642s
                                                                  🟢setDisplaySleepEnabled0.000s
                                                                  🟢setFullscreen1.370s
                                                                  🟢setIcon0.002s
                                                                  🟢setMode0.008s
                                                                  🟢setPosition0.001s
                                                                  🟢setTitle0.000s
                                                                  🟢setVSync0.000s
                                                                  🟡showMessageBox0.000scant test this worked
                                                                  🟢toPixels0.000s
                                                                  🟢updateMode0.006s
\ No newline at end of file +

🔴 love.test

  • 🟢 254 Tests
  • 🔴 1 Failures
  • 🟡 50 Skipped
  • 12.195s


🟢 love.audio

  • 🟢 26 Tests
  • 🔴 0 Failures
  • 🟡 2 Skipped
  • 0.473s


    • MethodTimeDetails
      🟡RecordingDevice0.024stest class needs writing
      🟡Source0.017stest class needs writing
      🟢getActiveEffects0.016s
      🟢getActiveSourceCount0.016s
      🟢getDistanceModel0.017s
      🟢getDopplerScale0.016s
      🟢getEffect0.016s
      🟢getMaxSceneEffects0.017s
      🟢getMaxSourceEffects0.015s
      🟢getOrientation0.017s
      🟢getPosition0.017s
      🟢getRecordingDevices0.017s
      🟢getVelocity0.016s
      🟢getVolume0.017s
      🟢isEffectsSupported0.016s
      🟢newQueueableSource0.015s
      🟢newSource0.014s
      🟢pause0.016s
      🟢play0.017s
      🟢setDistanceModel0.019s
      🟢setDopplerScale0.017s
      🟢setEffect0.017s
      🟢setMixWithSystem0.017s
      🟢setOrientation0.017s
      🟢setPosition0.018s
      🟢setVelocity0.017s
      🟢setVolume0.016s
      🟢stop0.018s

      🟢 love.data

      • 🟢 7 Tests
      • 🔴 0 Failures
      • 🟡 5 Skipped
      • 0.212s


        • MethodTimeDetails
          🟡ByteData0.016stest class needs writing
          🟡CompressedData0.017stest class needs writing
          🟢compress0.017s
          🟢decode0.018s
          🟢decompress0.018s
          🟢encode0.019s
          🟡getPackedSize0.019stest class needs writing
          🟢hash0.017s
          🟢newByteData0.017s
          🟢newDataView0.017s
          🟡pack0.018stest class needs writing
          🟡unpack0.018stest class needs writing

          🟢 love.event

          • 🟢 4 Tests
          • 🔴 0 Failures
          • 🟡 2 Skipped
          • 0.108s


            • MethodTimeDetails
              🟢clear0.017s
              🟢poll0.017s
              🟡pump0.019snot sure can be tested as used internally
              🟢push0.018s
              🟢quit0.019s
              🟡wait0.018stest class needs writing

              🟢 love.filesystem

              • 🟢 28 Tests
              • 🔴 0 Failures
              • 🟡 3 Skipped
              • 0.556s


                • MethodTimeDetails
                  🟢File0.017s
                  🟡FileData0.019stest class needs writing
                  🟢append0.019s
                  🟢areSymlinksEnabled0.017s
                  🟢createDirectory0.017s
                  🟢getAppdataDirectory0.018s
                  🟢getCRequirePath0.017s
                  🟢getDirectoryItems0.018s
                  🟢getIdentity0.019s
                  🟢getInfo0.019s
                  🟢getRealDirectory0.018s
                  🟢getRequirePath0.018s
                  🟢getSaveDirectory0.018s
                  🟡getSource0.018snot sure can be tested as used internally
                  🟢getSourceBaseDirectory0.018s
                  🟢getUserDirectory0.019s
                  🟢getWorkingDirectory0.019s
                  🟢isFused0.017s
                  🟢lines0.018s
                  🟢load0.016s
                  🟢mount0.019s
                  🟢newFileData0.018s
                  🟢openFile0.019s
                  🟢read0.017s
                  🟢remove0.018s
                  🟢setCRequirePath0.018s
                  🟢setIdentity0.018s
                  🟢setRequirePath0.018s
                  🟡setSource0.018snot sure can be tested as used internally
                  🟢unmount0.018s
                  🟢write0.019s

                  🟢 love.font

                  • 🟢 4 Tests
                  • 🔴 0 Failures
                  • 🟡 3 Skipped
                  • 0.127s


                    • MethodTimeDetails
                      🟡GlyphData0.017stest class needs writing
                      🟡Rasterizer0.018stest class needs writing
                      🟡newBMFontRasterizer0.018swiki and source dont match, not sure expected usage
                      🟢newGlyphData0.020s
                      🟢newImageRasterizer0.020s
                      🟢newRasterizer0.018s
                      🟢newTrueTypeRasterizer0.017s

                      🔴 love.graphics

                      • 🟢 91 Tests
                      • 🔴 1 Failures
                      • 🟡 15 Skipped
                      • 2.091s


                        • MethodTimeDetails
                          🟡Canvas0.016stest class needs writing
                          🟡Font0.017stest class needs writing
                          🟡Image0.019stest class needs writing
                          🟡Mesh0.019stest class needs writing
                          🟡ParticleSystem0.017stest class needs writing
                          🟡Quad0.019stest class needs writing
                          🟡Shader0.018stest class needs writing
                          🟡SpriteBatch0.018stest class needs writing
                          🟡Text0.018stest class needs writing
                          🟡Texture0.018stest class needs writing
                          🟡Video0.019stest class needs writing
                          🟢applyTransform0.018s

                          Expected

                          Actual

                          🟢arc0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢captureScreenshot0.183s
                          🟢circle0.017s

                          Expected

                          Actual

                          🟢clear0.017s

                          Expected

                          Actual

                          🟡discard0.017scant test this worked
                          🟢draw0.018s

                          Expected

                          Actual

                          🟡drawInstanced0.020stest class needs writing
                          🟢drawLayer0.018s

                          Expected

                          Actual

                          🟢ellipse0.018s

                          Expected

                          Actual

                          🟡flushBatch0.018snot sure can be tested as used internally
                          🟢getBackgroundColor0.018s
                          🟢getBlendMode0.018s
                          🟢getCanvas0.018s
                          🟢getColor0.017s
                          🟢getColorMask0.018s
                          🟢getDPIScale0.019s
                          🟢getDefaultFilter0.018s
                          🟢getDepthMode0.018s
                          🟢getDimensions0.017s
                          🟢getFont0.018s
                          🟢getFrontFaceWinding0.019s
                          🟢getHeight0.017s
                          🟢getLineJoin0.018s
                          🟢getLineStyle0.017s
                          🟢getLineWidth0.019s
                          🟢getMeshCullMode0.018s
                          🟢getPixelDimensions0.018s
                          🟢getPixelHeight0.018s
                          🟢getPixelWidth0.018s
                          🟢getPointSize0.019s
                          🟢getRendererInfo0.018s
                          🟢getScissor0.018s
                          🟢getShader0.018s
                          🟢getStackDepth0.018s
                          🟢getStats0.017s
                          🟢getStencilMode0.018s
                          🟢getSupported0.018s
                          🟢getSystemLimits0.019s
                          🟢getTextureFormats0.020s
                          🟢getTextureTypes0.017s
                          🟢getWidth0.018s
                          🟢intersectScissor0.018s

                          Expected

                          Actual

                          🟢inverseTransformPoint0.018s
                          🟢isActive0.018s
                          🟢isGammaCorrect0.019s
                          🟢isWireframe0.017s
                          🟢line0.016s

                          Expected

                          Actual

                          🟢newArrayImage0.018s
                          🟢newCanvas0.019s
                          🟢newCubeImage0.019s
                          🟢newFont0.019s
                          🟢newImage0.018s
                          🟢newImageFont0.017s
                          🟢newMesh0.018s
                          🟢newParticleSystem0.019s
                          🟢newQuad0.018s
                          🟢newShader0.018s
                          🟢newSpriteBatch0.018s
                          🟢newTextBatch0.017s
                          🟢newVideo0.017s
                          🟢newVolumeImage0.018s
                          🟢origin0.018s

                          Expected

                          Actual

                          🟢points0.018s

                          Expected

                          Actual

                          🟢polygon0.018s

                          Expected

                          Actual

                          🟢pop0.019s

                          Expected

                          Actual

                          🟡present0.018stest class needs writing
                          🟢print0.017s

                          Expected

                          Actual

                          🟢printf0.018s

                          Expected

                          Actual

                          🟢push0.018s

                          Expected

                          Actual

                          🟢rectangle0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢replaceTransform0.018s

                          Expected

                          Actual

                          🟢reset0.019s
                          🟢rotate0.019s

                          Expected

                          Actual

                          🟢scale0.017s
                          🟢setBackgroundColor0.017s
                          🟢setBlendMode0.017s

                          Expected

                          Actual

                          🟢setCanvas0.018s

                          Expected

                          Actual

                          🟢setColor0.018s

                          Expected

                          Actual

                          🔴setColorMask0.018sassert #7 [check pixel b for yellow at 0,0(set color mask)] expected '0' got '1'

                          Expected

                          Actual

                          🟢setDefaultFilter0.018s
                          🟢setDepthMode0.018s
                          🟢setFont0.018s

                          Expected

                          Actual

                          🟢setFrontFaceWinding0.019s
                          🟢setLineJoin0.017s

                          Expected

                          Actual

                          🟢setLineStyle0.018s

                          Expected

                          Actual

                          🟢setLineWidth0.018s

                          Expected

                          Actual

                          🟢setMeshCullMode0.018s
                          🟢setScissor0.018s

                          Expected

                          Actual

                          🟢setShader0.018s

                          Expected

                          Actual

                          🟢setStencilTest0.018s

                          Expected

                          Actual

                          🟢setWireframe0.016s

                          Expected

                          Actual

                          🟢shear0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢transformPoint0.018s
                          🟢translate0.019s

                          Expected

                          Actual

                          🟢validateShader0.019s

                          🟢 love.image

                          • 🟢 3 Tests
                          • 🔴 0 Failures
                          • 🟡 2 Skipped
                          • 0.087s


                            • MethodTimeDetails
                              🟡CompressedImageData0.015stest class needs writing
                              🟡ImageData0.018stest class needs writing
                              🟢isCompressed0.019s
                              🟢newCompressedData0.017s
                              🟢newImageData0.018s

                              🟢 love.math

                              • 🟢 17 Tests
                              • 🔴 0 Failures
                              • 🟡 3 Skipped
                              • 0.358s


                                • MethodTimeDetails
                                  🟡BezierCurve0.016stest class needs writing
                                  🟡RandomGenerator0.018stest class needs writing
                                  🟡Transform0.019stest class needs writing
                                  🟢colorFromBytes0.017s
                                  🟢colorToBytes0.018s
                                  🟢gammaToLinear0.017s
                                  🟢getRandomSeed0.018s
                                  🟢getRandomState0.017s
                                  🟢isConvex0.018s
                                  🟢linearToGamma0.017s
                                  🟢newBezierCurve0.018s
                                  🟢newRandomGenerator0.018s
                                  🟢newTransform0.020s
                                  🟢perlinNoise0.018s
                                  🟢random0.019s
                                  🟢randomNormal0.017s
                                  🟢setRandomSeed0.018s
                                  🟢setRandomState0.018s
                                  🟢simplexNoise0.018s
                                  🟢triangulate0.018s

                                  🟢 love.physics

                                  • 🟢 22 Tests
                                  • 🔴 0 Failures
                                  • 🟡 6 Skipped
                                  • 0.492s


                                    • MethodTimeDetails
                                      🟡Body0.015stest class needs writing
                                      🟡Contact0.017stest class needs writing
                                      🟡Fixture0.017stest class needs writing
                                      🟡Joint0.018stest class needs writing
                                      🟡Shape0.018stest class needs writing
                                      🟡World0.018stest class needs writing
                                      🟢getDistance0.017s
                                      🟢getMeter0.016s
                                      🟢newBody0.017s
                                      🟢newChainShape0.018s
                                      🟢newCircleShape0.019s
                                      🟢newDistanceJoint0.018s
                                      🟢newEdgeShape0.017s
                                      🟢newFixture0.019s
                                      🟢newFrictionJoint0.019s
                                      🟢newGearJoint0.019s
                                      🟢newMotorJoint0.018s
                                      🟢newMouseJoint0.017s
                                      🟢newPolygonShape0.017s
                                      🟢newPrismaticJoint0.017s
                                      🟢newPulleyJoint0.017s
                                      🟢newRectangleShape0.018s
                                      🟢newRevoluteJoint0.017s
                                      🟢newRopeJoint0.018s
                                      🟢newWeldJoint0.019s
                                      🟢newWheelJoint0.016s
                                      🟢newWorld0.018s
                                      🟢setMeter0.018s

                                      🟢 love.sound

                                      • 🟢 2 Tests
                                      • 🔴 0 Failures
                                      • 🟡 2 Skipped
                                      • 0.072s


                                        • MethodTimeDetails
                                          🟡Decoder0.016stest class needs writing
                                          🟡SoundData0.019stest class needs writing
                                          🟢newDecoder0.020s
                                          🟢newSoundData0.017s

                                          🟢 love.system

                                          • 🟢 6 Tests
                                          • 🔴 0 Failures
                                          • 🟡 2 Skipped
                                          • 0.142s


                                            • MethodTimeDetails
                                              🟢getClipboardText0.016s
                                              🟢getOS0.017s
                                              🟢getPowerInfo0.018s
                                              🟢getProcessorCount0.018s
                                              🟢hasBackgroundMusic0.019s
                                              🟡openURL0.018scant test this worked
                                              🟢setClipboardText0.018s
                                              🟡vibrate0.018scant test this worked

                                              🟢 love.thread

                                              • 🟢 3 Tests
                                              • 🔴 0 Failures
                                              • 🟡 2 Skipped
                                              • 0.088s


                                                • MethodTimeDetails
                                                  🟡Channel0.015stest class needs writing
                                                  🟡Thread0.018stest class needs writing
                                                  🟢getChannel0.018s
                                                  🟢newChannel0.019s
                                                  🟢newThread0.018s

                                                  🟢 love.timer

                                                  • 🟢 6 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 0 Skipped
                                                  • 2.086s


                                                    • MethodTimeDetails
                                                      🟢getAverageDelta0.015s
                                                      🟢getDelta0.017s
                                                      🟢getFPS0.018s
                                                      🟢getTime1.008s
                                                      🟢sleep1.011s
                                                      🟢step0.018s

                                                      🟢 love.video

                                                      • 🟢 1 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 1 Skipped
                                                      • 0.031s


                                                        • MethodTimeDetails
                                                          🟡VideoStream0.014stest class needs writing
                                                          🟢newVideoStream0.017s

                                                          🟢 love.window

                                                          • 🟢 34 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 2 Skipped
                                                          • 5.273s


                                                            • MethodTimeDetails
                                                              🟢close0.035s
                                                              🟢fromPixels0.002s
                                                              🟢getDPIScale0.002s
                                                              🟢getDesktopDimensions0.016s
                                                              🟢getDisplayCount0.018s
                                                              🟢getDisplayName0.018s
                                                              🟢getDisplayOrientation0.019s
                                                              🟢getFullscreen1.346s
                                                              🟢getFullscreenModes0.017s
                                                              🟢getIcon0.016s
                                                              🟢getMode0.017s
                                                              🟢getPosition0.017s
                                                              🟢getSafeArea0.017s
                                                              🟢getTitle0.017s
                                                              🟢getVSync0.018s
                                                              🟢hasFocus0.018s
                                                              🟢hasMouseFocus0.018s
                                                              🟢isDisplaySleepEnabled0.018s
                                                              🟢isMaximized0.186s
                                                              🟢isMinimized0.655s
                                                              🟢isOpen0.045s
                                                              🟢isVisible0.032s
                                                              🟢maximize0.172s
                                                              🟢minimize0.637s
                                                              🟡requestAttention0.003scant test this worked
                                                              🟢restore0.650s
                                                              🟢setDisplaySleepEnabled0.012s
                                                              🟢setFullscreen1.122s
                                                              🟢setIcon0.006s
                                                              🟢setMode0.018s
                                                              🟢setPosition0.017s
                                                              🟢setTitle0.018s
                                                              🟢setVSync0.017s
                                                              🟡showMessageBox0.017scant test this worked
                                                              🟢toPixels0.018s
                                                              🟢updateMode0.019s
\ No newline at end of file diff --git a/testing/examples/lovetest_runAllTests.md b/testing/examples/lovetest_runAllTests.md index 4fabcde1d..cfe0105b0 100644 --- a/testing/examples/lovetest_runAllTests.md +++ b/testing/examples/lovetest_runAllTests.md @@ -1,26 +1,28 @@ - + -**305** tests were completed in **37.853s** with **244** passed, **0** failed, and **61** skipped +**305** tests were completed in **12.195s** with **254** passed, **1** failed, and **50** skipped ### Report | Module | Passed | Failed | Skipped | Time | | --------------------- | ------ | ------ | ------- | ------ | -| 🟢 love.audio | 26 | 0 | 0 | 2.605s | -| 🟢 love.data | 7 | 0 | 3 | 1.003s | -| 🟢 love.event | 4 | 0 | 2 | 0.600s | -| 🟢 love.filesystem | 27 | 0 | 2 | 3.030s | -| 🟢 love.font | 4 | 0 | 1 | 0.511s | -| 🟢 love.graphics | 81 | 0 | 15 | 10.599s | -| 🟢 love.image | 3 | 0 | 0 | 0.299s | -| 🟢 love.math | 17 | 0 | 0 | 1.821s | -| 🟢 love.objects | 1 | 0 | 34 | 3.603s | -| 🟢 love.physics | 22 | 0 | 0 | 2.222s | -| 🟢 love.sound | 2 | 0 | 0 | 0.199s | -| 🟢 love.system | 6 | 0 | 2 | 0.844s | -| 🟢 love.thread | 3 | 0 | 0 | 0.318s | -| 🟢 love.timer | 6 | 0 | 0 | 2.309s | -| 🟢 love.video | 1 | 0 | 0 | 0.114s | -| 🟢 love.window | 34 | 0 | 2 | 7.778s | +| 🟢 audio | 26 | 0 | 2 | 0.473s | +| 🟢 data | 7 | 0 | 5 | 0.212s | +| 🟢 event | 4 | 0 | 2 | 0.108s | +| 🟢 filesystem | 28 | 0 | 3 | 0.556s | +| 🟢 font | 4 | 0 | 3 | 0.127s | +| 🔴 graphics | 91 | 1 | 15 | 2.091s | +| 🟢 image | 3 | 0 | 2 | 0.087s | +| 🟢 math | 17 | 0 | 3 | 0.358s | +| 🟢 physics | 22 | 0 | 6 | 0.492s | +| 🟢 sound | 2 | 0 | 2 | 0.072s | +| 🟢 system | 6 | 0 | 2 | 0.142s | +| 🟢 thread | 3 | 0 | 2 | 0.088s | +| 🟢 timer | 6 | 0 | 0 | 2.086s | +| 🟢 video | 1 | 0 | 1 | 0.031s | +| 🟢 window | 34 | 0 | 2 | 5.273s | ### Failures +> 🔴 setColorMask +> assert #7 [check pixel b for yellow at 0,0(set color mask)] expected '0' got '1' + diff --git a/testing/examples/lovetest_runAllTests.xml b/testing/examples/lovetest_runAllTests.xml index 9c69661ed..73ada5cba 100644 --- a/testing/examples/lovetest_runAllTests.xml +++ b/testing/examples/lovetest_runAllTests.xml @@ -1,578 +1,693 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assert #7 [check pixel b for yellow at 0,0(set color mask)] expected '0' got '1' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/main.lua b/testing/main.lua index 523d536d6..0e6e74e93 100644 --- a/testing/main.lua +++ b/testing/main.lua @@ -1,5 +1,5 @@ -- & 'c:\Program Files\LOVE\love.exe' ./ --console --- /Applications/love.app/Contents/MacOS/love ./ +-- /Applications/love_12.app/Contents/MacOS/love ./testing -- load test objs require('classes.TestSuite') @@ -25,7 +25,6 @@ if love.thread ~= nil then require('tests.thread') end if love.timer ~= nil then require('tests.timer') end if love.video ~= nil then require('tests.video') end if love.window ~= nil then require('tests.window') end -require('tests.objects') -- love.load -- load given arguments and run the test suite @@ -72,21 +71,21 @@ love.load = function(args) local cmderr = 'Invalid flag used' local modules = { 'audio', 'data', 'event', 'filesystem', 'font', 'graphics', - 'image', 'math', 'objects', 'physics', 'sound', 'system', + 'image', 'math', 'physics', 'sound', 'system', 'thread', 'timer', 'video', 'window' } + GITHUB_RUNNER = false for a=1,#arglist do if testcmd == '--runSpecificMethod' then if module == '' and love[ arglist[a] ] ~= nil then module = arglist[a] table.insert(modules, module) - end - if module ~= '' and love[module][ arglist[a] ] ~= nil and method == '' then - method = arglist[a] + elseif module ~= '' and love[module] ~= nil and method == '' then + if love.test[module][arglist[a]] ~= nil then method = arglist[a] end end end if testcmd == '--runSpecificModules' then - if love[ arglist[a] ] ~= nil or arglist[a] == 'objects' then + if love[ arglist[a] ] ~= nil and arglist[a] ~= '--isRunner' then table.insert(modules, arglist[a]) end end @@ -98,6 +97,9 @@ love.load = function(args) testcmd = arglist[a] modules = {} end + if arglist[a] == '--isRunner' then + GITHUB_RUNNER = true + end end -- runSpecificMethod uses the module + method given @@ -142,6 +144,10 @@ love.load = function(args) love.test.output = 'lovetest_runAllTests' end + if GITHUB_RUNNER then + love.test.module:log('grey', '--isRunner') + end + -- invalid command if love.test.module == nil then print(cmderr) @@ -183,6 +189,10 @@ love.quit = function() end +-- added so bad threads dont fail +function love.threaderror(thread, errorstr) end + + -- string split helper function UtilStringSplit(str, splitter) local splits = {} @@ -197,3 +207,7 @@ end function UtilTimeFormat(seconds) return string.format("%.3f", tostring(seconds)) end + +function UtilDebugLog(a, b, c) + if GITHUB_RUNNER == true then print("DEBUG ==> ", a, b, c) end +end diff --git a/testing/readme.md b/testing/readme.md index f322f7dd5..f9fdfd2cc 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -1,60 +1,87 @@ -# löve.test -Basic testing suite for the löve APIs, based off of [this issue](https://github.com/love2d/love/issues/1745) +# Lövetest +Basic testing suite for the [Löve](https://github.com/love2d/love) APIs, based off of [this issue](https://github.com/love2d/love/issues/1745). -Currently written for löve 12 +Currently written for [Löve 12](https://github.com/love2d/love/tree/12.0-development), which is still in development. --- -## Primary Goals +## Features - [x] Simple pass/fail tests in Lua with minimal setup -- [x] Ability to run all tests with a simple command. +- [x] Ability to run all tests with a simple command - [x] Ability to see how many tests are passing/failing -- [x] No platform-specific dependencies / scripts - [x] Ability to run a subset of tests -- [x] Ability to easily run an individual test. +- [x] Ability to easily run an individual test +- [x] Ability to see all visual results at a glance - [x] Automatic testing that happens after every commit +- [x] No platform-specific dependencies / scripts + +--- + +## Coverage +This is the status of all module tests currently. +| Module | Done | Todo | Skip | +| ----------------- | ---- | ---- | ---- | +| 🟢 audio | 28 | 0 | 0 | +| 🟢 data | 12 | 0 | 0 | +| 🟡 event | 4 | 1 | 1 | +| 🟢 filesystem | 28 | 0 | 2 | +| 🟢 font | 7 | 0 | 0 | +| 🟡 graphics | 93 | 14 | 1 | +| 🟢 image | 5 | 0 | 0 | +| 🟢 math | 20 | 0 | 0 | +| 🟡 physics | 22 | 6 | 0 | +| 🟢 sound | 4 | 0 | 0 | +| 🟢 system | 6 | 0 | 2 | +| 🟢 thread | 5 | 0 | 0 | +| 🟢 timer | 6 | 0 | 0 | +| 🟢 video | 2 | 0 | 0 | +| 🟢 window | 34 | 0 | 2 | + +> The following modules are not covered as we can't really emulate input nicely: +> `joystick`, `keyboard`, `mouse`, and `touch` --- ## Running Tests -The initial pass is to keep things as simple as possible, and just run all the tests inside Löve to match how they'd be used by developers in-engine. -To run the tests, download the repo and then run the main.lua as you would a löve game, i.e: +The testsuite aims to keep things as simple as possible, and just runs all the tests inside Löve to match how they'd be used by developers in-engine. +To run the tests, download the repo and then run the main.lua as you would a Löve game, i.e: WINDOWS: `& 'c:\Program Files\LOVE\love.exe' PATH_TO_TESTING_FOLDER --console` -MACOS: `/Applications/love.app/Contents/MacOS/love PATH_TO_TESTING_FOLDER` +MACOS: `/Applications/love.app/Contents/MacOS/love PATH_TO_TESTING_FOLDER` +LINUX: `./love.AppImage PATH_TO_TESTING_FOLDER` By default all tests will be run for all modules. - -If you want to specify a module you can add: -`--runSpecificModules filesystem` -For multiple modules, provide a comma seperate list: -`--runSpecificModules filesystem,audio,data"` - +If you want to specify a module/s you can use: +`--runSpecificModules filesystem,audio` If you want to specify only 1 specific method only you can use: `--runSpecificMethod filesystem write` All results will be printed in the console per method as PASS, FAIL, or SKIP with total assertions met on a module level and overall level. -An `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) will be generated in the `/output` directory, along with a `HTML` and a `Markdown` file with a summary of all tests (including visuals for love.graphics tests). -> An example of both types of output can be found in the `/examples` folder - -The Markdown file can be used with [this github action](https://github.com/ellraiser/love-test-report) if you want to output the report results to your CI. +When finished, the following files will be generated in the `/output` directory with a summary of the test results: +- an `XML` file in the style of [JUnit XML](https://www.ibm.com/docs/en/developer-for-zos/14.1?topic=formats-junit-xml-format) +- a `HTML` file that shows any visual test results +- a `Markdown` file for use with [this github action](https://github.com/ellraiser/love-test-report) +> An example of all types of output can be found in the `/examples` +> The visual results of any graphic tests can be found in `/output/actual` --- ## Architecture -Each method has it's own test method written in `/tests` under the matching module name. +Each method and object has it's own test method written in `/tests` under the matching module name. When you run the tests, a single TestSuite object is created which handles the progress + totals for all the tests. Each module has a TestModule object created, and each test method has a TestMethod object created which keeps track of assertions for that method. You can currently do the following assertions: - **assertNotNil**(value) -- **assertEquals**(expected, actual) -- **assertNotEquals**(expected, actual) -- **assertRange**(actual, min, max) -- **assertMatch**({option1, option2, option3 ...}, actual) -- **assertGreaterEqual**(expected, actual) -- **assertLessEqual**(expected, actual) +- **assertEquals**(expected, actual, label) +- **assertNotEquals**(expected, actual, label) +- **assertRange**(actual, min, max, label) +- **assertMatch**({option1, option2, option3 ...}, actual, label) +- **assertGreaterEqual**(expected, actual, label) +- **assertLessEqual**(expected, actual, label) - **assertObject**(table) +- **assertPixels**(imgdata, pixeltable, label) +- **assertCoords**(expected, actual, label) Example test method: ```lua @@ -76,52 +103,22 @@ end After each test method is ran, the assertions are totalled up, printed, and we move onto the next method! Once all methods in the suite are run a total pass/fail/skip is given for that module and we move onto the next module (if any) -For sanity-checking, if it's currently not covered or we're not sure how to test yet we can set the test to be skipped with `test:skipTest(reason)` - this way we still see the method listed in the tests without it affected the pass/fail totals - ---- - -## Coverage -This is the status of all module tests currently. -| Module | Passed | Failed | Skipped | Time | -| --------------------- | ------ | ------ | ------- | ------ | -| 🟢 love.audio | 26 | 0 | 0 | 2.602s | -| 🟢 love.data | 7 | 0 | 3 | 1.003s | -| 🟢 love.event | 4 | 0 | 2 | 0.599s | -| 🟢 love.filesystem | 27 | 0 | 2 | 2.900s | -| 🟢 love.font | 4 | 0 | 1 | 0.500s | -| 🟢 love.graphics | 81 | 0 | 15 | 10.678s | -| 🟢 love.image | 3 | 0 | 0 | 0.300s | -| 🟢 love.math | 17 | 0 | 0 | 1.678s | -| 🟢 love.physics | 22 | 0 | 0 | 2.197s | -| 🟢 love.sound | 2 | 0 | 0 | 0.200s | -| 🟢 love.system | 6 | 0 | 2 | 0.802s | -| 🟢 love.thread | 3 | 0 | 0 | 0.300s | -| 🟢 love.timer | 6 | 0 | 0 | 2.358s | -| 🟢 love.video | 1 | 0 | 0 | 0.100s | -| 🟢 love.window | 34 | 0 | 2 | 8.050s | - -The following modules are not covered as we can't really emulate input nicely: -`joystick`, `keyboard`, `mouse`, and `touch` +For sanity-checking, if it's currently not covered or it's not possible to test the method we can set the test to be skipped with `test:skipTest(reason)` - this way we still see the method listed in the test output without it affected the pass/fail totals --- ## Todo Modules with some small bits needed or needing sense checking: -- **love.data** - packing methods need writing cos i dont really get what they are - **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check - **love.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected - **love.graphics** - still need to do tests for the main drawing methods - **love.image** - ideally isCompressed should have an example of all compressed files love can take -- **love.math** - linearToGamma + gammaToLinear using direct formulas don't get same value back - **love.*.objects** - all objects tests still to be done - **love.graphics.setStencilTest** - deprecated, replaced by setStencilMode() --- -## Stretch Goals -- [ ] Tests can compare visual results to a reference image -- [ ] Ability to see all visual results at a glance +## Future Goals +- [ ] Tests can compare visual results to a reference image (partially done) - [ ] Ability to test loading different combinations of modules - [ ] Performance tests - -There is some unused code in the Test.lua class to add preview vs actual images to the HTML output diff --git a/testing/resources/alsoft.conf b/testing/resources/alsoft.conf new file mode 100644 index 000000000..3e28208eb --- /dev/null +++ b/testing/resources/alsoft.conf @@ -0,0 +1,4 @@ +[general] +drivers = wave +[wave] +file = output.wav \ No newline at end of file diff --git a/testing/resources/clickmono.ogg b/testing/resources/clickmono.ogg new file mode 100644 index 0000000000000000000000000000000000000000..d1b567e7d261ca5baa6c81fba0d7891ce6b14c2d GIT binary patch literal 3883 zcmai1eOyvm`aftY8M@?JQe!PNmf%}rYU0?Wr1`GJONuUQifEvi3205(IEk*AnHf@& zIcbV{Qz}v`nw+w|TB)0;?U@KdEcK~_33Br8{t zvpq}1&yrA3(8cg#ZcmfsCFk(hMJ4B^`S^Kw`*=`2Juwy^(Emc;umx&j0D;G%Y^-K{ z7qNedSWewool+UGzfrcB9(F=(&upgYYBE|bw-aUfrOZtfi)uzWL$HKbfl~O$@Rbrf zf9DfCd}8?Z;bR#Gf;t>!HcCbm<))lbO2;l?mQlLpj0n2bN{Ow%-jP`zK@Pf9BR}H!joNuF5WiGo z4K@LQFRde#n#qb=%zzgF^G=e>pOMQyrB(967n@XIcJKgP%eD_cY=7sxQ{;DUk%PgT z+4)1hZ1#+lt3xNzJ9QC?8W`48-MEz4g-a!1Z8#Qy2m`l~+=Vy)Ej%EFOe7&H1>v$InnBF3m}!Zi9L?V!OgL$_J|UramYGL1jI( zrotT?2~bbjrVkSO4nx`EHWf|i(G95;&-LLVk0D46(4dOxhB!2dvtv-?`Wbyf7Tp0- zpD$_JEvBQgKlDC?2l^XC@GaiaL=5}-)K`R%62a{TtFcozoVMX|teZnmojS~TL6oz4 z!YL;{c#Z{tB(rCPk%~UvN=U_ol-rc1ntj$T%?4^^8*g zj8^|?L_I&DUL{nMk86xt_5Ye4rUI`3;QnF9JBJ-%frmo^V~Q@^3uYi2cdG&xJ*@bT zKF0nG1Im41@t+9*z|-jl!!1l{t9#}1Aj_`7mLG$N< z%>c-#VUz~@lrmaV&4x0H;h4CXs&^EZ(+npi3>QOCAMI$UWM-gz( zd)*+5eb1Xc1X$79d2a&P zzeEj6*9}VeLsC(ql*^rsVk)9_Rs2DzXtavY&Et>E`V30AgKYkYggcVUkGsg_%;XPB zi=I~Tlj8UsLN0fLOLda%6!hh*l{ybj;?BaSTw$ttD9wWW{Th{ zihNnhC4A2QC7+pFG%n#k)fGMEWO4lz52X3YRig2DK8Ln77PT_7%HO%!64vBcx`D2{4q`dNRg8#R#Cz_G7$JMU5CbtFO zzB2Y)nCsM(sf}|8WL-wP&KonJ$wa8%-d>nm44T?M_XgIHT+IsnFyN5W{`yo-J(;5*m#QYU z_1m=S27#(sP%B7KrYltfL_<-k-2_TOLT#E-*;K9Crc`GrRV}3|N}o#Ds}U$QFSQ!c z6?Nuly}-m~DphV*G-pQDFJEXIII8AdwE|%+gfc0s&+Mudeo?y(sU;(b5J6fI#4Qo7 zDkqy&&ZSVIYE>dGeJbR!Mu2o=B8cb;^75@lWYj`SM2O1$I3h%mHEyHY)zB&wS!t+N zK{GOyh-+ePlM+SN?^i)^x8o|LS7E3|Ao7d-wHYR4;bTOgM3LQ(t6cijqPb3EuOgBP42}D!W~xuqGG}rSH3RYJ(}+H~kU6K_ru=A?%c#bEP7AG? z>Q!$)gR~e?_NTY%Y@^om8%^dM((+d8I;!1n^ctPX4~8Yk^bw81eF95xh7Uy#yhVv@ zcA{_ePzN8DAZ)40-q9m)7Y#=bwTUAM9I?PEyYMq1A#ZU;$7#5f9^8FMO=wh1bHU zHX|Lc!W4%6^#YiwL?}@;BWj~j`9WfQ0pnwmXtf^7`ep<%YBg$@6h!TMMf1`K3B=f| zcAM)$v}#uvQe)RS_&Q9%Xvg;NVR!GGn(I2;YSenX>!RX9G2n;!wjj{Lx1~Ir;k`J1 z+wBNIGzSHqmZU;F-I64$U__7_<#w=L{{Vkhx6+r8(cX(UhYSW)!IIz^>5tp*=Ysj* z(V=Wm@r5UqT2xfrG7m6d_vOJe8Pz}xE~E7jBz6&{uuW2}8XH(NE0TvSL_x*T?Wzu}5pSGGoBU@O@6d zkLk-jACDy%;AdkCPFnq!TZ=$J;6@5mvGteP^I+acvM>_L(y@zBc9{(C(&LD-q*T)? zo_@Qg(AFP%cRvU!E+{F{ySRCHdU^Z$`3In(Jk!X6tBOV|UP5&Y0ZC_v#0rWovicz8{Sb+O<#j?Mwa$4oQ z>g&^(vfhiq4%HsZ?VF~*eDT?5>e!mLf4^CE=*O9(E$XGaOQ+-Jmdkqgb#2d&f73e@ z{5pf0zMC^LHI{kc8SCcq*}Kj?dv5Qv+0(;$%J6)ce)O0+KQT6W-(=4M%c97iS$U34 z`R1~lmo1MuQ+iy_b|0NsXN;J1Z%1%z4Pzny$Xou(8Z_K|Ov+1Yw~e=T5Y~T5TQ;#i zFTKds=hivT+5WH79Uk{jH^KkWhhdu9hY@OcmFt=x!Sfi!o1J|Fs3s=8gSOxYzg9uU(<9&;Q?bnm}m(!&k*RY0TG8hUYtN zsfueoLdS;91CoR8S)!}%>YV|N$Mr+}^(ifnm_G?pOEK}5m=)Fw-wR_e@uWw75i?o4 zYeF0@h{OK8?#H{v{LWpkvvk^;|;oR!}(Ci-DU?Zdv2e$sz_7p~9q zb%ZTOVcGTcSNCPzC(R42lGcB|Vda*q|1jU{Y!UnK;rECB>H6sE)#)eLx)sFbzYush ztF8P54%@?w0x-O;leY5cW^27}HxJ;!f(dV=OP<7>QhFzepJj_X}% v%Wl{_|7=|JyvtQFwbfUOTVQ;2DTRFGK-Dtv*K344vulJb=CJL(9ANwZTBe{N literal 0 HcmV?d00001 diff --git a/testing/tests/audio.lua b/testing/tests/audio.lua index a174b48c8..86912966e 100644 --- a/testing/tests/audio.lua +++ b/testing/tests/audio.lua @@ -1,6 +1,172 @@ -- love.audio +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- RecordingDevice (love.audio.getRecordingDevices) +love.test.audio.RecordingDevice = function(test) + -- check devices first + local devices = love.audio.getRecordingDevices() + if #devices == 0 then + return test:skipTest('cant test this works: no recording devices found') + end + -- test device + if test:isDelayed() == false then + -- check object created and basics + local device = devices[1] + test.store.device = device + test:assertObject(device) + test:assertMatch({1, 2}, device:getChannelCount(), 'check channel count is 1 or 2') + test:assertNotEquals(nil, device:getName(), 'check has name') + -- check initial data is empty as we haven't recorded anything yet + test:assertNotNil(device:getBitDepth()) + test:assertEquals(nil, device:getData(), 'check initial data empty') + test:assertEquals(0, device:getSampleCount(), 'check initial sample empty') + test:assertNotNil(device:getSampleRate()) + test:assertEquals(false, device:isRecording(), 'check not recording') + -- start recording for a short time + local startrecording = device:start(32000, 4000, 16, 1) + test:assertEquals(true, startrecording, 'check recording started') + test:assertEquals(true, device:isRecording(), 'check now recording') + test:assertEquals(4000, device:getSampleRate(), 'check sample rate set') + test:assertEquals(16, device:getBitDepth(), 'check bit depth set') + test:assertEquals(1, device:getChannelCount(), 'check channel count set') + test:setDelay(20) + -- after recording + else + local device = test.store.device + local recording = device:stop() + test:assertEquals(false, device:isRecording(), 'check not recording') + test:assertEquals(nil, device:getData(), 'using stop should clear buffer') + test:assertObject(recording) + end +end + + +-- Source (love.audio.newSource) +love.test.audio.Source = function(test) + -- create stereo source + local stereo = love.audio.newSource('resources/click.ogg', 'static') + test:assertObject(stereo) + -- check stereo props + test:assertEquals(2, stereo:getChannelCount(), 'check stereo src') + test:assertEquals(66, math.floor(stereo:getDuration("seconds")*1000), 'check stereo seconds') + test:assertNotNil(stereo:getFreeBufferCount()) + test:assertEquals('static', stereo:getType(), 'check stereo type') + -- check cloning a stereo + local clone = stereo:clone() + test:assertEquals(2, clone:getChannelCount(), 'check clone stereo src') + test:assertEquals(66, math.floor(clone:getDuration("seconds")*1000), 'check clone stereo seconds') + test:assertNotNil(clone:getFreeBufferCount()) + test:assertEquals('static', clone:getType(), 'check cloned stereo type') + -- mess with stereo playing + test:assertEquals(false, stereo:isPlaying(), 'check not playing') + stereo:setLooping(true) + stereo:play() + test:assertEquals(true, stereo:isPlaying(), 'check now playing') + test:assertEquals(true, stereo:isLooping(), 'check now playing') + stereo:pause() + stereo:seek(0.01, 'seconds') + test:assertEquals(0.01, stereo:tell('seconds'), 'check seek/tell') + stereo:stop() + test:assertEquals(false, stereo:isPlaying(), 'check stopped playing') + -- check volume limits + stereo:setVolumeLimits(0.1, 0.5) + local min, max = stereo:getVolumeLimits() + test:assertEquals(1, math.floor(min*10), 'check min limit') + test:assertEquals(5, math.floor(max*10), 'check max limit') + -- @NOTE the following works as setVolumeLimits is used with set volume + -- as the BASE and then applying directional, rather than being a clamp + stereo:setVolume(1) + test:assertEquals(1, stereo:getVolume(), 'check set volume') + stereo:setVolume(0) + test:assertEquals(0, stereo:getVolume(), 'check set volume') + -- change some get/set props that can apply to stereo + stereo:setPitch(2) + test:assertEquals(2, stereo:getPitch(), 'check pitch change') + -- create mono source + local mono = love.audio.newSource('resources/clickmono.ogg', 'stream') + test:assertObject(mono) + test:assertEquals(1, mono:getChannelCount(), 'check mono src') + test:assertEquals(2927, mono:getDuration("samples"), 'check mono seconds') + test:assertEquals('stream', mono:getType(), 'check mono type') + -- check the basic get/set properties + test:assertEquals(0, mono:getAirAbsorption(), 'get air absorption') + mono:setAirAbsorption(1) + test:assertEquals(1, mono:getAirAbsorption(), 'set air absorption') + mono:setCone(0, 90*(math.pi/180), 1) + local ia, oa, ov = mono:getCone() + test:assertEquals(0, ia, 'check cone ia') + test:assertEquals(math.floor(9000*(math.pi/180)), math.floor(oa*100), 'check cone oa') + test:assertEquals(1, ov, 'check cone ov') + mono:setDirection(3, 1, -1) + local x, y, z = mono:getDirection() + test:assertEquals(3, x, 'check direction x') + test:assertEquals(1, y, 'check direction y') + test:assertEquals(-1, z, 'check direction z') + mono:setRelative(true) + test:assertEquals(true, mono:isRelative(), 'check set relative') + mono:setPosition(1, 2, 3) + x, y, z = mono:getPosition() + test:assertEquals(x, 1, 'check pos x') + test:assertEquals(y, 2, 'check pos y') + test:assertEquals(z, 3, 'check pos z') + mono:setVelocity(1, 3, 4) + x, y, z = mono:getVelocity() + test:assertEquals(x, 1, 'check velocity x') + test:assertEquals(y, 3, 'check velocity x') + test:assertEquals(z, 4, 'check velocity x') + mono:setRolloff(1) + test:assertEquals(1, mono:getRolloff(), 'check rolloff set') + -- create queue source + local queue = love.audio.newQueueableSource(44100, 16, 1, 3) + local sdata = love.sound.newSoundData(1024, 44100, 16, 1) + test:assertObject(queue) + local run = queue:queue(sdata) + test:assertEquals(true, run, 'check queued sound') + queue:stop() + -- check making a filer + local setfilter = stereo:setFilter({ + type = 'lowpass', + volume = 0.5, + highgain = 0.3 + }) + test:assertEquals(true, setfilter, 'check filter applied') + local filter = stereo:getFilter() + test:assertEquals('lowpass', filter.type, 'check filter type') + test:assertEquals(0.5, filter.volume, 'check filter volume') + test:assertEquals(3, math.floor(filter.highgain*10), 'check filter highgain') + test:assertEquals(nil, filter.lowgain, 'check filter lowgain') + -- add an effect + local effsource = love.audio.newSource('resources/click.ogg', 'static') + love.audio.setEffect('testeffect', { + type = 'flanger', + volume = 10 + }) + local seteffect, err = effsource:setEffect('flanger', { + type = 'highpass', + volume = 0.3, + lowgain = 0.1 + }) + -- both these fail on 12 using stereo or mono, no err + test:assertEquals(true, seteffect, 'check effect was applied') + local filtersettings = effsource:getEffect('chorus', {}) + test:assertNotNil(filtersettings) +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.audio.getActiveEffects love.test.audio.getActiveEffects = function(test) -- check we get a value @@ -142,14 +308,14 @@ end -- love.audio.newQueueableSource --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.audio.newQueueableSource = function(test) test:assertObject(love.audio.newQueueableSource(32, 8, 1, 8)) end -- love.audio.newSource --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.audio.newSource = function(test) test:assertObject(love.audio.newSource('resources/click.ogg', 'static')) test:assertObject(love.audio.newSource('resources/click.ogg', 'stream')) diff --git a/testing/tests/data.lua b/testing/tests/data.lua index dac5f3c06..bfd5413d0 100644 --- a/testing/tests/data.lua +++ b/testing/tests/data.lua @@ -1,6 +1,61 @@ -- love.data +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- ByteData (love.data.newByteData) +love.test.data.ByteData = function(test) + -- create new obj + local data = love.data.newByteData('helloworld') + test:assertObject(data) + -- check properties match expected + test:assertEquals('helloworld', data:getString(), 'check data string') + test:assertEquals(10, data:getSize(), 'check data size') + -- check cloning the bytedata + local cloneddata = data:clone() + test:assertObject(cloneddata) + test:assertEquals('helloworld', cloneddata:getString(), 'check cloned data') + test:assertEquals(10, cloneddata:getSize(), 'check cloned size') + -- check pointer access if allowed + if data:getFFIPointer() ~= nil and ffi ~= nil then + local pointer = data:getFFIPointer() + local ptr = ffi.cast('uint8_t*', pointer) + local byte5 = ptr[4] + test:assertEquals('o', byte5) + end +end + + +-- CompressedData (love.data.compress) +love.test.data.CompressedData = function(test) + -- create new compressed data + local cdata = love.data.compress('data', 'zlib', 'helloworld', -1) + test:assertObject(cdata) + test:assertEquals('zlib', cdata:getFormat(), 'check format used') + -- check properties match expected + test:assertEquals(18, cdata:getSize()) + test:assertEquals('helloworld', love.data.decompress('data', cdata):getString()) + -- check cloning the data + local clonedcdata = cdata:clone() + test:assertObject(clonedcdata) + test:assertEquals('zlib', clonedcdata:getFormat()) + test:assertEquals(18, clonedcdata:getSize()) + test:assertEquals('helloworld', love.data.decompress('data', clonedcdata):getString()) +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.data.compress love.test.data.compress = function(test) -- here just testing each combo 'works' - in decompress's test method @@ -119,9 +174,13 @@ end -- love.data.getPackedSize --- @NOTE I don't really get what lua packing types are so skipping for now - ell love.test.data.getPackedSize = function(test) - test:skipTest('test class needs writing') + local pack1 = love.data.getPackedSize('>xI3b') + local pack2 = love.data.getPackedSize('>I2B') + local pack3 = love.data.getPackedSize('>I4I4I4I4x') + test:assertEquals(5, pack1, 'check pack size 1') + test:assertEquals(3, pack2, 'check pack size 2') + test:assertEquals(17, pack3, 'check pack size 3') end @@ -145,28 +204,39 @@ end -- love.data.newByteData --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.data.newByteData = function(test) test:assertObject(love.data.newByteData('helloworld')) end -- love.data.newDataView --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.data.newDataView = function(test) test:assertObject(love.data.newDataView(love.data.newByteData('helloworld'), 0, 10)) end -- love.data.pack --- @NOTE I don't really get what lua packing types are so skipping for now - ell love.test.data.pack = function(test) - test:skipTest('test class needs writing') + local packed1 = love.data.pack('string', '>I4I4I4I4', 9999, 1000, 1010, 2030) + local packed2 = love.data.pack('data', '>I4I4I4I4', 9999, 1000, 1010, 2030) + local a, b, c, d = love.data.unpack('>I4I4I4I4', packed1) + local e, f, g, h = love.data.unpack('>I4I4I4I4', packed2) + test:assertEquals(9999+9999, a+e, 'check packed 1') + test:assertEquals(1000+1000, b+f, 'check packed 2') + test:assertEquals(1010+1010, c+g, 'check packed 3') + test:assertEquals(2030+2030, d+h, 'check packed 4') end -- love.data.unpack --- @NOTE I don't really get what lua packing types are so skipping for now - ell love.test.data.unpack = function(test) - test:skipTest('test class needs writing') + local packed1 = love.data.pack('string', '>s5s4I3', 'hello', 'love', 100) + local packed2 = love.data.pack('data', '>s5I2', 'world', 20) + local a, b, c = love.data.unpack('>s5s4I3', packed1) + local d, e = love.data.unpack('>s5I2', packed2) + test:assertEquals(a .. ' ' .. d, 'hello world', 'check unpack 1') + test:assertEquals(b, 'love', 'check unpack 2') + test:assertEquals(c - e, 80, 'check unpack 3') end diff --git a/testing/tests/event.lua b/testing/tests/event.lua index ff667c394..9e43f8b82 100644 --- a/testing/tests/event.lua +++ b/testing/tests/event.lua @@ -1,6 +1,13 @@ -- love.event +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.event.clear love.test.event.clear = function(test) -- push some events first @@ -35,7 +42,7 @@ end -- love.event.pump -- @NOTE dont think can really test as internally used love.test.event.pump = function(test) - test:skipTest('not sure can be tested as used internally') + test:skipTest('used internally') end diff --git a/testing/tests/filesystem.lua b/testing/tests/filesystem.lua index 248aa39c4..224a7e916 100644 --- a/testing/tests/filesystem.lua +++ b/testing/tests/filesystem.lua @@ -1,6 +1,101 @@ -- love.filesystem +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- File (love.filesystem.newFile) +love.test.filesystem.File = function(test) + -- setup a file to play with + local file1 = love.filesystem.openFile('data.txt', 'w') + file1:write('helloworld') + test:assertObject(file1) + file1:close() + -- test read mode + file1:open('r') + test:assertEquals('r', file1:getMode(), 'check read mode') + local contents, size = file1:read() + test:assertEquals('helloworld', contents) + test:assertEquals(10, size, 'check file read') + test:assertEquals(10, file1:getSize()) + local ok, err = file1:write('hello') + test:assertNotEquals(nil, err, 'check cant write in read mode') + local iterator = file1:lines() + test:assertNotEquals(nil, iterator, 'check can read lines') + test:assertEquals('data.txt', file1:getFilename(), 'check filename matches') + file1:close() + -- test write mode + file1:open('w') + test:assertEquals('w', file1:getMode(), 'check write mode') + contents, size = file1:read() + test:assertEquals(nil, contents, 'check cant read file in write mode') + test:assertEquals('string', type(size), 'check err message shown') + ok, err = file1:write('helloworld') + test:assertEquals(true, ok, 'check file write') + test:assertEquals(nil, err, 'check no err writing') + -- test open/closing + file1:open('r') + test:assertEquals(true, file1:isOpen(), 'check file is open') + file1:close() + test:assertEquals(false, file1:isOpen(), 'check file gets closed') + file1:close() + -- test buffering and flushing + file1:open('w') + ok, err = file1:setBuffer('full', 10000) + test:assertEquals(true, ok) + test:assertEquals('full', file1:getBuffer()) + file1:write('replacedcontent') + file1:flush() + file1:close() + file1:open('r') + contents, size = file1:read() + test:assertEquals('replacedcontent', contents, 'check buffered content was written') + file1:close() + -- loop through file data with seek/tell until EOF + file1:open('r') + local counter = 0 + for i=1,100 do + file1:seek(i) + test:assertEquals(i, file1:tell()) + if file1:isEOF() == true then + counter = i + break + end + end + test:assertEquals(counter, 15) + file1:close() +end + + +-- FileData (love.filesystem.newFileData) +love.test.filesystem.FileData = function(test) + -- create new obj + local fdata = love.filesystem.newFileData('helloworld', 'test.txt') + test:assertObject(fdata) + test:assertEquals('test.txt', fdata:getFilename()) + test:assertEquals('txt', fdata:getExtension()) + -- check properties match expected + test:assertEquals('helloworld', fdata:getString(), 'check data string') + test:assertEquals(10, fdata:getSize(), 'check data size') + -- check cloning the bytedata + local clonedfdata = fdata:clone() + test:assertObject(clonedfdata) + test:assertEquals('helloworld', clonedfdata:getString(), 'check cloned data') + test:assertEquals(10, clonedfdata:getSize(), 'check cloned size') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.filesystem.append love.test.filesystem.append = function(test) -- create a new file to test with @@ -116,7 +211,7 @@ end -- love.filesystem.getSource -- @NOTE i dont think we can test this cos love calls it first love.test.filesystem.getSource = function(test) - test:skipTest('not sure can be tested as used internally') + test:skipTest('used internally') end @@ -229,7 +324,7 @@ end -- love.filesystem.openFile --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.filesystem.openFile = function(test) test:assertNotNil(love.filesystem.openFile('file2.txt', 'w')) test:assertNotNil(love.filesystem.openFile('file2.txt', 'r')) @@ -240,7 +335,7 @@ end -- love.filesystem.newFileData --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.filesystem.newFileData = function(test) test:assertNotNil(love.filesystem.newFileData('helloworld', 'file1')) end @@ -307,9 +402,8 @@ end -- love.filesystem.setSource --- @NOTE dont think can test this cos used internally? love.test.filesystem.setSource = function(test) - test:skipTest('not sure can be tested as used internally') + test:skipTest('used internally') end diff --git a/testing/tests/font.lua b/testing/tests/font.lua index 84c3f4568..695da4120 100644 --- a/testing/tests/font.lua +++ b/testing/tests/font.lua @@ -1,16 +1,76 @@ -- love.font +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- GlyphData (love.font.newGlyphData) +love.test.font.GlyphData = function(test) + -- create obj + local rasterizer = love.font.newRasterizer('resources/font.ttf') + local gdata = love.font.newGlyphData(rasterizer, 97) -- 'a' + test:assertObject(gdata) + -- check properties match expected + test:assertNotNil(gdata:getString()) + test:assertEquals(128, gdata:getSize(), 'check data size') + test:assertEquals(9, gdata:getAdvance(), 'check advance') + test:assertEquals('la8', gdata:getFormat(), 'check format') + test:assertEquals(97, gdata:getGlyph(), 'check glyph number') + test:assertEquals('a', gdata:getGlyphString(), 'check glyph string') + test:assertEquals(8, gdata:getHeight(), 'check height') + test:assertEquals(8, gdata:getWidth(), 'check width') + -- check boundary + local x, y, w, h = gdata:getBoundingBox() + local dw, dh = gdata:getDimensions() + local bw, bh = gdata:getBearing() + test:assertEquals(0, x, 'check bbox x') + test:assertEquals(-3, y, 'check bbox y') + test:assertEquals(8, w, 'check bbox w') + test:assertEquals(14, h, 'check bbox h') + test:assertEquals(8, dw, 'check dim width') + test:assertEquals(8, dh, 'check dim height') + test:assertEquals(0, bw, 'check bearing w') + test:assertEquals(11, bh, 'check bearing h') +end + + +-- Rasterizer (love.font.newRasterizer) +love.test.font.Rasterizer = function(test) + -- create obj + local rasterizer = love.font.newRasterizer('resources/font.ttf') + test:assertObject(rasterizer) + -- check properties match + test:assertEquals(9, rasterizer:getAdvance(), 'check advance') + test:assertEquals(9, rasterizer:getAscent(), 'check ascent') + test:assertEquals(-3, rasterizer:getDescent(), 'check descent') + test:assertEquals(77, rasterizer:getGlyphCount(), 'check glyph count') + test:assertObject(rasterizer:getGlyphData('L')) + test:assertEquals(12, rasterizer:getHeight(), 'check height') + test:assertEquals(15, rasterizer:getLineHeight(), 'check line height') + test:assertEquals(true, rasterizer:hasGlyphs('L', 'O', 'V', 'E'), 'check LOVE') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.font.newBMFontRasterizer --- @NOTE the wiki specifies diff. params to source code and trying to do --- what source code wants gives some errors still love.test.font.newBMFontRasterizer = function(test) - test:skipTest('wiki and source dont match, not sure expected usage') + local rasterizer = love.font.newBMFontRasterizer('resources/love.png'); + test:assertObject(rasterizer) end -- love.font.newGlyphData --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.font.newGlyphData = function(test) local img = love.image.newImageData('resources/love.png') local rasterizer = love.font.newImageRasterizer(img, 'ABC', 0, 1); @@ -20,7 +80,7 @@ end -- love.font.newImageRasterizer --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.font.newImageRasterizer = function(test) local img = love.image.newImageData('resources/love.png') local rasterizer = love.font.newImageRasterizer(img, 'ABC', 0, 1); @@ -29,14 +89,14 @@ end -- love.font.newRasterizer --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.font.newRasterizer = function(test) test:assertObject(love.font.newRasterizer('resources/font.ttf')) end -- love.font.newTrueTypeRasterizer --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.font.newTrueTypeRasterizer = function(test) test:assertObject(love.font.newTrueTypeRasterizer(12, "normal", 1)) test:assertObject(love.font.newTrueTypeRasterizer('resources/font.ttf', 8, "normal", 1)) diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua index 203c22aa0..8a1d0f28b 100644 --- a/testing/tests/graphics.lua +++ b/testing/tests/graphics.lua @@ -1,6 +1,79 @@ -- love.graphics +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- Canvas (love.graphics.newCanvas) +love.test.graphics.Canvas = function(test) + test:skipTest('test class needs writing') +end + + +-- Font (love.graphics.newFont) +love.test.graphics.Font = function(test) + test:skipTest('test class needs writing') +end + + +-- Image (love.graphics.newImage) +love.test.graphics.Image = function(test) + test:skipTest('test class needs writing') +end + + +-- Mesh (love.graphics.newMesh) +love.test.graphics.Mesh = function(test) + test:skipTest('test class needs writing') +end + + +-- ParticleSystem (love.graphics.newParticleSystem) +love.test.graphics.ParticleSystem = function(test) + test:skipTest('test class needs writing') +end + + +-- Quad (love.graphics.newQuad) +love.test.graphics.Quad = function(test) + test:skipTest('test class needs writing') +end + + +-- Shader (love.graphics.newShader) +love.test.graphics.Shader = function(test) + test:skipTest('test class needs writing') +end + + +-- SpriteBatch (love.graphics.newSpriteBatch) +love.test.graphics.SpriteBatch = function(test) + test:skipTest('test class needs writing') +end + + +-- Text (love.graphics.newTextBatch) +love.test.graphics.Text = function(test) + test:skipTest('test class needs writing') +end + + +-- Texture (love.graphics.newTexture) +love.test.graphics.Texture = function(test) + test:skipTest('test class needs writing') +end + + +-- Video (love.graphics.newVideo) +love.test.graphics.Video = function(test) + test:skipTest('test class needs writing') +end + + -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ------------------------------------DRAWING------------------------------------- @@ -222,7 +295,17 @@ end -- love.graphics.flushBatch love.test.graphics.flushBatch = function(test) - test:skipTest('not sure can be tested as used internally') + love.graphics.flushBatch() + local initial = love.graphics.getStats()['drawcalls'] + local canvas = love.graphics.newCanvas(32, 32) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.rectangle('fill', 0, 0, 32, 32) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setCanvas() + love.graphics.flushBatch() + local after = love.graphics.getStats()['drawcalls'] + test:assertEquals(initial+1, after, 'check drawcalls increased') end @@ -418,7 +501,7 @@ end -- love.graphics.newArrayImage --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newArrayImage = function(test) test:assertObject(love.graphics.newArrayImage({ 'resources/love.png', 'resources/love2.png', 'resources/love3.png' @@ -426,7 +509,7 @@ love.test.graphics.newArrayImage = function(test) end -- love.graphics.newCanvas --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newCanvas = function(test) test:assertObject(love.graphics.newCanvas(16, 16, { type = '2d', @@ -441,7 +524,7 @@ end -- love.graphics.newCubeImage --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newCubeImage = function(test) test:assertObject(love.graphics.newCubeImage('resources/cubemap.png', { mipmaps = false, @@ -451,7 +534,7 @@ end -- love.graphics.newFont --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newFont = function(test) test:assertObject(love.graphics.newFont('resources/font.ttf')) test:assertObject(love.graphics.newFont('resources/font.ttf', 8, "normal", 1)) @@ -459,7 +542,7 @@ end -- love.graphics.newImage --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newImage = function(test) test:assertObject(love.graphics.newImage('resources/love.png', { mipmaps = false, @@ -470,21 +553,21 @@ end -- love.graphics.newImageFont --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newImageFont = function(test) test:assertObject(love.graphics.newImageFont('resources/love.png', 'ABCD', 1)) end -- love.graphics.newMesh --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newMesh = function(test) test:assertObject(love.graphics.newMesh({{1, 1, 0, 0, 1, 1, 1, 1}}, 'fan', 'dynamic')) end -- love.graphics.newParticleSystem --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newParticleSystem = function(test) local imgdata = love.graphics.newImage('resources/love.png') test:assertObject(love.graphics.newParticleSystem(imgdata, 1000)) @@ -492,7 +575,7 @@ end -- love.graphics.newQuad --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newQuad = function(test) local imgdata = love.graphics.newImage('resources/love.png') test:assertObject(love.graphics.newQuad(0, 0, 16, 16, imgdata)) @@ -500,16 +583,25 @@ end -- love.graphics.newShader --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newShader = function(test) - local pixelcode = 'vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex, texture_coords); return texturecolor * color;}' - local vertexcode = 'vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform_projection * vertex_position; }' + local pixelcode = [[ + vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { + vec4 texturecolor = Texel(tex, texture_coords); + return texturecolor * color; + } + ]] + local vertexcode = [[ + vec4 position(mat4 transform_projection, vec4 vertex_position) { + return transform_projection * vertex_position; + } + ]] test:assertObject(love.graphics.newShader(pixelcode, vertexcode)) end -- love.graphics.newSpriteBatch --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newSpriteBatch = function(test) local imgdata = love.graphics.newImage('resources/love.png') test:assertObject(love.graphics.newSpriteBatch(imgdata, 1000)) @@ -517,7 +609,7 @@ end -- love.graphics.newText --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newTextBatch = function(test) local font = love.graphics.newFont('resources/font.ttf') test:assertObject(love.graphics.newTextBatch(font, 'helloworld')) @@ -525,7 +617,7 @@ end -- love.graphics.newVideo --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newVideo = function(test) test:assertObject(love.graphics.newVideo('resources/sample.ogv', { audio = false, @@ -535,7 +627,7 @@ end -- love.graphics.newVolumeImage --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.graphics.newVolumeImage = function(test) test:assertObject(love.graphics.newVolumeImage({ 'resources/love.png', 'resources/love2.png', 'resources/love3.png' @@ -548,8 +640,17 @@ end -- love.graphics.validateShader love.test.graphics.validateShader = function(test) - local pixelcode = 'vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex, texture_coords); return texturecolor * color;}' - local vertexcode = 'vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform_projection * vertex_position; }' + local pixelcode = [[ + vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { + vec4 texturecolor = Texel(tex, texture_coords); + return texturecolor * color; + } + ]] + local vertexcode = [[ + vec4 position(mat4 transform_projection, vec4 vertex_position) { + return transform_projection * vertex_position; + } + ]] -- check made up code first local status, _ = love.graphics.validateShader(true, 'nothing here', 'or here') test:assertEquals(false, status, 'check invalid shader code') @@ -829,25 +930,37 @@ end -- love.graphics.isActive love.test.graphics.isActive = function(test) - test:assertEquals(true, love.graphics.isActive(), 'check graphics is active') -- i mean if you got this far + local name, version, vendor, device = love.graphics.getRendererInfo() + if string.find(name, 'Vulkan') ~= nil then + test:skipTest('love.graphics.isActive() crashes on Vulkan') + else + test:assertEquals(true, love.graphics.isActive(), 'check graphics is active') -- i mean if you got this far + end end -- love.graphics.isGammaCorrect love.test.graphics.isGammaCorrect = function(test) -- we know the config so know this is false - test:assertEquals(false, love.graphics.isGammaCorrect(), 'check gamma correct false') + print('gammaCorrect #1') + test:assertNotNil(love.graphics.isGammaCorrect()) + print('gammaCorrect #2') end -- love.graphics.isWireframe love.test.graphics.isWireframe = function(test) - -- check off by default - test:assertEquals(false, love.graphics.isWireframe(), 'check no wireframe by default') - -- check on when enabled - love.graphics.setWireframe(true) - test:assertEquals(true, love.graphics.isWireframe(), 'check wireframe is set') - love.graphics.setWireframe(false) -- reset + local name, version, vendor, device = love.graphics.getRendererInfo() + if string.match(name, 'OpenGL ES') then + test:skipTest('Wireframe not supported on OpenGL ES') + else + -- check off by default + test:assertEquals(false, love.graphics.isWireframe(), 'check no wireframe by default') + -- check on when enabled + love.graphics.setWireframe(true) + test:assertEquals(true, love.graphics.isWireframe(), 'check wireframe is set') + love.graphics.setWireframe(false) -- reset + end end @@ -1193,8 +1306,17 @@ end -- love.graphics.setShader love.test.graphics.setShader = function(test) -- make a shader that will only ever draw yellow - local pixelcode = 'vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { vec4 texturecolor = Texel(tex, texture_coords); return vec4(1.0,1.0,0.0,1.0);}' - local vertexcode = 'vec4 position(mat4 transform_projection, vec4 vertex_position) { return transform_projection * vertex_position; }' + local pixelcode = [[ + vec4 effect(vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords) { + vec4 texturecolor = Texel(tex, texture_coords); + return vec4(1.0,1.0,0.0,1.0); + } + ]] + local vertexcode = [[ + vec4 position(mat4 transform_projection, vec4 vertex_position) { + return transform_projection * vertex_position; + } + ]] local shader = love.graphics.newShader(pixelcode, vertexcode) local canvas = love.graphics.newCanvas(16, 16) love.graphics.setCanvas(canvas) @@ -1238,22 +1360,27 @@ end -- love.graphics.setWireframe love.test.graphics.setWireframe = function(test) - -- check wireframe outlines - love.graphics.setWireframe(true) - local canvas = love.graphics.newCanvas(16, 16) - love.graphics.setCanvas(canvas) - love.graphics.clear(0, 0, 0, 1) - love.graphics.setColor(1, 1, 0, 1) - love.graphics.rectangle('fill', 2, 2, 13, 13) - love.graphics.setColor(1, 1, 1, 1) - love.graphics.setWireframe(false) - love.graphics.setCanvas() - local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) - test:assertPixels(imgdata, { - yellow = {{1,14},{14,1},{14,14},{2,2},{13,13}}, - black = {{2,13},{13,2}} - }, 'set wireframe') - test:exportImg(imgdata) + local name, version, vendor, device = love.graphics.getRendererInfo() + if string.match(name, 'OpenGL ES') then + test:skipTest('Wireframe not supported on OpenGL ES') + else + -- check wireframe outlines + love.graphics.setWireframe(true) + local canvas = love.graphics.newCanvas(16, 16) + love.graphics.setCanvas(canvas) + love.graphics.clear(0, 0, 0, 1) + love.graphics.setColor(1, 1, 0, 1) + love.graphics.rectangle('fill', 2, 2, 13, 13) + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setWireframe(false) + love.graphics.setCanvas() + local imgdata = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + test:assertPixels(imgdata, { + yellow = {{1,14},{14,1},{14,14},{2,2},{13,13}}, + black = {{2,13},{13,2}} + }, 'set wireframe') + test:exportImg(imgdata) + end end diff --git a/testing/tests/image.lua b/testing/tests/image.lua index e0a71d492..5de709a1a 100644 --- a/testing/tests/image.lua +++ b/testing/tests/image.lua @@ -1,6 +1,81 @@ -- love.image +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- CompressedImageData (love.image.newCompressedImageData) +love.test.image.CompressedImageData = function(test) + -- create obj + local idata = love.image.newCompressedData('resources/love.dxt1') + test:assertObject(idata) + -- check data properties + test:assertNotEquals(nil, idata:getString(), 'check data string') + test:assertEquals(2744, idata:getSize(), 'check data size') + -- check img data properties + local iw, ih = idata:getDimensions() + test:assertEquals(64, iw, 'check image dimension w') + test:assertEquals(64, ih, 'check image dimension h') + test:assertEquals('DXT1', idata:getFormat(), 'check image format') + test:assertEquals(64, idata:getWidth(), 'check image direct w') + test:assertEquals(64, idata:getHeight(), 'check image direct h') + test:assertEquals(7, idata:getMipmapCount(), 'check mipmap count') +end + + +-- ImageData (love.image.newImageData) +love.test.image.ImageData = function(test) + -- create obj + local idata = love.image.newImageData('resources/love.png') + test:assertObject(idata) + -- check data properties + test:assertNotEquals(nil, idata:getString(), 'check data string') + test:assertEquals(16384, idata:getSize(), 'check data size') + -- check img data properties + local iw, ih = idata:getDimensions() + test:assertEquals(64, iw, 'check image dimension w') + test:assertEquals(64, ih, 'check image dimension h') + test:assertEquals('rgba8', idata:getFormat(), 'check image format') + test:assertEquals(64, idata:getWidth(), 'check image direct w') + test:assertEquals(64, idata:getHeight(), 'check image direct h') + -- manipulate image data so white heart is black + local mapdata = function(x, y, r, g, b, a) + if r == 1 and g == 1 and b == 1 then + r = 0; g = 0; b = 0 + end + return r, g, b, a + end + idata:mapPixel(mapdata, 0, 0, 64, 64) + local r1, g1, b1 = idata:getPixel(25, 25) + test:assertEquals(0, r1+g1+b1, 'check mapped black') + -- map some other data into the idata + local idata2 = love.image.newImageData('resources/loveinv.png') + idata:paste(idata2, 0, 0, 0, 0) + r1, g1, b1 = idata:getPixel(25, 25) + test:assertEquals(3, r1+g1+b1, 'check back to white') + -- set pixels directly + idata:setPixel(25, 25, 1, 0, 0, 1) + r1, g1, b1 = idata:getPixel(25, 25) + test:assertEquals(1, r1+g1+b1, 'check set to red') + -- check encoding to an image + idata:encode('png', 'test-encode.png') + local read = love.filesystem.openFile('test-encode.png', 'r') + test:assertNotNil(read) + love.filesystem.remove('test-encode.png') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.image.isCompressed -- @NOTE really we need to test each of the files listed here: -- https://love2d.org/wiki/CompressedImageFormat @@ -12,14 +87,14 @@ end -- love.image.newCompressedData --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.image.newCompressedData = function(test) test:assertObject(love.image.newCompressedData('resources/love.dxt1')) end -- love.image.newImageData --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.image.newImageData = function(test) test:assertObject(love.image.newImageData('resources/love.png')) test:assertObject(love.image.newImageData(16, 16, 'rgba8', nil)) diff --git a/testing/tests/math.lua b/testing/tests/math.lua index 51e915728..14b9791c7 100644 --- a/testing/tests/math.lua +++ b/testing/tests/math.lua @@ -1,6 +1,156 @@ -- love.math +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- BezierCurve (love.math.newBezierCurve) +love.test.math.BezierCurve = function(test) + -- create obj + local curve = love.math.newBezierCurve(1, 1, 2, 2, 3, 1) + local px, py = curve:getControlPoint(2) + test:assertObject(curve) + -- check initial properties + test:assertCoords({2, 2}, {px, py}, 'check point x/y') + test:assertEquals(3, curve:getControlPointCount(), 'check 3 points') + test:assertEquals(2, curve:getDegree(), 'check degree is points-1') + -- check some values on the curve + test:assertEquals(1, curve:evaluate(0), 'check curve evaluation 0') + test:assertEquals(120, math.floor(curve:evaluate(0.1)*100), 'check curve evaluation 0.1') + test:assertEquals(140, math.floor(curve:evaluate(0.2)*100), 'check curve evaluation 0.2') + test:assertEquals(200, math.floor(curve:evaluate(0.5)*100), 'check curve evaluation 0.5') + test:assertEquals(3, curve:evaluate(1), 'check curve evaluation 1') + -- check derivative + local deriv = curve:getDerivative() + test:assertObject(deriv) + test:assertEquals(2, deriv:getControlPointCount(), 'check deriv points') + test:assertEquals(200, math.floor(deriv:evaluate(0.1)*100), 'check deriv evaluation 0.1') + -- check segment + local segment = curve:getSegment(0, 0.5) + test:assertObject(segment) + test:assertEquals(3, segment:getControlPointCount(), 'check segment points') + test:assertEquals(109, math.floor(segment:evaluate(0.1)*100), 'check segment evaluation 0.1') + -- mess with control points + curve:removeControlPoint(2) + curve:insertControlPoint(4, 1, -1) + curve:insertControlPoint(5, 3, -1) + curve:insertControlPoint(6, 2, -1) + curve:setControlPoint(2, 3, 2) + test:assertEquals(5, curve:getControlPointCount(), 'check 3 points still') + local px1, py1 = curve:getControlPoint(1) + local px2, py2 = curve:getControlPoint(3) + local px3, py3 = curve:getControlPoint(5) + test:assertCoords({1, 1}, {px1, py1}, 'check modified point 1') + test:assertCoords({5, 3}, {px2, py2}, 'check modified point 1') + test:assertCoords({3, 1}, {px3, py3}, 'check modified point 1') + -- check render lists + local coords1 = curve:render(5) + local coords2 = curve:renderSegment(0, 0.1, 5) + test:assertEquals(196, #coords1, 'check coords') + test:assertEquals(20, #coords2, 'check segment coords') + -- check translation values + px, py = curve:getControlPoint(2) + test:assertCoords({3, 2}, {px, py}, 'check pretransform x/y') + curve:rotate(90 * (math.pi/180), 0, 0) + px, py = curve:getControlPoint(2) + test:assertCoords({-2, 3}, {px, py}, 'check rotated x/y') + curve:scale(2, 0, 0) + px, py = curve:getControlPoint(2) + test:assertCoords({-4, 6}, {px, py}, 'check scaled x/y') + curve:translate(5, -5) + px, py = curve:getControlPoint(2) + test:assertCoords({1, 1}, {px, py}, 'check translated x/y') +end + + +-- RandomGenerator (love.math.RandomGenerator) +-- @NOTE as this checks random numbers the chances this fails is very unlikely, but not 0... +-- if you've managed to proc it congrats! your prize is to rerun the testsuite again +love.test.math.RandomGenerator = function(test) + -- create object + local rng1 = love.math.newRandomGenerator(3418323524, 20529293) + test:assertObject(rng1) + -- check set properties + local low, high = rng1:getSeed() + test:assertEquals(3418323524, low, 'check seed low') + test:assertEquals(20529293, high, 'check seed high') + -- check states + local rng2 = love.math.newRandomGenerator(1448323524, 10329293) + test:assertNotEquals(rng1:random(), rng2:random(), 'check not matching states') + test:assertNotEquals(rng1:randomNormal(), rng2:randomNormal(), 'check not matching states') + -- check setting state works + rng2:setState(rng1:getState()) + test:assertEquals(rng1:random(), rng2:random(), 'check now matching') + -- check overwriting seed works, should change output + rng1:setSeed(os.time()) + test:assertNotEquals(rng1:random(), rng2:random(), 'check not matching states') + test:assertNotEquals(rng1:randomNormal(), rng2:randomNormal(), 'check not matching states') +end + + +-- Transform (love.math.Transform) +love.test.math.Transform = function(test) + -- create obj + local transform = love.math.newTransform(0, 0, 0, 1, 1, 0, 0, 0, 0) + test:assertObject(transform) + -- set some values and check the matrix and transformPoint values + transform:translate(10, 8) + transform:scale(2, 3) + transform:rotate(90*(math.pi/180)) + transform:shear(1, 2) + local px, py = transform:transformPoint(1, 1) + test:assertCoords({4, 14}, {px, py}, 'check transformation methods') + transform:reset() + px, py = transform:transformPoint(1, 1) + test:assertCoords({1, 1}, {px, py}, 'check reset') + -- apply a transform to another transform + local transform2 = love.math.newTransform() + transform2:translate(5, 3) + transform:apply(transform2) + px, py = transform:transformPoint(1, 1) + test:assertCoords({6, 4}, {px, py}, 'check apply other transform') + -- check cloning a transform + local transform3 = transform:clone() + px, py = transform3:transformPoint(1, 1) + test:assertCoords({6, 4}, {px, py}, 'check clone transform') + -- check inverse and inverseTransform + transform:reset() + transform:translate(-14, 6) + local ipx, ipy = transform:inverseTransformPoint(0, 0) + transform:inverse() + px, py = transform:transformPoint(0, 0) + test:assertCoords({-px, -py}, {ipx, ipy}, 'check inverse points transform') + -- check matrix manipulation + transform:setTransformation(0, 0, 0, 1, 1, 0, 0, 0, 0) + transform:translate(4, 4) + local m1, m2, m3, m4, m5, m6, m7, m8, + m9, m10, m11, m12, m13, m14, m15, m16 = transform:getMatrix() + test:assertEquals(4, m4, 'check translate matrix x') + test:assertEquals(4, m8, 'check translate matrix y') + transform:setMatrix(m1, m2, m3, 3, m5, m6, m7, 1, m9, m10, m11, m12, m13, m14, m15, m16) + px, py = transform:transformPoint(1, 1) + test:assertCoords({4, 2}, {px, py}, 'check set matrix') + -- check affine vs non affine + transform:reset() + test:assertEquals(true, transform:isAffine2DTransform(), 'check affine 1') + transform:translate(4, 3) + test:assertEquals(true, transform:isAffine2DTransform(), 'check affine 2') + transform:setMatrix(1, 3, 4, 5.5, 1, 4.5, 2, 1, 3.4, 5.1, 4.1, 13, 1, 1, 2, 3) + test:assertEquals(false, transform:isAffine2DTransform(), 'check not affine') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.math.colorFromBytes love.test.math.colorFromBytes = function(test) -- check random value @@ -98,21 +248,21 @@ end -- love.math.newBezierCurve --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.math.newBezierCurve = function(test) test:assertObject(love.math.newBezierCurve({0, 0, 0, 1, 1, 1, 2, 1})) end -- love.math.newRandomGenerator --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.math.newRandomGenerator = function(test) test:assertObject(love.math.newRandomGenerator()) end -- love.math.newTransform --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.math.newTransform = function(test) test:assertObject(love.math.newTransform()) end diff --git a/testing/tests/objects.lua b/testing/tests/objects.lua deleted file mode 100644 index 2a03544b8..000000000 --- a/testing/tests/objects.lua +++ /dev/null @@ -1,411 +0,0 @@ --- objects put in their own test methods to test all attributes and class methods - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -------------------------------------AUDIO--------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- RecordingDevice (love.audio.getRecordingDevices) -love.test.objects.RecordingDevice = function(test) - test:skipTest('test class needs writing') -end - - --- Source (love.audio.newSource) -love.test.objects.Source = function(test) - test:skipTest('test class needs writing') - -- local source1 = love.audio.newSource('resources/click.ogg', 'static') - --source1:clone() - --source1:getChannelCount() - --source1:getDuration() - --source1:isRelative() - --source1:queue() - --source1:getFreeBufferCount() - --source1:getType() - --source1:isPlaying() - --source1:play() - --source1:pause() - --source1:stop() - --source1:seek() - --source1:tell() - --source1:isLooping() - --source1:setLooping() - --source1:setAirAbsorption() - --source1:getAirAbsorption() - --source1:setAttenuationDistances() - --source1:getAttenuationDistances() - --source1:setCone() - --source1:getCone() - --source1:setDirection() - --source1:getDirection() - --source1:setEffect() - --source1:getEffect() - --source1:getActiveEffects() - --source1:setFilter() - --source1:getFilter() - --source1:setPitch() - --source1:getPitch() - --source1:setPosition() - --source1:getPosition() - --source1:setRelative() - --source1:setRolloff() - --source1:getRolloff() - --source1:setVelocity() - --source1:getVelocity() - --source1:setVolume() - --source1:getVolume() - --source1:setVolumeLimits() - --source1:getVolumeLimits() -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -------------------------------------DATA---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- ByteData (love.data.newByteData) -love.test.objects.ByteData = function(test) - test:skipTest('test class needs writing') -end - - --- CompressedData (love.data.compress) -love.test.objects.CompressedData = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- ----------------------------------FILESYSTEM------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- File (love.filesystem.newFile) -love.test.objects.File = function(test) - - -- setup a file to play with - local file1 = love.filesystem.openFile('data.txt', 'w') - file1:write('helloworld') - test:assertObject(file1) - file1:close() - - -- test read mode - file1:open('r') - test:assertEquals('r', file1:getMode(), 'check read mode') - local contents, size = file1:read() - test:assertEquals('helloworld', contents) - test:assertEquals(10, size, 'check file read') - test:assertEquals(10, file1:getSize()) - local ok, err = file1:write('hello') - test:assertNotEquals(nil, err, 'check cant write in read mode') - local iterator = file1:lines() - test:assertNotEquals(nil, iterator, 'check can read lines') - test:assertEquals('data.txt', file1:getFilename(), 'check filename matches') - file1:close() - - -- test write mode - file1:open('w') - test:assertEquals('w', file1:getMode(), 'check write mode') - contents, size = file1:read() - test:assertEquals(nil, contents, 'check cant read file in write mode') - test:assertEquals('string', type(size), 'check err message shown') - ok, err = file1:write('helloworld') - test:assertEquals(true, ok, 'check file write') - test:assertEquals(nil, err, 'check no err writing') - - -- test open/closing - file1:open('r') - test:assertEquals(true, file1:isOpen(), 'check file is open') - file1:close() - test:assertEquals(false, file1:isOpen(), 'check file gets closed') - file1:close() - - -- test buffering - -- @NOTE think I'm just not understanding how this is supposed to work? - -- I thought if buffering is enabled then nothing should get written until - -- buffer overflows? - -- file1:open('a') - -- ok, err = file1:setBuffer('full', 10000) - -- test:assertEquals(true, ok) - -- test:assertEquals('full', file1:getBuffer()) - -- file1:write('morecontent') - -- file1:close() - -- file1:open('r') - -- contents, size = file1:read() - -- test:assertEquals('helloworld', contents, 'check buffered content wasnt written') - -- file1:close() - - -- @NOTE :close() commits buffer content so need to check before not after - - -- test buffering and flushing - file1:open('w') - ok, err = file1:setBuffer('full', 10000) - test:assertEquals(true, ok) - test:assertEquals('full', file1:getBuffer()) - file1:write('replacedcontent') - file1:flush() - file1:close() - file1:open('r') - contents, size = file1:read() - test:assertEquals('replacedcontent', contents, 'check buffered content was written') - file1:close() - - -- loop through file data with seek/tell until EOF - file1:open('r') - local counter = 0 - for i=1,100 do - file1:seek(i) - test:assertEquals(i, file1:tell()) - if file1:isEOF() == true then - counter = i - break - end - end - test:assertEquals(counter, 15) - file1:close() - -end - - --- FileData (love.filesystem.newFileData) -love.test.objects.FileData = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -------------------------------------FONT---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- GlyphData (love.font.newGlyphData) -love.test.objects.GlyphData = function(test) - test:skipTest('test class needs writing') -end - - --- Rasterizer (love.font.newRasterizer) -love.test.objects.Rasterizer = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- ----------------------------------GRAPHICS--------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- Canvas (love.graphics.newCanvas) -love.test.objects.Canvas = function(test) - test:skipTest('test class needs writing') -end - - --- Font (love.graphics.newFont) -love.test.objects.Font = function(test) - test:skipTest('test class needs writing') -end - - --- Image (love.graphics.newImage) -love.test.objects.Image = function(test) - test:skipTest('test class needs writing') -end - - --- Mesh (love.graphics.newMesh) -love.test.objects.Mesh = function(test) - test:skipTest('test class needs writing') -end - - --- ParticleSystem (love.graphics.newParticleSystem) -love.test.objects.ParticleSystem = function(test) - test:skipTest('test class needs writing') -end - - --- Quad (love.graphics.newQuad) -love.test.objects.Quad = function(test) - test:skipTest('test class needs writing') -end - - --- Shader (love.graphics.newShader) -love.test.objects.Shader = function(test) - test:skipTest('test class needs writing') -end - - --- SpriteBatch (love.graphics.newSpriteBatch) -love.test.objects.SpriteBatch = function(test) - test:skipTest('test class needs writing') -end - - --- Text (love.graphics.newTextBatch) -love.test.objects.Text = function(test) - test:skipTest('test class needs writing') -end - - --- Texture (love.graphics.newTexture) -love.test.objects.Texture = function(test) - test:skipTest('test class needs writing') -end - - --- Video (love.graphics.newVideo) -love.test.objects.Video = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- ------------------------------------IMAGE---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- CompressedImageData (love.image.newCompressedImageData) -love.test.objects.CompressedImageData = function(test) - test:skipTest('test class needs writing') -end - - --- ImageData (love.image.newImageData) -love.test.objects.ImageData = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -------------------------------------MATH---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- BezierCurve (love.math.newBezierCurve) -love.test.objects.BezierCurve = function(test) - test:skipTest('test class needs writing') -end - - --- RandomGenerator (love.math.RandomGenerator) -love.test.objects.RandomGenerator = function(test) - test:skipTest('test class needs writing') -end - - --- Transform (love.math.Transform) -love.test.objects.Transform = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -----------------------------------PHYSICS--------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- Body (love.physics.newBody) -love.test.objects.Body = function(test) - test:skipTest('test class needs writing') -end - - --- Contact (love.physics.World:getContacts) -love.test.objects.Contact = function(test) - test:skipTest('test class needs writing') -end - - --- Fixture (love.physics.newFixture) -love.test.objects.Fixture = function(test) - test:skipTest('test class needs writing') -end - - --- Joint (love.physics.newDistanceJoint) -love.test.objects.Joint = function(test) - test:skipTest('test class needs writing') -end - - --- Shape (love.physics.newCircleShape) -love.test.objects.Shape = function(test) - test:skipTest('test class needs writing') -end - - --- World (love.physics.newWorld) -love.test.objects.World = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- ------------------------------------SOUND---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- Decoder (love.sound.newDecoder) -love.test.objects.Decoder = function(test) - test:skipTest('test class needs writing') -end - - --- SoundData (love.sound.newSoundData) -love.test.objects.SoundData = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -----------------------------------THREAD---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- Channel (love.thread.newChannel) -love.test.objects.Channel = function(test) - test:skipTest('test class needs writing') -end - - --- Thread (love.thread.newThread) -love.test.objects.Thread = function(test) - test:skipTest('test class needs writing') -end - - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- ------------------------------------VIDEO---------------------------------------- --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - - --- VideoStream (love.thread.newVideoStream) -love.test.objects.VideoStream = function(test) - test:skipTest('test class needs writing') -end diff --git a/testing/tests/physics.lua b/testing/tests/physics.lua index 87b99da3b..929bbf0e6 100644 --- a/testing/tests/physics.lua +++ b/testing/tests/physics.lua @@ -1,6 +1,56 @@ -- love.physics +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------OBJECTS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- Body (love.physics.newBody) +love.test.physics.Body = function(test) + test:skipTest('test class needs writing') +end + + +-- Contact (love.physics.World:getContacts) +love.test.physics.Contact = function(test) + test:skipTest('test class needs writing') +end + + +-- Fixture (love.physics.newFixture) +love.test.physics.Fixture = function(test) + test:skipTest('test class needs writing') +end + + +-- Joint (love.physics.newDistanceJoint) +love.test.physics.Joint = function(test) + test:skipTest('test class needs writing') +end + + +-- Shape (love.physics.newCircleShape) +love.test.physics.Shape = function(test) + test:skipTest('test class needs writing') +end + + +-- World (love.physics.newWorld) +love.test.physics.World = function(test) + test:skipTest('test class needs writing') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.physics.getDistance love.test.physics.getDistance = function(test) -- setup two fixtues to check @@ -24,7 +74,7 @@ end -- love.physics.newBody --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newBody = function(test) local world = love.physics.newWorld(1, 1, true) local body = love.physics.newBody(world, 10, 10, 'static') @@ -33,21 +83,21 @@ end -- love.physics.newChainShape --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newChainShape = function(test) test:assertObject(love.physics.newChainShape(true, 0, 0, 1, 0, 1, 1, 0, 1)) end -- love.physics.newCircleShape --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newCircleShape = function(test) test:assertObject(love.physics.newCircleShape(10)) end -- love.physics.newDistanceJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newDistanceJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -58,7 +108,7 @@ end -- love.physics.newEdgeShape --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newEdgeShape = function(test) local obj = love.physics.newEdgeShape(0, 0, 10, 10) test:assertObject(obj) @@ -66,7 +116,7 @@ end -- love.physics.newFixture --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newFixture = function(test) local world = love.physics.newWorld(1, 1, true) local body = love.physics.newBody(world, 10, 10, 'static') @@ -77,7 +127,7 @@ end -- love.physics.newFrictionJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newFrictionJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -88,7 +138,7 @@ end -- love.physics.newGearJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newGearJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'dynamic') @@ -103,7 +153,7 @@ end -- love.physics.newMotorJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newMotorJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -114,7 +164,7 @@ end -- love.physics.newMouseJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newMouseJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body = love.physics.newBody(world, 10, 10, 'static') @@ -124,7 +174,7 @@ end -- love.physics.newPolygonShape --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newPolygonShape = function(test) local obj = love.physics.newPolygonShape({0, 0, 2, 3, 2, 1, 3, 1, 5, 1}) test:assertObject(obj) @@ -132,7 +182,7 @@ end -- love.physics.newPrismaticJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newPrismaticJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -143,7 +193,7 @@ end -- love.physics.newPulleyJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newPulleyJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -154,7 +204,7 @@ end -- love.physics.newRectangleShape --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newRectangleShape = function(test) local shape1 = love.physics.newRectangleShape(10, 20) local shape2 = love.physics.newRectangleShape(10, 10, 40, 30, 10) @@ -164,7 +214,7 @@ end -- love.physics.newRevoluteJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newRevoluteJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -175,7 +225,7 @@ end -- love.physics.newRopeJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newRopeJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -186,7 +236,7 @@ end -- love.physics.newWeldJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newWeldJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -197,7 +247,7 @@ end -- love.physics.newWheelJoint --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newWheelJoint = function(test) local world = love.physics.newWorld(1, 1, true) local body1 = love.physics.newBody(world, 10, 10, 'static') @@ -208,7 +258,7 @@ end -- love.physics.newWorld --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.physics.newWorld = function(test) local world = love.physics.newWorld(1, 1, true) test:assertObject(world) diff --git a/testing/tests/sound.lua b/testing/tests/sound.lua index 88d3398ba..887aabf0b 100644 --- a/testing/tests/sound.lua +++ b/testing/tests/sound.lua @@ -1,15 +1,81 @@ -- love.sound +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------OBJECTS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- Decoder (love.sound.newDecoder) +love.test.sound.Decoder = function(test) + -- create obj + local decoder = love.sound.newDecoder('resources/click.ogg') + test:assertObject(decoder) + -- check decoder props + test:assertMatch({8, 16}, decoder:getBitDepth(), 'check bit depth') + test:assertMatch({1, 2}, decoder:getChannelCount(), 'check channel count') + test:assertEquals(66, math.floor(decoder:getDuration()*1000), 'check duration') + test:assertEquals(44100, decoder:getSampleRate(), 'check sample rate') + -- check makes sound data (test in method below) + test:assertObject(decoder:decode()) + -- check cloning sound + local clone = decoder:clone() + test:assertMatch({8, 16}, clone:getBitDepth(), 'check cloned bit depth') + test:assertMatch({1, 2}, clone:getChannelCount(), 'check cloned channel count') + test:assertEquals(66, math.floor(clone:getDuration()*1000), 'check cloned duration') + test:assertEquals(44100, clone:getSampleRate(), 'check cloned sample rate') +end + + +-- SoundData (love.sound.newSoundData) +love.test.sound.SoundData = function(test) + -- create obj + local sdata = love.sound.newSoundData('resources/click.ogg') + test:assertObject(sdata) + -- check data props + test:assertEquals(11708, sdata:getSize(), 'check size') + test:assertNotNil(sdata:getString()) + test:assertMatch({8, 16}, sdata:getBitDepth(), 'check bit depth') + test:assertMatch({1, 2}, sdata:getChannelCount(), 'check channel count') + test:assertEquals(66, math.floor(sdata:getDuration()*1000), 'check duration') + test:assertEquals(44100, sdata:getSampleRate(), 'check sample rate') + test:assertEquals(2927, sdata:getSampleCount(), 'check sample count') + -- check cloning + local clone = sdata:clone() + test:assertEquals(11708, clone:getSize(), 'check clone size') + test:assertNotNil(clone:getString()) + test:assertMatch({8, 16}, clone:getBitDepth(), 'check clone bit depth') + test:assertMatch({1, 2}, clone:getChannelCount(), 'check clone channel count') + test:assertEquals(66, math.floor(clone:getDuration()*1000), 'check clone duration') + test:assertEquals(44100, clone:getSampleRate(), 'check clone sample rate') + test:assertEquals(2927, clone:getSampleCount(), 'check clone sample count') + -- check sample setting + test:assertEquals(-22, math.floor(sdata:getSample(0.001)*100000), 'check sample 1') + test:assertEquals(-22, math.floor(sdata:getSample(0.005)*100000), 'check sample 1') + sdata:setSample(0.002, 1) + test:assertEquals(1, sdata:getSample(0.002), 'check setting sample manually') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +------------------------------------METHODS------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + + -- love.sound.newDecoder --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.sound.newDecoder = function(test) test:assertObject(love.sound.newDecoder('resources/click.ogg')) end -- love.sound.newSoundData --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.sound.newSoundData = function(test) test:assertObject(love.sound.newSoundData('resources/click.ogg')) test:assertObject(love.sound.newSoundData(math.floor((1/32)*44100), 44100, 16, 1)) diff --git a/testing/tests/system.lua b/testing/tests/system.lua index 432352ec5..e8ef4229c 100644 --- a/testing/tests/system.lua +++ b/testing/tests/system.lua @@ -1,6 +1,13 @@ -- love.system +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------METHODS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.system.getClipboardText love.test.system.getClipboardText = function(test) -- ignore if not using window diff --git a/testing/tests/thread.lua b/testing/tests/thread.lua index 8bbcab62f..8714ffeda 100644 --- a/testing/tests/thread.lua +++ b/testing/tests/thread.lua @@ -1,22 +1,124 @@ -- love.thread +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------OBJECTS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- Channel (love.thread.newChannel) +love.test.thread.Channel = function(test) + -- create channel + local channel = love.thread.getChannel('test') + test:assertObject(channel) + -- setup thread to use + local threadcode1 = [[ + require("love.timer") + love.timer.sleep(0.1) + love.thread.getChannel('test'):push('hello world') + love.timer.sleep(0.1) + love.thread.getChannel('test'):push('me again') + ]] + local thread1 = love.thread.newThread(threadcode1) + thread1:start() + -- check message sent from thread to channel + local msg1 = channel:demand() + test:assertEquals('hello world', msg1, 'check 1st message was sent') + thread1:wait() + test:assertEquals(1, channel:getCount(), 'check still another message') + test:assertEquals('me again', channel:peek(), 'check 2nd message pending') + local msg2 = channel:pop() + test:assertEquals('me again', msg2, 'check 2nd message was sent') + channel:clear() + -- setup another thread for some ping pong + local threadcode2 = [[ + local function setChannel(channel, value) + channel:clear() + return channel:push(value) + end + local channel = love.thread.getChannel('test') + local waiting = true + local sent = nil + while waiting == true do + if sent == nil then + sent = channel:performAtomic(setChannel, 'ping') + end + if channel:hasRead(sent) then + local msg = channel:demand() + if msg == 'pong' then + channel:push(msg) + waiting = false + end + end + end + ]] + -- first we run a thread that will send 1 ping + local thread2 = love.thread.newThread(threadcode2) + thread2:start() + -- we wait for that ping to be sent and then send a pong back + local msg3 = channel:demand() + test:assertEquals('ping', msg3, 'check message recieved 1') + -- thread should be waiting for us, and checking is the ping was read + channel:supply('pong', 1) + -- if it was then it should send back our pong and thread should die + thread2:wait() + local msg4 = channel:pop() + test:assertEquals('pong', msg4, 'check message recieved 2') + test:assertEquals(0, channel:getCount()) +end + + +-- Thread (love.thread.newThread) +love.test.thread.Thread = function(test) + -- create thread + local threadcode = [[ + local b = 0 + for a=1,100000 do + b = b + a + end + ]] + local thread = love.thread.newThread(threadcode) + test:assertObject(thread) + -- check thread runs + thread:start() + test:assertEquals(true, thread:isRunning(), 'check started') + thread:wait() + test:assertEquals(false, thread:isRunning(), 'check finished') + test:assertEquals(nil, thread:getError(), 'check no errors') + -- check an invalid thread + local badthreadcode = 'local b = 0\nreturn b + "string" .. 10' + local badthread = love.thread.newThread(badthreadcode) + badthread:start() + badthread:wait() + test:assertNotNil(badthread:getError()) +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------METHODS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.thread.getChannel --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.thread.getChannel = function(test) test:assertObject(love.thread.getChannel('test')) end -- love.thread.newChannel --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.thread.newChannel = function(test) test:assertObject(love.thread.newChannel()) end -- love.thread.newThread --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.thread.newThread = function(test) test:assertObject(love.thread.newThread('classes/TestSuite.lua')) end diff --git a/testing/tests/timer.lua b/testing/tests/timer.lua index ca82449d3..3fd1b5b53 100644 --- a/testing/tests/timer.lua +++ b/testing/tests/timer.lua @@ -1,6 +1,13 @@ -- love.timer +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------METHODS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.timer.getAverageDelta -- @NOTE not sure if you could reliably get a specific delta? love.test.timer.getAverageDelta = function(test) diff --git a/testing/tests/video.lua b/testing/tests/video.lua index a67aaac11..06b4eea7c 100644 --- a/testing/tests/video.lua +++ b/testing/tests/video.lua @@ -1,8 +1,42 @@ -- love.video +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------OBJECTS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + +-- VideoStream (love.thread.newVideoStream) +love.test.video.VideoStream = function(test) + -- create obj + local video = love.video.newVideoStream('resources/sample.ogv') + test:assertObject(video) + -- check def properties + test:assertEquals('resources/sample.ogv', video:getFilename(), 'check filename') + test:assertEquals(false, video:isPlaying(), 'check not playing by def') + -- check playing and pausing + video:play() + test:assertEquals(true, video:isPlaying(), 'check now playing') + video:seek(0.3) + test:assertEquals(0.3, video:tell(), 'check seek/tell') + video:rewind() + test:assertEquals(0, video:tell(), 'check rewind') + video:pause() + test:assertEquals(false, video:isPlaying(), 'check paused') +end + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------METHODS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.video.newVideoStream --- @NOTE this is just basic nil checking, full obj test are in objects.lua +-- @NOTE this is just basic nil checking, objs have their own test method love.test.video.newVideoStream = function(test) test:assertObject(love.video.newVideoStream('resources/sample.ogv')) end diff --git a/testing/tests/window.lua b/testing/tests/window.lua index ae2cfdb9e..44d21a235 100644 --- a/testing/tests/window.lua +++ b/testing/tests/window.lua @@ -1,6 +1,13 @@ -- love.window +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +----------------------------------METHODS--------------------------------------- +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + + -- love.window.close love.test.window.close = function(test) -- closing window should cause graphics to not be active @@ -130,12 +137,6 @@ end -- love.window.getVSync love.test.window.getVSync = function(test) test:assertNotNil(love.window.getVSync()) - -- check turning off - love.window.setVSync(0) - test:assertEquals(0, love.window.getVSync(), 'check vsync off') - -- check turning on - love.window.setVSync(1) - test:assertEquals(1, love.window.getVSync(), 'check vsync on') end @@ -168,6 +169,7 @@ end -- love.window.isMaximized love.test.window.isMaximized = function(test) if test:isDelayed() == false then + test:assertEquals(false, love.window.isMaximized(), 'check window not maximized') love.window.maximize() test:setDelay(10) else @@ -180,12 +182,17 @@ end -- love.window.isMinimized love.test.window.isMinimized = function(test) - -- check not minimized to start - test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') - -- try to minimize - love.window.minimize() - test:assertEquals(true, love.window.isMinimized(), 'check window minimized') - love.window.restore() + if test:isDelayed() == false then + -- check not minimized to start + test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') + -- try to minimize + love.window.minimize() + test:setDelay(10) + else + -- on linux minimize won't get recognized immediately, so wait a few frames + test:assertEquals(true, love.window.isMinimized(), 'check window minimized') + love.window.restore() + end end @@ -214,6 +221,7 @@ end -- love.window.maximize love.test.window.maximize = function(test) if test:isDelayed() == false then + test:assertEquals(false, love.window.isMaximized(), 'check window not maximized') -- check maximizing is set love.window.maximize() test:setDelay(10) @@ -227,10 +235,16 @@ end -- love.window.minimize love.test.window.minimize = function(test) - -- check minimizing is set - love.window.minimize() - test:assertEquals(true, love.window.isMinimized(), 'check window minimized') - love.window.restore() + if test:isDelayed() == false then + test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') + -- check minimizing is set + love.window.minimize() + test:setDelay(10) + else + -- on linux we need to wait a few frames + test:assertEquals(true, love.window.isMinimized(), 'check window maximized') + love.window.restore() + end end @@ -242,12 +256,20 @@ end -- love.window.restore love.test.window.restore = function(test) - -- check minimized to start - love.window.minimize() - test:assertEquals(true, love.window.isMinimized(), 'check window minimized') - -- check restoring the state of the window - love.window.restore() - test:assertEquals(false, love.window.isMinimized(), 'check window restored') + + -- TODO: for linux runner + -- test doesn't pass because the current test delay system can't wait twice + + if test:isDelayed() == false then + -- check minimized to start + love.window.minimize() + love.window.restore() + test:setDelay(10) + else + -- check restoring the state of the window + test:assertEquals(false, love.window.isMinimized(), 'check window restored') + end + end @@ -305,11 +327,15 @@ end -- love.window.setPosition love.test.window.setPosition = function(test) - -- check position is returned - love.window.setPosition(100, 100, 1) - local x, y, _ = love.window.getPosition() - test:assertEquals(100, x, 'check position x') - test:assertEquals(100, y, 'check position y') + if test:isDelayed() == false then + -- check position is returned + love.window.setPosition(100, 100, 1) + test:setDelay(10) + else + local x, y, _ = love.window.getPosition() + test:assertEquals(100, x, 'check position x') + test:assertEquals(100, y, 'check position y') + end end @@ -324,12 +350,8 @@ end -- love.window.setVSync love.test.window.setVSync = function(test) - -- check setting vsync value off love.window.setVSync(0) - test:assertEquals(0, love.window.getVSync(), 'check vsync off') - -- check setting vsync value on - love.window.setVSync(1) - test:assertEquals(1, love.window.getVSync(), 'check vsync on') + test:assertNotNil(love.window.getVSync()) end diff --git a/testing/todo.md b/testing/todo.md index a212b2ab1..b84d8d527 100644 --- a/testing/todo.md +++ b/testing/todo.md @@ -1,31 +1,26 @@ `/Applications/love_12.app/Contents/MacOS/love ./testing` -## TESTSUITE -- [ ] move object methods to respective modules -- [ ] start object methods -- [ ] setStencilMode to replace setStencilTest +## GENERAL +- [ ] check 12.0 wiki page for new methods +- [ ] change delay system to use coroutines +- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) -## GRAPHICS +## OBJECT TESTS +- [ ] physics.Body, physics.Contact, physics.Fixture, + physics.Joint, physics.Shape, physics.World +- [ ] threads.Channel, threads.Thread + +## METHOD TESTS +- [ ] event.wait +- [ ] graphics.present +- [ ] graphics.drawInstanced + +## DEPRECATED +- [ ] deprecated setStencilTest (use setStencilMode) +- [ ] deprecated physics methods + +## GRAPHIC TESTS Methods that need a actual graphic pixel checks if possible: - [ ] setDepthMode - [ ] setFrontFaceWinding - [ ] setMeshCullMode -- [ ] present -- [ ] drawInstanced - -## FUTURE -- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) -- [ ] use coroutines for the delay action? i.e. wrap each test call in coroutine -- [ ] could nil check some joystick and keyboard methods? - -## GITHUB ACTION CI -- [ ] linux needs to run xvfb-run with the appimage -- [ ] try vulkan on windows/linux -- [ ] ios test run? - -## NOTES -Can't run --renderers metal on github action images: -Run love-macos/love.app/Contents/MacOS/love testing --renderers metal -Cannot create Metal renderer: Metal is not supported on this system. -Cannot create graphics: no supported renderer on this system. -Error: Cannot create graphics: no supported renderer on this system. From 343d192f1008e0c46576d173154db55a6a607cdf Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 14 Oct 2023 15:01:01 -0300 Subject: [PATCH 062/409] Compressed texture formats have explicit sRGB variants --- src/common/pixelformat.cpp | 389 ++++++++++++++--------- src/common/pixelformat.h | 61 +++- src/modules/graphics/Graphics.cpp | 4 +- src/modules/graphics/Graphics.h | 2 +- src/modules/graphics/Texture.cpp | 8 +- src/modules/graphics/Texture.h | 2 - src/modules/graphics/metal/Graphics.h | 2 +- src/modules/graphics/metal/Graphics.mm | 66 ++-- src/modules/graphics/metal/Metal.h | 2 +- src/modules/graphics/metal/Metal.mm | 215 +++++++++---- src/modules/graphics/metal/Texture.mm | 2 +- src/modules/graphics/opengl/Graphics.cpp | 15 +- src/modules/graphics/opengl/Graphics.h | 2 +- src/modules/graphics/opengl/OpenGL.cpp | 328 ++++++++++++------- src/modules/graphics/opengl/OpenGL.h | 4 +- src/modules/graphics/opengl/Shader.cpp | 3 +- src/modules/graphics/opengl/Texture.cpp | 15 +- src/modules/graphics/vulkan/Graphics.cpp | 8 +- src/modules/graphics/vulkan/Graphics.h | 2 +- src/modules/graphics/vulkan/Texture.cpp | 6 +- src/modules/graphics/vulkan/Vulkan.cpp | 167 +++++++--- src/modules/graphics/vulkan/Vulkan.h | 2 +- src/modules/graphics/wrap_Graphics.cpp | 13 +- src/modules/image/magpie/ASTCHandler.cpp | 28 +- src/modules/image/magpie/KTXHandler.cpp | 28 +- src/modules/image/magpie/PVRHandler.cpp | 28 +- 26 files changed, 890 insertions(+), 512 deletions(-) diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index fad2611e7..42325510f 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -26,101 +26,126 @@ namespace love static PixelFormatInfo formatInfo[] = { - // components, blockW, blockH, blockSize, color, depth, stencil, compressed, dataType - { 0, 1, 1, 0, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN + // components, blockW, blockH, blockSize, color, depth, stencil, compressed, sRGB, dataType + { 0, 1, 1, 0, false, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN - { 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL - { 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR + { 0, 1, 1, 0, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL + { 0, 1, 1, 0, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR - { 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM - { 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT - { 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT - { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM - { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT - { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT - { 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT - { 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT - { 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT - { 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT + { 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM + { 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT + { 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT + { 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM + { 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT + { 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT + { 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT + { 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT + { 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT + { 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT - { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM - { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT - { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT - { 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM - { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM - { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT - { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT - { 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT - { 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT - { 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT - { 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT + { 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM + { 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT + { 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT + { 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM + { 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM + { 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT + { 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT + { 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT + { 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT + { 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT + { 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM_sRGB - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM_sRGB - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT - { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM - { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT - { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT - { 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT - { 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT - { 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT - { 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT + { 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM + { 4, 1, 1, 4, true, false, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_sRGB + { 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM + { 4, 1, 1, 4, true, false, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_sRGB + { 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT + { 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT + { 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM + { 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT + { 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT + { 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT + { 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT + { 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT + { 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT - { 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM - { 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM - { 3, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM - { 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM - { 3, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT + { 4, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM + { 4, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM + { 3, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM + { 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM + { 3, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT - { 1, 1, 1, 1, false, false, true , false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8 - { 1, 1, 1, 2, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM - { 1, 1, 1, 3, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM - { 1, 1, 1, 4, false, true, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT - { 2, 1, 1, 4, false, true, true , false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8 - { 2, 1, 1, 5, false, true, true , false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 + { 1, 1, 1, 1, false, false, true , false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8 + { 1, 1, 1, 2, false, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM + { 1, 1, 1, 3, false, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM + { 1, 1, 1, 4, false, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT + { 2, 1, 1, 4, false, true, true , false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8 + { 2, 1, 1, 5, false, true, true , false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 - { 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM - { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM - { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM - { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM - { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM - { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM - { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM - { 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT - { 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT - { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM + { 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM + { 3, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_sRGB + { 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM + { 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_sRGB + { 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM + { 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_sRGB + { 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM + { 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM + { 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM + { 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM + { 3, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT + { 3, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT + { 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM + { 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_sRGB - { 3, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM - { 3, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM - { 4, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM - { 4, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM + { 3, 16, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM + { 3, 16, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_sRGB + { 3, 8, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM + { 3, 8, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_sRGB + { 4, 16, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM + { 4, 16, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_sRGB + { 4, 8, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM + { 4, 8, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_sRGB - { 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM - { 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM - { 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM - { 4, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM - { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM - { 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM - { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM - { 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM + { 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM + { 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM + { 3, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_sRGB + { 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM + { 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_sRGB + { 4, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM + { 4, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_sRGB + { 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM + { 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM + { 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM + { 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM - { 4, 4, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4 - { 4, 5, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4 - { 4, 5, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5 - { 4, 6, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5 - { 4, 6, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6 - { 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5 - { 4, 8, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6 - { 4, 8, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8 - { 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5 - { 4, 10, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6 - { 4, 10, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8 - { 4, 10, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10 - { 4, 12, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10 - { 4, 12, 12, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12 + { 4, 4, 4, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4_UNORM + { 4, 5, 4, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4_UNORM + { 4, 5, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5_UNORM + { 4, 6, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5_UNORM + { 4, 6, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6_UNORM + { 4, 8, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5_UNORM + { 4, 8, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6_UNORM + { 4, 8, 8, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8_UNORM + { 4, 8, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5_UNORM + { 4, 10, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6_UNORM + { 4, 10, 8, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8_UNORM + { 4, 10, 10, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10_UNORM + { 4, 12, 10, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10_UNORM + { 4, 12, 12, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12_UNORM + { 4, 4, 4, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4_sRGB + { 4, 5, 4, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4_sRGB + { 4, 5, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5_sRGB + { 4, 6, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5_sRGB + { 4, 6, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6_sRGB + { 4, 8, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5_sRGB + { 4, 8, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6_sRGB + { 4, 8, 8, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8_sRGB + { 4, 8, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5_sRGB + { 4, 10, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6_sRGB + { 4, 10, 8, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8_sRGB + { 4, 10, 10, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10_sRGB + { 4, 12, 10, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10_sRGB + { 4, 12, 12, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12_sRGB }; static_assert(sizeof(formatInfo) / sizeof(PixelFormatInfo) == PIXELFORMAT_MAX_ENUM, "Update the formatInfo array when adding or removing a PixelFormat"); @@ -155,19 +180,19 @@ static StringMap::Entry formatEntries[] = { "rg32i", PIXELFORMAT_RG32_INT }, { "rg32ui", PIXELFORMAT_RG32_UINT }, - { "rgba8", PIXELFORMAT_RGBA8_UNORM }, - { "srgba8", PIXELFORMAT_RGBA8_UNORM_sRGB }, - { "bgra8", PIXELFORMAT_BGRA8_UNORM }, - { "bgra8srgb", PIXELFORMAT_BGRA8_UNORM_sRGB }, - { "rgba8i", PIXELFORMAT_RGBA8_INT }, - { "rgba8ui", PIXELFORMAT_RGBA8_UINT }, - { "rgba16", PIXELFORMAT_RGBA16_UNORM }, - { "rgba16f", PIXELFORMAT_RGBA16_FLOAT }, - { "rgba16i", PIXELFORMAT_RGBA16_INT }, - { "rgba16ui", PIXELFORMAT_RGBA16_UINT }, - { "rgba32f", PIXELFORMAT_RGBA32_FLOAT }, - { "rgba32i", PIXELFORMAT_RGBA32_INT }, - { "rgba32ui", PIXELFORMAT_RGBA32_UINT }, + { "rgba8", PIXELFORMAT_RGBA8_UNORM }, + { "srgba8", PIXELFORMAT_RGBA8_sRGB }, + { "bgra8", PIXELFORMAT_BGRA8_UNORM }, + { "bgra8srgb", PIXELFORMAT_BGRA8_sRGB }, + { "rgba8i", PIXELFORMAT_RGBA8_INT }, + { "rgba8ui", PIXELFORMAT_RGBA8_UINT }, + { "rgba16", PIXELFORMAT_RGBA16_UNORM }, + { "rgba16f", PIXELFORMAT_RGBA16_FLOAT }, + { "rgba16i", PIXELFORMAT_RGBA16_INT }, + { "rgba16ui", PIXELFORMAT_RGBA16_UINT }, + { "rgba32f", PIXELFORMAT_RGBA32_FLOAT }, + { "rgba32i", PIXELFORMAT_RGBA32_INT }, + { "rgba32ui", PIXELFORMAT_RGBA32_UINT }, { "rgba4", PIXELFORMAT_RGBA4_UNORM }, { "rgb5a1", PIXELFORMAT_RGB5A1_UNORM }, @@ -182,43 +207,70 @@ static StringMap::Entry formatEntries[] = { "depth24stencil8", PIXELFORMAT_DEPTH24_UNORM_STENCIL8 }, { "depth32fstencil8", PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 }, - { "DXT1", PIXELFORMAT_DXT1_UNORM }, - { "DXT3", PIXELFORMAT_DXT3_UNORM }, - { "DXT5", PIXELFORMAT_DXT5_UNORM }, - { "BC4", PIXELFORMAT_BC4_UNORM }, - { "BC4s", PIXELFORMAT_BC4_SNORM }, - { "BC5", PIXELFORMAT_BC5_UNORM }, - { "BC5s", PIXELFORMAT_BC5_SNORM }, - { "BC6h", PIXELFORMAT_BC6H_UFLOAT }, - { "BC6hs", PIXELFORMAT_BC6H_FLOAT }, - { "BC7", PIXELFORMAT_BC7_UNORM }, - { "PVR1rgb2", PIXELFORMAT_PVR1_RGB2_UNORM }, - { "PVR1rgb4", PIXELFORMAT_PVR1_RGB4_UNORM }, - { "PVR1rgba2", PIXELFORMAT_PVR1_RGBA2_UNORM }, - { "PVR1rgba4", PIXELFORMAT_PVR1_RGBA4_UNORM }, - { "ETC1", PIXELFORMAT_ETC1_UNORM }, - { "ETC2rgb", PIXELFORMAT_ETC2_RGB_UNORM }, - { "ETC2rgba", PIXELFORMAT_ETC2_RGBA_UNORM }, - { "ETC2rgba1", PIXELFORMAT_ETC2_RGBA1_UNORM }, - { "EACr", PIXELFORMAT_EAC_R_UNORM }, - { "EACrs", PIXELFORMAT_EAC_R_SNORM }, - { "EACrg", PIXELFORMAT_EAC_RG_UNORM }, - { "EACrgs", PIXELFORMAT_EAC_RG_SNORM }, + { "DXT1", PIXELFORMAT_DXT1_UNORM }, + { "DXT1srgb", PIXELFORMAT_DXT1_sRGB }, + { "DXT3", PIXELFORMAT_DXT3_UNORM }, + { "DXT3srgb", PIXELFORMAT_DXT3_sRGB }, + { "DXT5", PIXELFORMAT_DXT5_UNORM }, + { "DXT5srgb", PIXELFORMAT_DXT5_sRGB }, + { "BC4", PIXELFORMAT_BC4_UNORM }, + { "BC4s", PIXELFORMAT_BC4_SNORM }, + { "BC5", PIXELFORMAT_BC5_UNORM }, + { "BC5s", PIXELFORMAT_BC5_SNORM }, + { "BC6h", PIXELFORMAT_BC6H_UFLOAT }, + { "BC6hs", PIXELFORMAT_BC6H_FLOAT }, + { "BC7", PIXELFORMAT_BC7_UNORM }, + { "BC7srgb", PIXELFORMAT_BC7_sRGB }, - { "ASTC4x4", PIXELFORMAT_ASTC_4x4 }, - { "ASTC5x4", PIXELFORMAT_ASTC_5x4 }, - { "ASTC5x5", PIXELFORMAT_ASTC_5x5 }, - { "ASTC6x5", PIXELFORMAT_ASTC_6x5 }, - { "ASTC6x6", PIXELFORMAT_ASTC_6x6 }, - { "ASTC8x5", PIXELFORMAT_ASTC_8x5 }, - { "ASTC8x6", PIXELFORMAT_ASTC_8x6 }, - { "ASTC8x8", PIXELFORMAT_ASTC_8x8 }, - { "ASTC10x5", PIXELFORMAT_ASTC_10x5 }, - { "ASTC10x6", PIXELFORMAT_ASTC_10x6 }, - { "ASTC10x8", PIXELFORMAT_ASTC_10x8 }, - { "ASTC10x10", PIXELFORMAT_ASTC_10x10 }, - { "ASTC12x10", PIXELFORMAT_ASTC_12x10 }, - { "ASTC12x12", PIXELFORMAT_ASTC_12x12 }, + { "PVR1rgb2", PIXELFORMAT_PVR1_RGB2_UNORM }, + { "PVR1rgb2srgb", PIXELFORMAT_PVR1_RGB2_sRGB }, + { "PVR1rgb4", PIXELFORMAT_PVR1_RGB4_UNORM }, + { "PVR1rgb4srgb", PIXELFORMAT_PVR1_RGB4_sRGB }, + { "PVR1rgba2", PIXELFORMAT_PVR1_RGBA2_UNORM }, + { "PVR1rgba2srgb", PIXELFORMAT_PVR1_RGBA2_sRGB }, + { "PVR1rgba4", PIXELFORMAT_PVR1_RGBA4_UNORM }, + { "PVR1rgba4srgb", PIXELFORMAT_PVR1_RGBA4_sRGB }, + + { "ETC1", PIXELFORMAT_ETC1_UNORM }, + { "ETC2rgb", PIXELFORMAT_ETC2_RGB_UNORM }, + { "ETC2srgb", PIXELFORMAT_ETC2_RGB_sRGB }, + { "ETC2rgba", PIXELFORMAT_ETC2_RGBA_UNORM }, + { "ETC2srgba", PIXELFORMAT_ETC2_RGBA_sRGB }, + { "ETC2rgba1", PIXELFORMAT_ETC2_RGBA1_UNORM }, + { "ETC2srgba1", PIXELFORMAT_ETC2_RGBA1_sRGB }, + { "EACr", PIXELFORMAT_EAC_R_UNORM }, + { "EACrs", PIXELFORMAT_EAC_R_SNORM }, + { "EACrg", PIXELFORMAT_EAC_RG_UNORM }, + { "EACrgs", PIXELFORMAT_EAC_RG_SNORM }, + + { "ASTC4x4", PIXELFORMAT_ASTC_4x4_UNORM }, + { "ASTC5x4", PIXELFORMAT_ASTC_5x4_UNORM }, + { "ASTC5x5", PIXELFORMAT_ASTC_5x5_UNORM }, + { "ASTC6x5", PIXELFORMAT_ASTC_6x5_UNORM }, + { "ASTC6x6", PIXELFORMAT_ASTC_6x6_UNORM }, + { "ASTC8x5", PIXELFORMAT_ASTC_8x5_UNORM }, + { "ASTC8x6", PIXELFORMAT_ASTC_8x6_UNORM }, + { "ASTC8x8", PIXELFORMAT_ASTC_8x8_UNORM }, + { "ASTC10x5", PIXELFORMAT_ASTC_10x5_UNORM }, + { "ASTC10x6", PIXELFORMAT_ASTC_10x6_UNORM }, + { "ASTC10x8", PIXELFORMAT_ASTC_10x8_UNORM }, + { "ASTC10x10", PIXELFORMAT_ASTC_10x10_UNORM }, + { "ASTC12x10", PIXELFORMAT_ASTC_12x10_UNORM }, + { "ASTC12x12", PIXELFORMAT_ASTC_12x12_UNORM }, + { "ASTC4x4srgb", PIXELFORMAT_ASTC_4x4_sRGB }, + { "ASTC5x4srgb", PIXELFORMAT_ASTC_5x4_sRGB }, + { "ASTC5x5srgb", PIXELFORMAT_ASTC_5x5_sRGB }, + { "ASTC6x5srgb", PIXELFORMAT_ASTC_6x5_sRGB }, + { "ASTC6x6srgb", PIXELFORMAT_ASTC_6x6_sRGB }, + { "ASTC8x5srgb", PIXELFORMAT_ASTC_8x5_sRGB }, + { "ASTC8x6srgb", PIXELFORMAT_ASTC_8x6_sRGB }, + { "ASTC8x8srgb", PIXELFORMAT_ASTC_8x8_sRGB }, + { "ASTC10x5srgb", PIXELFORMAT_ASTC_10x5_sRGB }, + { "ASTC10x6srgb", PIXELFORMAT_ASTC_10x6_sRGB }, + { "ASTC10x8srgb", PIXELFORMAT_ASTC_10x8_sRGB }, + { "ASTC10x10srgb", PIXELFORMAT_ASTC_10x10_sRGB }, + { "ASTC12x10srgb", PIXELFORMAT_ASTC_12x10_sRGB }, + { "ASTC12x12srgb", PIXELFORMAT_ASTC_12x12_sRGB }, }; static_assert(sizeof(formatEntries) / sizeof(formatEntries[0]) == (size_t) PIXELFORMAT_MAX_ENUM, "pixel format string map is missing entries!"); @@ -275,7 +327,7 @@ bool isPixelFormatStencil(PixelFormat format) bool isPixelFormatSRGB(PixelFormat format) { - return format == PIXELFORMAT_RGBA8_UNORM_sRGB || format == PIXELFORMAT_BGRA8_UNORM_sRGB; + return formatInfo[format].sRGB; } bool isPixelFormatInteger(PixelFormat format) @@ -286,19 +338,70 @@ bool isPixelFormatInteger(PixelFormat format) PixelFormat getSRGBPixelFormat(PixelFormat format) { - if (format == PIXELFORMAT_RGBA8_UNORM) - return PIXELFORMAT_RGBA8_UNORM_sRGB; - else if (format == PIXELFORMAT_BGRA8_UNORM) - return PIXELFORMAT_BGRA8_UNORM_sRGB; + switch (format) + { + case PIXELFORMAT_RGBA8_UNORM: return PIXELFORMAT_RGBA8_sRGB; + case PIXELFORMAT_BGRA8_UNORM: return PIXELFORMAT_BGRA8_sRGB; + case PIXELFORMAT_PVR1_RGB2_UNORM: return PIXELFORMAT_PVR1_RGB2_sRGB; + case PIXELFORMAT_PVR1_RGB4_UNORM: return PIXELFORMAT_PVR1_RGB4_sRGB; + case PIXELFORMAT_PVR1_RGBA2_UNORM: return PIXELFORMAT_PVR1_RGBA2_sRGB; + case PIXELFORMAT_PVR1_RGBA4_UNORM: return PIXELFORMAT_PVR1_RGBA4_sRGB; + case PIXELFORMAT_ETC1_UNORM: return PIXELFORMAT_ETC2_RGB_sRGB; // ETC2 can load ETC1 data. + case PIXELFORMAT_ETC2_RGB_UNORM: return PIXELFORMAT_ETC2_RGB_sRGB; + case PIXELFORMAT_ETC2_RGBA_UNORM: return PIXELFORMAT_ETC2_RGBA_sRGB; + case PIXELFORMAT_ETC2_RGBA1_UNORM: return PIXELFORMAT_ETC2_RGBA1_sRGB; + case PIXELFORMAT_ASTC_4x4_UNORM: return PIXELFORMAT_ASTC_4x4_sRGB; + case PIXELFORMAT_ASTC_5x4_UNORM: return PIXELFORMAT_ASTC_5x4_sRGB; + case PIXELFORMAT_ASTC_5x5_UNORM: return PIXELFORMAT_ASTC_5x5_sRGB; + case PIXELFORMAT_ASTC_6x5_UNORM: return PIXELFORMAT_ASTC_6x5_sRGB; + case PIXELFORMAT_ASTC_6x6_UNORM: return PIXELFORMAT_ASTC_6x6_sRGB; + case PIXELFORMAT_ASTC_8x5_UNORM: return PIXELFORMAT_ASTC_8x5_sRGB; + case PIXELFORMAT_ASTC_8x6_UNORM: return PIXELFORMAT_ASTC_8x6_sRGB; + case PIXELFORMAT_ASTC_8x8_UNORM: return PIXELFORMAT_ASTC_8x8_sRGB; + case PIXELFORMAT_ASTC_10x5_UNORM: return PIXELFORMAT_ASTC_10x5_sRGB; + case PIXELFORMAT_ASTC_10x6_UNORM: return PIXELFORMAT_ASTC_10x6_sRGB; + case PIXELFORMAT_ASTC_10x8_UNORM: return PIXELFORMAT_ASTC_10x8_sRGB; + case PIXELFORMAT_ASTC_10x10_UNORM: return PIXELFORMAT_ASTC_10x10_sRGB; + case PIXELFORMAT_ASTC_12x10_UNORM: return PIXELFORMAT_ASTC_12x10_sRGB; + case PIXELFORMAT_ASTC_12x12_UNORM: return PIXELFORMAT_ASTC_12x12_sRGB; + default: + break; + } + return format; } PixelFormat getLinearPixelFormat(PixelFormat format) { - if (format == PIXELFORMAT_RGBA8_UNORM_sRGB) - return PIXELFORMAT_RGBA8_UNORM; - else if (format == PIXELFORMAT_BGRA8_UNORM_sRGB) - return PIXELFORMAT_BGRA8_UNORM; + switch (format) + { + case PIXELFORMAT_RGBA8_sRGB: return PIXELFORMAT_RGBA8_UNORM; + case PIXELFORMAT_BGRA8_sRGB: return PIXELFORMAT_BGRA8_UNORM; + case PIXELFORMAT_PVR1_RGB2_sRGB: return PIXELFORMAT_PVR1_RGB2_UNORM; + case PIXELFORMAT_PVR1_RGB4_sRGB: return PIXELFORMAT_PVR1_RGB4_UNORM; + case PIXELFORMAT_PVR1_RGBA2_sRGB: return PIXELFORMAT_PVR1_RGBA2_UNORM; + case PIXELFORMAT_PVR1_RGBA4_sRGB: return PIXELFORMAT_PVR1_RGBA4_UNORM; + case PIXELFORMAT_ETC2_RGB_sRGB: return PIXELFORMAT_ETC2_RGB_UNORM; + case PIXELFORMAT_ETC2_RGBA_sRGB: return PIXELFORMAT_ETC2_RGBA_UNORM; + case PIXELFORMAT_ETC2_RGBA1_sRGB: return PIXELFORMAT_ETC2_RGBA1_UNORM; + case PIXELFORMAT_ASTC_4x4_sRGB: return PIXELFORMAT_ASTC_4x4_UNORM; + case PIXELFORMAT_ASTC_5x4_sRGB: return PIXELFORMAT_ASTC_5x4_UNORM; + case PIXELFORMAT_ASTC_5x5_sRGB: return PIXELFORMAT_ASTC_5x5_UNORM; + case PIXELFORMAT_ASTC_6x5_sRGB: return PIXELFORMAT_ASTC_6x5_UNORM; + case PIXELFORMAT_ASTC_6x6_sRGB: return PIXELFORMAT_ASTC_6x6_UNORM; + case PIXELFORMAT_ASTC_8x5_sRGB: return PIXELFORMAT_ASTC_8x5_UNORM; + case PIXELFORMAT_ASTC_8x6_sRGB: return PIXELFORMAT_ASTC_8x6_UNORM; + case PIXELFORMAT_ASTC_8x8_sRGB: return PIXELFORMAT_ASTC_8x8_UNORM; + case PIXELFORMAT_ASTC_10x5_sRGB: return PIXELFORMAT_ASTC_10x5_UNORM; + case PIXELFORMAT_ASTC_10x6_sRGB: return PIXELFORMAT_ASTC_10x6_UNORM; + case PIXELFORMAT_ASTC_10x8_sRGB: return PIXELFORMAT_ASTC_10x8_UNORM; + case PIXELFORMAT_ASTC_10x10_sRGB: return PIXELFORMAT_ASTC_10x10_UNORM; + case PIXELFORMAT_ASTC_12x10_sRGB: return PIXELFORMAT_ASTC_12x10_UNORM; + case PIXELFORMAT_ASTC_12x12_sRGB: return PIXELFORMAT_ASTC_12x12_UNORM; + default: + break; + } + return format; } diff --git a/src/common/pixelformat.h b/src/common/pixelformat.h index a2f52a4db..b928f92d7 100644 --- a/src/common/pixelformat.h +++ b/src/common/pixelformat.h @@ -60,9 +60,9 @@ enum PixelFormat // 4-channel normal formats PIXELFORMAT_RGBA8_UNORM, - PIXELFORMAT_RGBA8_UNORM_sRGB, + PIXELFORMAT_RGBA8_sRGB, PIXELFORMAT_BGRA8_UNORM, - PIXELFORMAT_BGRA8_UNORM_sRGB, + PIXELFORMAT_BGRA8_sRGB, PIXELFORMAT_RGBA8_INT, PIXELFORMAT_RGBA8_UINT, PIXELFORMAT_RGBA16_UNORM, @@ -90,8 +90,11 @@ enum PixelFormat // compressed formats PIXELFORMAT_DXT1_UNORM, + PIXELFORMAT_DXT1_sRGB, PIXELFORMAT_DXT3_UNORM, + PIXELFORMAT_DXT3_sRGB, PIXELFORMAT_DXT5_UNORM, + PIXELFORMAT_DXT5_sRGB, PIXELFORMAT_BC4_UNORM, PIXELFORMAT_BC4_SNORM, PIXELFORMAT_BC5_UNORM, @@ -99,32 +102,57 @@ enum PixelFormat PIXELFORMAT_BC6H_UFLOAT, PIXELFORMAT_BC6H_FLOAT, PIXELFORMAT_BC7_UNORM, + PIXELFORMAT_BC7_sRGB, + PIXELFORMAT_PVR1_RGB2_UNORM, + PIXELFORMAT_PVR1_RGB2_sRGB, PIXELFORMAT_PVR1_RGB4_UNORM, + PIXELFORMAT_PVR1_RGB4_sRGB, PIXELFORMAT_PVR1_RGBA2_UNORM, + PIXELFORMAT_PVR1_RGBA2_sRGB, PIXELFORMAT_PVR1_RGBA4_UNORM, + PIXELFORMAT_PVR1_RGBA4_sRGB, + PIXELFORMAT_ETC1_UNORM, PIXELFORMAT_ETC2_RGB_UNORM, + PIXELFORMAT_ETC2_RGB_sRGB, PIXELFORMAT_ETC2_RGBA_UNORM, + PIXELFORMAT_ETC2_RGBA_sRGB, PIXELFORMAT_ETC2_RGBA1_UNORM, + PIXELFORMAT_ETC2_RGBA1_sRGB, PIXELFORMAT_EAC_R_UNORM, PIXELFORMAT_EAC_R_SNORM, PIXELFORMAT_EAC_RG_UNORM, PIXELFORMAT_EAC_RG_SNORM, - PIXELFORMAT_ASTC_4x4, - PIXELFORMAT_ASTC_5x4, - PIXELFORMAT_ASTC_5x5, - PIXELFORMAT_ASTC_6x5, - PIXELFORMAT_ASTC_6x6, - PIXELFORMAT_ASTC_8x5, - PIXELFORMAT_ASTC_8x6, - PIXELFORMAT_ASTC_8x8, - PIXELFORMAT_ASTC_10x5, - PIXELFORMAT_ASTC_10x6, - PIXELFORMAT_ASTC_10x8, - PIXELFORMAT_ASTC_10x10, - PIXELFORMAT_ASTC_12x10, - PIXELFORMAT_ASTC_12x12, + + PIXELFORMAT_ASTC_4x4_UNORM, + PIXELFORMAT_ASTC_5x4_UNORM, + PIXELFORMAT_ASTC_5x5_UNORM, + PIXELFORMAT_ASTC_6x5_UNORM, + PIXELFORMAT_ASTC_6x6_UNORM, + PIXELFORMAT_ASTC_8x5_UNORM, + PIXELFORMAT_ASTC_8x6_UNORM, + PIXELFORMAT_ASTC_8x8_UNORM, + PIXELFORMAT_ASTC_10x5_UNORM, + PIXELFORMAT_ASTC_10x6_UNORM, + PIXELFORMAT_ASTC_10x8_UNORM, + PIXELFORMAT_ASTC_10x10_UNORM, + PIXELFORMAT_ASTC_12x10_UNORM, + PIXELFORMAT_ASTC_12x12_UNORM, + PIXELFORMAT_ASTC_4x4_sRGB, + PIXELFORMAT_ASTC_5x4_sRGB, + PIXELFORMAT_ASTC_5x5_sRGB, + PIXELFORMAT_ASTC_6x5_sRGB, + PIXELFORMAT_ASTC_6x6_sRGB, + PIXELFORMAT_ASTC_8x5_sRGB, + PIXELFORMAT_ASTC_8x6_sRGB, + PIXELFORMAT_ASTC_8x8_sRGB, + PIXELFORMAT_ASTC_10x5_sRGB, + PIXELFORMAT_ASTC_10x6_sRGB, + PIXELFORMAT_ASTC_10x8_sRGB, + PIXELFORMAT_ASTC_10x10_sRGB, + PIXELFORMAT_ASTC_12x10_sRGB, + PIXELFORMAT_ASTC_12x12_sRGB, PIXELFORMAT_MAX_ENUM }; @@ -149,6 +177,7 @@ struct PixelFormatInfo bool depth; bool stencil; bool compressed; + bool sRGB; PixelFormatType dataType; }; diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index be2b979e0..3d32b727b 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -925,7 +925,7 @@ void Graphics::setRenderTargets(const RenderTargets &rts) PixelFormat dsformat = PIXELFORMAT_STENCIL8; if (wantsdepth && wantsstencil) dsformat = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; - else if (wantsdepth && isPixelFormatSupported(PIXELFORMAT_DEPTH24_UNORM, PIXELFORMATUSAGEFLAGS_RENDERTARGET, false)) + else if (wantsdepth && isPixelFormatSupported(PIXELFORMAT_DEPTH24_UNORM, PIXELFORMATUSAGEFLAGS_RENDERTARGET)) dsformat = PIXELFORMAT_DEPTH24_UNORM; else if (wantsdepth) dsformat = PIXELFORMAT_DEPTH16_UNORM; @@ -2395,7 +2395,7 @@ PixelFormat Graphics::getSizedFormat(PixelFormat format) const { case PIXELFORMAT_NORMAL: if (isGammaCorrect()) - return PIXELFORMAT_RGBA8_UNORM_sRGB; + return PIXELFORMAT_RGBA8_sRGB; else return PIXELFORMAT_RGBA8_UNORM; case PIXELFORMAT_HDR: diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index f9a51eab3..d2989213d 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -824,7 +824,7 @@ public: /** * Gets whether the specified pixel format usage is supported. **/ - virtual bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) = 0; + virtual bool isPixelFormatSupported(PixelFormat format, uint32 usage) = 0; /** * Gets the renderer used by love.graphics. diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 5cda31dae..4d0e59fcf 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -168,7 +168,6 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) , computeWrite(settings.computeWrite) , readable(true) , mipmapsMode(settings.mipmaps) - , sRGB(false) , width(settings.width) , height(settings.height) , depth(settings.type == TEXTURE_VOLUME ? settings.layers : 1) @@ -236,7 +235,8 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) readable = !renderTarget || !isPixelFormatDepthStencil(format); format = gfx->getSizedFormat(format); - sRGB = isPixelFormatSRGB(format) || (isCompressed() && isGammaCorrect() && !settings.linear); + if (!isGammaCorrect() || settings.linear) + format = getLinearPixelFormat(format); if (mipmapsMode == MIPMAPS_AUTO && isCompressed()) mipmapsMode = MIPMAPS_MANUAL; @@ -291,7 +291,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) if (computeWrite) usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE; - if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, sRGB)) + if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage)) { const char *fstr = "unknown"; love::getConstant(format, fstr); @@ -622,7 +622,7 @@ bool Texture::isCompressed() const bool Texture::isFormatLinear() const { - return isGammaCorrect() && !sRGB && !isPixelFormatSRGB(format); + return isGammaCorrect() && !isPixelFormatSRGB(format); } bool Texture::isValidSlice(int slice, int mip) const diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index 2132bf741..56fda383e 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -325,8 +325,6 @@ protected: MipmapsMode mipmapsMode; - bool sRGB; - int width; int height; diff --git a/src/modules/graphics/metal/Graphics.h b/src/modules/graphics/metal/Graphics.h index ea8894f4c..610f7d5de 100644 --- a/src/modules/graphics/metal/Graphics.h +++ b/src/modules/graphics/metal/Graphics.h @@ -110,7 +110,7 @@ public: void setWireframe(bool enable) override; - bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override; + bool isPixelFormatSupported(PixelFormat format, uint32 usage) override; Renderer getRenderer() const override; bool usesGLSLES() const override; RendererInfo getRendererInfo() const override; diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index ca6c76b82..0feab35dd 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -503,7 +503,7 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh backbufferMSAA.set(nullptr); if (settings.msaa > 1) { - settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM; + settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM; backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN); } @@ -681,7 +681,7 @@ id Graphics::useRenderEncoder() attachmentStoreActions.stencil = MTLStoreActionDontCare; auto &key = lastRenderPipelineKey; - key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM; + key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM; key.depthStencilFormat = backbufferDepthStencil->getPixelFormat(); key.msaa = backbufferMSAA ? (uint8) backbufferMSAA->getMSAA() : 1; } @@ -1864,13 +1864,10 @@ void Graphics::setWireframe(bool enable) } } -bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) +bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage) { format = getSizedFormat(format); - if (sRGB) - format = getSRGBPixelFormat(format); - const uint32 sample = PIXELFORMATUSAGEFLAGS_SAMPLE; const uint32 filter = PIXELFORMATUSAGEFLAGS_LINEAR; const uint32 rt = PIXELFORMATUSAGEFLAGS_RENDERTARGET; @@ -1958,8 +1955,8 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG case PIXELFORMAT_BGRA8_UNORM: flags |= all; break; - case PIXELFORMAT_RGBA8_UNORM_sRGB: - case PIXELFORMAT_BGRA8_UNORM_sRGB: + case PIXELFORMAT_RGBA8_sRGB: + case PIXELFORMAT_BGRA8_sRGB: if (families.apple[1] || families.mac[1] || families.macCatalyst[1]) flags |= commonsample | commonrender; if (families.apple[2]) @@ -2058,8 +2055,11 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG break; case PIXELFORMAT_DXT1_UNORM: + case PIXELFORMAT_DXT1_sRGB: case PIXELFORMAT_DXT3_UNORM: + case PIXELFORMAT_DXT3_sRGB: case PIXELFORMAT_DXT5_UNORM: + case PIXELFORMAT_DXT5_sRGB: case PIXELFORMAT_BC4_UNORM: case PIXELFORMAT_BC4_SNORM: case PIXELFORMAT_BC5_UNORM: @@ -2067,22 +2067,30 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG case PIXELFORMAT_BC6H_UFLOAT: case PIXELFORMAT_BC6H_FLOAT: case PIXELFORMAT_BC7_UNORM: + case PIXELFORMAT_BC7_sRGB: if (families.mac[1] || families.macCatalyst[1]) flags |= commonsample; break; case PIXELFORMAT_PVR1_RGB2_UNORM: + case PIXELFORMAT_PVR1_RGB2_sRGB: case PIXELFORMAT_PVR1_RGB4_UNORM: + case PIXELFORMAT_PVR1_RGB4_sRGB: case PIXELFORMAT_PVR1_RGBA2_UNORM: + case PIXELFORMAT_PVR1_RGBA2_sRGB: case PIXELFORMAT_PVR1_RGBA4_UNORM: + case PIXELFORMAT_PVR1_RGBA4_sRGB: if (families.apple[1]) flags |= commonsample; break; case PIXELFORMAT_ETC1_UNORM: case PIXELFORMAT_ETC2_RGB_UNORM: + case PIXELFORMAT_ETC2_RGB_sRGB: case PIXELFORMAT_ETC2_RGBA_UNORM: + case PIXELFORMAT_ETC2_RGBA_sRGB: case PIXELFORMAT_ETC2_RGBA1_UNORM: + case PIXELFORMAT_ETC2_RGBA1_sRGB: case PIXELFORMAT_EAC_R_UNORM: case PIXELFORMAT_EAC_R_SNORM: case PIXELFORMAT_EAC_RG_UNORM: @@ -2091,20 +2099,34 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG flags |= commonsample; break; - case PIXELFORMAT_ASTC_4x4: - case PIXELFORMAT_ASTC_5x4: - case PIXELFORMAT_ASTC_5x5: - case PIXELFORMAT_ASTC_6x5: - case PIXELFORMAT_ASTC_6x6: - case PIXELFORMAT_ASTC_8x5: - case PIXELFORMAT_ASTC_8x6: - case PIXELFORMAT_ASTC_8x8: - case PIXELFORMAT_ASTC_10x5: - case PIXELFORMAT_ASTC_10x6: - case PIXELFORMAT_ASTC_10x8: - case PIXELFORMAT_ASTC_10x10: - case PIXELFORMAT_ASTC_12x10: - case PIXELFORMAT_ASTC_12x12: + case PIXELFORMAT_ASTC_4x4_UNORM: + case PIXELFORMAT_ASTC_5x4_UNORM: + case PIXELFORMAT_ASTC_5x5_UNORM: + case PIXELFORMAT_ASTC_6x5_UNORM: + case PIXELFORMAT_ASTC_6x6_UNORM: + case PIXELFORMAT_ASTC_8x5_UNORM: + case PIXELFORMAT_ASTC_8x6_UNORM: + case PIXELFORMAT_ASTC_8x8_UNORM: + case PIXELFORMAT_ASTC_10x5_UNORM: + case PIXELFORMAT_ASTC_10x6_UNORM: + case PIXELFORMAT_ASTC_10x8_UNORM: + case PIXELFORMAT_ASTC_10x10_UNORM: + case PIXELFORMAT_ASTC_12x10_UNORM: + case PIXELFORMAT_ASTC_12x12_UNORM: + case PIXELFORMAT_ASTC_4x4_sRGB: + case PIXELFORMAT_ASTC_5x4_sRGB: + case PIXELFORMAT_ASTC_5x5_sRGB: + case PIXELFORMAT_ASTC_6x5_sRGB: + case PIXELFORMAT_ASTC_6x6_sRGB: + case PIXELFORMAT_ASTC_8x5_sRGB: + case PIXELFORMAT_ASTC_8x6_sRGB: + case PIXELFORMAT_ASTC_8x8_sRGB: + case PIXELFORMAT_ASTC_10x5_sRGB: + case PIXELFORMAT_ASTC_10x6_sRGB: + case PIXELFORMAT_ASTC_10x8_sRGB: + case PIXELFORMAT_ASTC_10x10_sRGB: + case PIXELFORMAT_ASTC_12x10_sRGB: + case PIXELFORMAT_ASTC_12x12_sRGB: if (families.apple[2]) flags |= commonsample; break; diff --git a/src/modules/graphics/metal/Metal.h b/src/modules/graphics/metal/Metal.h index e38b8f529..2283d9d87 100644 --- a/src/modules/graphics/metal/Metal.h +++ b/src/modules/graphics/metal/Metal.h @@ -43,7 +43,7 @@ public: API_AVAILABLE(macos(10.15), ios(13.0)) MTLTextureSwizzleChannels swizzle; }; - static PixelFormatDesc convertPixelFormat(id device, PixelFormat format, bool &isSRGB); + static PixelFormatDesc convertPixelFormat(id device, PixelFormat format); }; // Metal diff --git a/src/modules/graphics/metal/Metal.mm b/src/modules/graphics/metal/Metal.mm index d547c3028..589329b4f 100644 --- a/src/modules/graphics/metal/Metal.mm +++ b/src/modules/graphics/metal/Metal.mm @@ -28,17 +28,11 @@ namespace graphics namespace metal { -Metal::PixelFormatDesc Metal::convertPixelFormat(id device, PixelFormat format, bool &isSRGB) +Metal::PixelFormatDesc Metal::convertPixelFormat(id device, PixelFormat format) { MTLPixelFormat mtlformat = MTLPixelFormatInvalid; PixelFormatDesc desc = {}; - if (isSRGB) - format = getSRGBPixelFormat(format); - - if (!isPixelFormatCompressed(format) && !isPixelFormatSRGB(format)) - isSRGB = false; - switch (format) { case PIXELFORMAT_R8_UNORM: @@ -50,13 +44,13 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id device, PixelForm case PIXELFORMAT_RGBA8_UNORM: mtlformat = MTLPixelFormatRGBA8Unorm; break; - case PIXELFORMAT_RGBA8_UNORM_sRGB: + case PIXELFORMAT_RGBA8_sRGB: mtlformat = MTLPixelFormatRGBA8Unorm_sRGB; break; case PIXELFORMAT_BGRA8_UNORM: mtlformat = MTLPixelFormatBGRA8Unorm; break; - case PIXELFORMAT_BGRA8_UNORM_sRGB: + case PIXELFORMAT_BGRA8_sRGB: mtlformat = MTLPixelFormatBGRA8Unorm_sRGB; break; case PIXELFORMAT_R16_UNORM: @@ -205,177 +199,264 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id device, PixelForm case PIXELFORMAT_DXT1_UNORM: #ifndef LOVE_IOS - mtlformat = isSRGB ? MTLPixelFormatBC1_RGBA_sRGB : MTLPixelFormatBC1_RGBA; + mtlformat = MTLPixelFormatBC1_RGBA; +#endif + break; + case PIXELFORMAT_DXT1_sRGB: +#ifndef LOVE_IOS + mtlformat = MTLPixelFormatBC1_RGBA_sRGB; #endif break; case PIXELFORMAT_DXT3_UNORM: #ifndef LOVE_IOS - mtlformat = isSRGB ? MTLPixelFormatBC2_RGBA_sRGB : MTLPixelFormatBC2_RGBA; + mtlformat = MTLPixelFormatBC2_RGBA; +#endif + break; + case PIXELFORMAT_DXT3_sRGB: +#ifndef LOVE_IOS + mtlformat = MTLPixelFormatBC2_RGBA_sRGB; #endif break; case PIXELFORMAT_DXT5_UNORM: #ifndef LOVE_IOS - mtlformat = isSRGB ? MTLPixelFormatBC3_RGBA_sRGB : MTLPixelFormatBC3_RGBA; + mtlformat = MTLPixelFormatBC3_RGBA; +#endif + break; + case PIXELFORMAT_DXT5_sRGB: +#ifndef LOVE_IOS + mtlformat = MTLPixelFormatBC3_RGBA_sRGB; #endif break; case PIXELFORMAT_BC4_UNORM: #ifndef LOVE_IOS - isSRGB = false; mtlformat = MTLPixelFormatBC4_RUnorm; #endif break; case PIXELFORMAT_BC4_SNORM: #ifndef LOVE_IOS - isSRGB = false; mtlformat = MTLPixelFormatBC4_RSnorm; #endif break; case PIXELFORMAT_BC5_UNORM: #ifndef LOVE_IOS - isSRGB = false; mtlformat = MTLPixelFormatBC5_RGUnorm; #endif break; case PIXELFORMAT_BC5_SNORM: #ifndef LOVE_IOS - isSRGB = false; mtlformat = MTLPixelFormatBC5_RGSnorm; #endif break; case PIXELFORMAT_BC6H_UFLOAT: #ifndef LOVE_IOS - isSRGB = false; mtlformat = MTLPixelFormatBC6H_RGBUfloat; #endif break; case PIXELFORMAT_BC6H_FLOAT: #ifndef LOVE_IOS - isSRGB = false; mtlformat = MTLPixelFormatBC6H_RGBFloat; #endif break; case PIXELFORMAT_BC7_UNORM: #ifndef LOVE_IOS - mtlformat = isSRGB ? MTLPixelFormatBC7_RGBAUnorm_sRGB : MTLPixelFormatBC7_RGBAUnorm; + mtlformat = MTLPixelFormatBC7_RGBAUnorm; +#endif + break; + case PIXELFORMAT_BC7_sRGB: +#ifndef LOVE_IOS + mtlformat = MTLPixelFormatBC7_RGBAUnorm_sRGB; #endif break; case PIXELFORMAT_PVR1_RGB2_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_2BPP_sRGB : MTLPixelFormatPVRTC_RGB_2BPP; + mtlformat = MTLPixelFormatPVRTC_RGB_2BPP; + break; + case PIXELFORMAT_PVR1_RGB2_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatPVRTC_RGB_2BPP_sRGB; break; case PIXELFORMAT_PVR1_RGB4_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_4BPP_sRGB : MTLPixelFormatPVRTC_RGB_4BPP; + mtlformat = MTLPixelFormatPVRTC_RGB_4BPP; + break; + case PIXELFORMAT_PVR1_RGB4_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatPVRTC_RGB_4BPP_sRGB; break; case PIXELFORMAT_PVR1_RGBA2_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_2BPP_sRGB : MTLPixelFormatPVRTC_RGBA_2BPP; + mtlformat = MTLPixelFormatPVRTC_RGBA_2BPP; + break; + case PIXELFORMAT_PVR1_RGBA2_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatPVRTC_RGB_2BPP_sRGB; break; case PIXELFORMAT_PVR1_RGBA4_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_4BPP_sRGB : MTLPixelFormatPVRTC_RGBA_4BPP; + mtlformat = MTLPixelFormatPVRTC_RGBA_4BPP; break; + case PIXELFORMAT_PVR1_RGBA4_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatPVRTC_RGB_4BPP_sRGB; + break; + case PIXELFORMAT_ETC1_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8; + mtlformat = MTLPixelFormatETC2_RGB8; break; case PIXELFORMAT_ETC2_RGB_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8; + mtlformat = MTLPixelFormatETC2_RGB8; + break; + case PIXELFORMAT_ETC2_RGB_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatETC2_RGB8_sRGB; break; case PIXELFORMAT_ETC2_RGBA_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8; + mtlformat = MTLPixelFormatEAC_RGBA8; + break; + case PIXELFORMAT_ETC2_RGBA_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatEAC_RGBA8_sRGB; break; case PIXELFORMAT_ETC2_RGBA1_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1; + mtlformat = MTLPixelFormatETC2_RGB8A1; + break; + case PIXELFORMAT_ETC2_RGBA1_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatETC2_RGB8A1_sRGB; break; case PIXELFORMAT_EAC_R_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - { - isSRGB = false; mtlformat = MTLPixelFormatEAC_R11Unorm; - } break; case PIXELFORMAT_EAC_R_SNORM: if (@available(macOS 11.0, iOS 8.0, *)) - { - isSRGB = false; mtlformat = MTLPixelFormatEAC_R11Snorm; - } break; case PIXELFORMAT_EAC_RG_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - { - isSRGB = false; mtlformat = MTLPixelFormatEAC_RG11Unorm; - } break; case PIXELFORMAT_EAC_RG_SNORM: if (@available(macOS 11.0, iOS 8.0, *)) - { - isSRGB = false; mtlformat = MTLPixelFormatEAC_RG11Snorm; - } break; - case PIXELFORMAT_ASTC_4x4: + case PIXELFORMAT_ASTC_4x4_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR; + mtlformat = MTLPixelFormatASTC_4x4_LDR; break; - case PIXELFORMAT_ASTC_5x4: + case PIXELFORMAT_ASTC_5x4_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR; + mtlformat = MTLPixelFormatASTC_5x4_LDR; break; - case PIXELFORMAT_ASTC_5x5: + case PIXELFORMAT_ASTC_5x5_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR; + mtlformat = MTLPixelFormatASTC_5x5_LDR; break; - case PIXELFORMAT_ASTC_6x5: + case PIXELFORMAT_ASTC_6x5_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR; + mtlformat = MTLPixelFormatASTC_6x5_LDR; break; - case PIXELFORMAT_ASTC_6x6: + case PIXELFORMAT_ASTC_6x6_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR; + mtlformat = MTLPixelFormatASTC_6x6_LDR; break; - case PIXELFORMAT_ASTC_8x5: + case PIXELFORMAT_ASTC_8x5_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR; + mtlformat = MTLPixelFormatASTC_8x5_LDR; break; - case PIXELFORMAT_ASTC_8x6: + case PIXELFORMAT_ASTC_8x6_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR; + mtlformat = MTLPixelFormatASTC_8x6_LDR; break; - case PIXELFORMAT_ASTC_8x8: + case PIXELFORMAT_ASTC_8x8_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR; + mtlformat = MTLPixelFormatASTC_8x8_LDR; break; - case PIXELFORMAT_ASTC_10x5: + case PIXELFORMAT_ASTC_10x5_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR; + mtlformat = MTLPixelFormatASTC_10x5_LDR; break; - case PIXELFORMAT_ASTC_10x6: + case PIXELFORMAT_ASTC_10x6_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR; + mtlformat = MTLPixelFormatASTC_10x6_LDR; break; - case PIXELFORMAT_ASTC_10x8: + case PIXELFORMAT_ASTC_10x8_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR; + mtlformat = MTLPixelFormatASTC_10x8_LDR; break; - case PIXELFORMAT_ASTC_10x10: + case PIXELFORMAT_ASTC_10x10_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR; + mtlformat = MTLPixelFormatASTC_10x10_LDR; break; - case PIXELFORMAT_ASTC_12x10: + case PIXELFORMAT_ASTC_12x10_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR; + mtlformat = MTLPixelFormatASTC_12x10_LDR; break; - case PIXELFORMAT_ASTC_12x12: + case PIXELFORMAT_ASTC_12x12_UNORM: if (@available(macOS 11.0, iOS 8.0, *)) - mtlformat = isSRGB ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR; + mtlformat = MTLPixelFormatASTC_12x12_LDR; + break; + case PIXELFORMAT_ASTC_4x4_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_4x4_sRGB; + break; + case PIXELFORMAT_ASTC_5x4_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_5x4_sRGB; + break; + case PIXELFORMAT_ASTC_5x5_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_5x5_sRGB; + break; + case PIXELFORMAT_ASTC_6x5_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_6x5_sRGB; + break; + case PIXELFORMAT_ASTC_6x6_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_6x6_sRGB; + break; + case PIXELFORMAT_ASTC_8x5_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_8x5_sRGB; + break; + case PIXELFORMAT_ASTC_8x6_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_8x6_sRGB; + break; + case PIXELFORMAT_ASTC_8x8_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_8x8_sRGB; + break; + case PIXELFORMAT_ASTC_10x5_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_10x5_sRGB; + break; + case PIXELFORMAT_ASTC_10x6_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_10x6_sRGB; + break; + case PIXELFORMAT_ASTC_10x8_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_10x8_sRGB; + break; + case PIXELFORMAT_ASTC_10x10_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_10x10_sRGB; + break; + case PIXELFORMAT_ASTC_12x10_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_12x10_sRGB; + break; + case PIXELFORMAT_ASTC_12x12_sRGB: + if (@available(macOS 11.0, iOS 8.0, *)) + mtlformat = MTLPixelFormatASTC_12x12_sRGB; break; case PIXELFORMAT_UNKNOWN: diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index 8421cbcc1..0efd7d21a 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/src/modules/graphics/metal/Texture.mm @@ -62,7 +62,7 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id device, const desc.mipmapLevelCount = mipmapCount; desc.textureType = getMTLTextureType(texType, 1); - auto formatdesc = Metal::convertPixelFormat(device, format, sRGB); + auto formatdesc = Metal::convertPixelFormat(device, format); desc.pixelFormat = formatdesc.format; if (formatdesc.swizzled) { diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 651978742..e76da4ad7 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -250,7 +250,7 @@ void Graphics::updateBackbuffer(int width, int height, int /*pixelwidth*/, int p settings.renderTarget = true; settings.readable.set(false); - settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_UNORM_sRGB : PIXELFORMAT_RGBA8_UNORM; + settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_sRGB : PIXELFORMAT_RGBA8_UNORM; internalBackbuffer.set(newTexture(settings), Acquire::NORETAIN); settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8; @@ -1189,8 +1189,7 @@ GLuint Graphics::bindCachedFBO(const RenderTargets &targets) auto attachRT = [&](const RenderTarget &rt) { bool renderbuffer = msaa > 1 || !rt.texture->isReadable(); - bool srgb = false; - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer, srgb); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer); if (fmt.framebufferAttachments[0] == GL_COLOR_ATTACHMENT0) { @@ -1754,9 +1753,8 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable) { GLuint texture = 0; GLuint renderbuffer = 0; - bool sRGB = isPixelFormatSRGB(format); - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable); GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL); @@ -1778,7 +1776,7 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable) s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST; gl.setSamplerState(TEXTURE_2D, s); - gl.rawTexStorage(TEXTURE_2D, 1, format, sRGB, 1, 1); + gl.rawTexStorage(TEXTURE_2D, 1, format, 1, 1); } else { @@ -1814,11 +1812,8 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable) return usage; } -bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) +bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage) { - if (sRGB) - format = getSRGBPixelFormat(format); - format = getSizedFormat(format); bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0; diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index d27c96791..09b01ce10 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -106,7 +106,7 @@ public: void setWireframe(bool enable) override; - bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override; + bool isPixelFormatSupported(PixelFormat format, uint32 usage) override; Renderer getRenderer() const override; bool usesGLSLES() const override; RendererInfo getRendererInfo() const override; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 9166b8c9f..7ad47cb08 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -646,11 +646,9 @@ void OpenGL::createDefaultTexture() const GLubyte *p = datatype == DATA_BASETYPE_FLOAT ? pix : intpix; - bool isSRGB = false; - rawTexStorage(type, 1, format, isSRGB, 1, 1); - - TextureFormat fmt = convertPixelFormat(format, false, isSRGB); + rawTexStorage(type, 1, format, 1, 1); + TextureFormat fmt = convertPixelFormat(format, false); int slices = type == TEXTURE_CUBE ? 6 : 1; for (int slice = 0; slice < slices; slice++) @@ -1433,10 +1431,10 @@ void OpenGL::setSamplerState(TextureType target, SamplerState &s) } } -bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth) +bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, int width, int height, int depth) { GLenum gltarget = getGLTextureType(target); - TextureFormat fmt = convertPixelFormat(pixelformat, false, isSRGB); + TextureFormat fmt = convertPixelFormat(pixelformat, false); // This shouldn't be needed for glTexStorage, but some drivers don't follow // the spec apparently. @@ -1700,16 +1698,14 @@ OpenGL::Vendor OpenGL::getVendor() const return vendor; } -OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB) +OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool renderbuffer) { TextureFormat f; f.framebufferAttachments[0] = GL_COLOR_ATTACHMENT0; f.framebufferAttachments[1] = GL_NONE; - if (isSRGB) - pixelformat = getSRGBPixelFormat(pixelformat); - else if (pixelformat == PIXELFORMAT_ETC1_UNORM) + if (pixelformat == PIXELFORMAT_ETC1_UNORM) { // The ETC2 format can load ETC1 textures. if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility) @@ -1742,7 +1738,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r f.externalformat = GL_RGBA; f.type = GL_UNSIGNED_BYTE; break; - case PIXELFORMAT_RGBA8_UNORM_sRGB: + case PIXELFORMAT_RGBA8_sRGB: f.internalformat = GL_SRGB8_ALPHA8; f.type = GL_UNSIGNED_BYTE; if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0) @@ -1751,7 +1747,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r f.externalformat = GL_RGBA; break; case PIXELFORMAT_BGRA8_UNORM: - case PIXELFORMAT_BGRA8_UNORM_sRGB: + case PIXELFORMAT_BGRA8_sRGB: // Not supported right now. break; case PIXELFORMAT_R16_UNORM: @@ -2026,123 +2022,190 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r break; case PIXELFORMAT_DXT1_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + break; + case PIXELFORMAT_DXT1_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; break; case PIXELFORMAT_DXT3_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + case PIXELFORMAT_DXT3_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; break; case PIXELFORMAT_DXT5_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + case PIXELFORMAT_DXT5_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; break; case PIXELFORMAT_BC4_UNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_RED_RGTC1; break; case PIXELFORMAT_BC4_SNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_SIGNED_RED_RGTC1; break; case PIXELFORMAT_BC5_UNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_RG_RGTC2; break; case PIXELFORMAT_BC5_SNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_SIGNED_RG_RGTC2; break; case PIXELFORMAT_BC6H_UFLOAT: - isSRGB = false; f.internalformat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; break; case PIXELFORMAT_BC6H_FLOAT: - isSRGB = false; f.internalformat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; break; case PIXELFORMAT_BC7_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : GL_COMPRESSED_RGBA_BPTC_UNORM; + f.internalformat = GL_COMPRESSED_RGBA_BPTC_UNORM; break; + case PIXELFORMAT_BC7_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; + break; + case PIXELFORMAT_PVR1_RGB2_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + f.internalformat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + break; + case PIXELFORMAT_PVR1_RGB2_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT; break; case PIXELFORMAT_PVR1_RGB4_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + f.internalformat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + break; + case PIXELFORMAT_PVR1_RGB4_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT; break; case PIXELFORMAT_PVR1_RGBA2_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + f.internalformat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + break; + case PIXELFORMAT_PVR1_RGBA2_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT; break; case PIXELFORMAT_PVR1_RGBA4_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + f.internalformat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; + case PIXELFORMAT_PVR1_RGBA4_sRGB: + f.internalformat = GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT; + break; + case PIXELFORMAT_ETC1_UNORM: - isSRGB = false; f.internalformat = GL_ETC1_RGB8_OES; break; case PIXELFORMAT_ETC2_RGB_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ETC2 : GL_COMPRESSED_RGB8_ETC2; + f.internalformat = GL_COMPRESSED_RGB8_ETC2; + break; + case PIXELFORMAT_ETC2_RGB_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ETC2; break; case PIXELFORMAT_ETC2_RGBA_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : GL_COMPRESSED_RGBA8_ETC2_EAC; + f.internalformat = GL_COMPRESSED_RGBA8_ETC2_EAC; + break; + case PIXELFORMAT_ETC2_RGBA_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; break; case PIXELFORMAT_ETC2_RGBA1_UNORM: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + f.internalformat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case PIXELFORMAT_ETC2_RGBA1_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; break; case PIXELFORMAT_EAC_R_UNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_R11_EAC; break; case PIXELFORMAT_EAC_R_SNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_SIGNED_R11_EAC; break; case PIXELFORMAT_EAC_RG_UNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_RG11_EAC; break; case PIXELFORMAT_EAC_RG_SNORM: - isSRGB = false; f.internalformat = GL_COMPRESSED_SIGNED_RG11_EAC; break; - case PIXELFORMAT_ASTC_4x4: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : GL_COMPRESSED_RGBA_ASTC_4x4_KHR; + + case PIXELFORMAT_ASTC_4x4_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; - case PIXELFORMAT_ASTC_5x4: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : GL_COMPRESSED_RGBA_ASTC_5x4_KHR; + case PIXELFORMAT_ASTC_4x4_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR; break; - case PIXELFORMAT_ASTC_5x5: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : GL_COMPRESSED_RGBA_ASTC_5x5_KHR; + case PIXELFORMAT_ASTC_5x4_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_5x4_KHR; break; - case PIXELFORMAT_ASTC_6x5: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : GL_COMPRESSED_RGBA_ASTC_6x5_KHR; + case PIXELFORMAT_ASTC_5x4_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR; break; - case PIXELFORMAT_ASTC_6x6: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : GL_COMPRESSED_RGBA_ASTC_6x6_KHR; + case PIXELFORMAT_ASTC_5x5_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_5x5_KHR; break; - case PIXELFORMAT_ASTC_8x5: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : GL_COMPRESSED_RGBA_ASTC_8x5_KHR; + case PIXELFORMAT_ASTC_5x5_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR; break; - case PIXELFORMAT_ASTC_8x6: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : GL_COMPRESSED_RGBA_ASTC_8x6_KHR; + case PIXELFORMAT_ASTC_6x5_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_6x5_KHR; break; - case PIXELFORMAT_ASTC_8x8: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : GL_COMPRESSED_RGBA_ASTC_8x8_KHR; + case PIXELFORMAT_ASTC_6x5_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR; break; - case PIXELFORMAT_ASTC_10x5: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : GL_COMPRESSED_RGBA_ASTC_10x5_KHR; + case PIXELFORMAT_ASTC_6x6_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_6x6_KHR; break; - case PIXELFORMAT_ASTC_10x6: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : GL_COMPRESSED_RGBA_ASTC_10x6_KHR; + case PIXELFORMAT_ASTC_6x6_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR; break; - case PIXELFORMAT_ASTC_10x8: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : GL_COMPRESSED_RGBA_ASTC_10x8_KHR; + case PIXELFORMAT_ASTC_8x5_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x5_KHR; break; - case PIXELFORMAT_ASTC_10x10: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : GL_COMPRESSED_RGBA_ASTC_10x10_KHR; + case PIXELFORMAT_ASTC_8x5_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR; break; - case PIXELFORMAT_ASTC_12x10: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : GL_COMPRESSED_RGBA_ASTC_12x10_KHR; + case PIXELFORMAT_ASTC_8x6_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x6_KHR; break; - case PIXELFORMAT_ASTC_12x12: - f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : GL_COMPRESSED_RGBA_ASTC_12x12_KHR; + case PIXELFORMAT_ASTC_8x6_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR; + break; + case PIXELFORMAT_ASTC_8x8_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; + break; + case PIXELFORMAT_ASTC_8x8_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR; + break; + case PIXELFORMAT_ASTC_10x5_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x5_KHR; + break; + case PIXELFORMAT_ASTC_10x5_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR; + break; + case PIXELFORMAT_ASTC_10x6_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x6_KHR; + break; + case PIXELFORMAT_ASTC_10x6_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR; + break; + case PIXELFORMAT_ASTC_10x8_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x8_KHR; + break; + case PIXELFORMAT_ASTC_10x8_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR; + break; + case PIXELFORMAT_ASTC_10x10_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x10_KHR; + break; + case PIXELFORMAT_ASTC_10x10_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR; + break; + case PIXELFORMAT_ASTC_12x10_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_12x10_KHR; + break; + case PIXELFORMAT_ASTC_12x10_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR; + break; + case PIXELFORMAT_ASTC_12x12_UNORM: + f.internalformat = GL_COMPRESSED_RGBA_ASTC_12x12_KHR; + break; + case PIXELFORMAT_ASTC_12x12_sRGB: + f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR; break; default: @@ -2164,9 +2227,6 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r { f.internalformat = f.externalformat; } - - if (!isPixelFormatSRGB(pixelformat)) - isSRGB = false; } return f; @@ -2198,7 +2258,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_1) flags |= computewrite; break; - case PIXELFORMAT_RGBA8_UNORM_sRGB: + case PIXELFORMAT_RGBA8_sRGB: if (gl.bugs.brokenSRGB) break; if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB) @@ -2210,7 +2270,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= computewrite; break; case PIXELFORMAT_BGRA8_UNORM: - case PIXELFORMAT_BGRA8_UNORM_sRGB: + case PIXELFORMAT_BGRA8_sRGB: // Not supported right now. break; case PIXELFORMAT_R16_UNORM: @@ -2278,47 +2338,47 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) flags |= computewrite; break; - case PIXELFORMAT_R8_INT: - case PIXELFORMAT_R8_UINT: - case PIXELFORMAT_RG8_INT: - case PIXELFORMAT_RG8_UINT: - case PIXELFORMAT_RGBA8_INT: - case PIXELFORMAT_RGBA8_UINT: - case PIXELFORMAT_R16_INT: - case PIXELFORMAT_R16_UINT: - case PIXELFORMAT_RG16_INT: - case PIXELFORMAT_RG16_UINT: - case PIXELFORMAT_RGBA16_INT: - case PIXELFORMAT_RGBA16_UINT: - case PIXELFORMAT_R32_INT: - case PIXELFORMAT_R32_UINT: - case PIXELFORMAT_RG32_INT: - case PIXELFORMAT_RG32_UINT: - case PIXELFORMAT_RGBA32_INT: - case PIXELFORMAT_RGBA32_UINT: - if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0) - flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET; - if (GLAD_VERSION_4_3) - flags |= computewrite; - if (GLAD_ES_VERSION_3_1) + case PIXELFORMAT_R8_INT: + case PIXELFORMAT_R8_UINT: + case PIXELFORMAT_RG8_INT: + case PIXELFORMAT_RG8_UINT: + case PIXELFORMAT_RGBA8_INT: + case PIXELFORMAT_RGBA8_UINT: + case PIXELFORMAT_R16_INT: + case PIXELFORMAT_R16_UINT: + case PIXELFORMAT_RG16_INT: + case PIXELFORMAT_RG16_UINT: + case PIXELFORMAT_RGBA16_INT: + case PIXELFORMAT_RGBA16_UINT: + case PIXELFORMAT_R32_INT: + case PIXELFORMAT_R32_UINT: + case PIXELFORMAT_RG32_INT: + case PIXELFORMAT_RG32_UINT: + case PIXELFORMAT_RGBA32_INT: + case PIXELFORMAT_RGBA32_UINT: + if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0) + flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET; + if (GLAD_VERSION_4_3) + flags |= computewrite; + if (GLAD_ES_VERSION_3_1) + { + switch (pixelformat) { - switch (pixelformat) - { - case PIXELFORMAT_RGBA8_INT: - case PIXELFORMAT_RGBA8_UINT: - case PIXELFORMAT_RGBA16_INT: - case PIXELFORMAT_RGBA16_UINT: - case PIXELFORMAT_R32_INT: - case PIXELFORMAT_R32_UINT: - case PIXELFORMAT_RGBA32_INT: - case PIXELFORMAT_RGBA32_UINT: - flags |= computewrite; - break; - default: - break; - } + case PIXELFORMAT_RGBA8_INT: + case PIXELFORMAT_RGBA8_UINT: + case PIXELFORMAT_RGBA16_INT: + case PIXELFORMAT_RGBA16_UINT: + case PIXELFORMAT_R32_INT: + case PIXELFORMAT_R32_UINT: + case PIXELFORMAT_RGBA32_INT: + case PIXELFORMAT_RGBA32_UINT: + flags |= computewrite; + break; + default: + break; } - break; + } + break; case PIXELFORMAT_LA8_UNORM: flags |= commonsample; @@ -2380,14 +2440,17 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) break; case PIXELFORMAT_DXT1_UNORM: + case PIXELFORMAT_DXT1_sRGB: if (GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1) flags |= commonsample; break; case PIXELFORMAT_DXT3_UNORM: + case PIXELFORMAT_DXT3_sRGB: if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3) flags |= commonsample; break; case PIXELFORMAT_DXT5_UNORM: + case PIXELFORMAT_DXT5_sRGB: if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5) flags |= commonsample; break; @@ -2401,6 +2464,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) case PIXELFORMAT_BC6H_UFLOAT: case PIXELFORMAT_BC6H_FLOAT: case PIXELFORMAT_BC7_UNORM: + case PIXELFORMAT_BC7_sRGB: if (GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc) flags |= commonsample; break; @@ -2411,14 +2475,24 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) if (GLAD_IMG_texture_compression_pvrtc) flags |= commonsample; break; + case PIXELFORMAT_PVR1_RGB2_sRGB: + case PIXELFORMAT_PVR1_RGB4_sRGB: + case PIXELFORMAT_PVR1_RGBA2_sRGB: + case PIXELFORMAT_PVR1_RGBA4_sRGB: + if (GLAD_EXT_pvrtc_sRGB) + flags |= commonsample; + break; case PIXELFORMAT_ETC1_UNORM: // ETC2 support guarantees ETC1 support as well. if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture) flags |= commonsample; break; case PIXELFORMAT_ETC2_RGB_UNORM: + case PIXELFORMAT_ETC2_RGB_sRGB: case PIXELFORMAT_ETC2_RGBA_UNORM: + case PIXELFORMAT_ETC2_RGBA_sRGB: case PIXELFORMAT_ETC2_RGBA1_UNORM: + case PIXELFORMAT_ETC2_RGBA1_sRGB: case PIXELFORMAT_EAC_R_UNORM: case PIXELFORMAT_EAC_R_SNORM: case PIXELFORMAT_EAC_RG_UNORM: @@ -2426,20 +2500,34 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat) if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility) flags |= commonsample; break; - case PIXELFORMAT_ASTC_4x4: - case PIXELFORMAT_ASTC_5x4: - case PIXELFORMAT_ASTC_5x5: - case PIXELFORMAT_ASTC_6x5: - case PIXELFORMAT_ASTC_6x6: - case PIXELFORMAT_ASTC_8x5: - case PIXELFORMAT_ASTC_8x6: - case PIXELFORMAT_ASTC_8x8: - case PIXELFORMAT_ASTC_10x5: - case PIXELFORMAT_ASTC_10x6: - case PIXELFORMAT_ASTC_10x8: - case PIXELFORMAT_ASTC_10x10: - case PIXELFORMAT_ASTC_12x10: - case PIXELFORMAT_ASTC_12x12: + case PIXELFORMAT_ASTC_4x4_UNORM: + case PIXELFORMAT_ASTC_5x4_UNORM: + case PIXELFORMAT_ASTC_5x5_UNORM: + case PIXELFORMAT_ASTC_6x5_UNORM: + case PIXELFORMAT_ASTC_6x6_UNORM: + case PIXELFORMAT_ASTC_8x5_UNORM: + case PIXELFORMAT_ASTC_8x6_UNORM: + case PIXELFORMAT_ASTC_8x8_UNORM: + case PIXELFORMAT_ASTC_10x5_UNORM: + case PIXELFORMAT_ASTC_10x6_UNORM: + case PIXELFORMAT_ASTC_10x8_UNORM: + case PIXELFORMAT_ASTC_10x10_UNORM: + case PIXELFORMAT_ASTC_12x10_UNORM: + case PIXELFORMAT_ASTC_12x12_UNORM: + case PIXELFORMAT_ASTC_4x4_sRGB: + case PIXELFORMAT_ASTC_5x4_sRGB: + case PIXELFORMAT_ASTC_5x5_sRGB: + case PIXELFORMAT_ASTC_6x5_sRGB: + case PIXELFORMAT_ASTC_6x6_sRGB: + case PIXELFORMAT_ASTC_8x5_sRGB: + case PIXELFORMAT_ASTC_8x6_sRGB: + case PIXELFORMAT_ASTC_8x8_sRGB: + case PIXELFORMAT_ASTC_10x5_sRGB: + case PIXELFORMAT_ASTC_10x6_sRGB: + case PIXELFORMAT_ASTC_10x8_sRGB: + case PIXELFORMAT_ASTC_10x10_sRGB: + case PIXELFORMAT_ASTC_12x10_sRGB: + case PIXELFORMAT_ASTC_12x12_sRGB: if (GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr) flags |= commonsample; break; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 3690c6baa..e3cbff100 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -381,7 +381,7 @@ public: * to glTexImage2D/3D for all levels and slices of a texture otherwise. * NOTE: this does not handle compressed texture formats. **/ - bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth = 1); + bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, int width, int height, int depth = 1); bool isTextureTypeSupported(TextureType type) const; bool isBufferUsageSupported(BufferUsage usage) const; @@ -475,7 +475,7 @@ public: static GLint getGLWrapMode(SamplerState::WrapMode wmode); static GLint getGLCompareMode(CompareMode mode); - static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB); + static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer); static bool isTexStorageSupported(); static uint32 getPixelFormatUsageFlags(PixelFormat pixelformat); diff --git a/src/modules/graphics/opengl/Shader.cpp b/src/modules/graphics/opengl/Shader.cpp index d4d2b65ca..bfd728a1e 100644 --- a/src/modules/graphics/opengl/Shader.cpp +++ b/src/modules/graphics/opengl/Shader.cpp @@ -175,8 +175,7 @@ void Shader::mapActiveUniforms() else if ((u.access & ACCESS_READ) != 0) binding.access = GL_READ_ONLY; - bool sRGB = false; - auto fmt = OpenGL::convertPixelFormat(u.storageTextureFormat, false, sRGB); + auto fmt = OpenGL::convertPixelFormat(u.storageTextureFormat, false); binding.internalFormat = fmt.internalformat; for (int i = 0; i < u.count; i++) diff --git a/src/modules/graphics/opengl/Texture.cpp b/src/modules/graphics/opengl/Texture.cpp index 1b6eb69f1..8a9ad9655 100644 --- a/src/modules/graphics/opengl/Texture.cpp +++ b/src/modules/graphics/opengl/Texture.cpp @@ -56,8 +56,7 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo glReadBuffer(GL_NONE); } - bool unusedSRGB = false; - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false, unusedSRGB); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false); int faces = texType == TEXTURE_CUBE ? 6 : 1; @@ -125,8 +124,7 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat pixelformat, GLuint &buffer) { - bool unusedSRGB = false; - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true, unusedSRGB); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true); GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL); @@ -282,7 +280,7 @@ void Texture::createTexture() // remember some driver issues on some old Android systems, maybe... // For now, the base class enforces data on init for compressed textures. if (!isCompressed()) - gl.rawTexStorage(texType, mipcount, format, sRGB, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers); + gl.rawTexStorage(texType, mipcount, format, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers); // rawTexStorage handles this for uncompressed textures. if (isCompressed() && (GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0)) @@ -292,7 +290,7 @@ void Texture::createTexture() int h = pixelHeight; int d = depth; - OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, sRGB); + OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false); for (int mip = 0; mip < mipcount; mip++) { @@ -460,7 +458,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s gl.bindTextureToUnit(this, 0, false); - OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false, sRGB); + OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false); GLenum gltarget = OpenGL::getGLTextureType(texType); if (texType == TEXTURE_CUBE) @@ -508,8 +506,7 @@ void Texture::readbackInternal(int slice, int mipmap, const Rect &rect, int dest gl.bindTextureToUnit(this, 0, false); - bool isSRGB = false; - OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, isSRGB); + OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false); if (gl.isCopyTextureToBufferSupported()) { diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 39228f335..c3a7c5c73 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -1057,11 +1057,11 @@ void Graphics::setWireframe(bool enable) states.back().wireframe = enable; } -bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) +bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage) { format = getSizedFormat(format); - auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB); + auto vulkanFormat = Vulkan::getTextureFormat(format); VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(physicalDevice, vulkanFormat.internalFormat, &formatProperties); @@ -2444,12 +2444,12 @@ void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, b RenderPassConfiguration renderPassConfiguration{}; for (const auto &color : rts.colors) renderPassConfiguration.colorAttachments.push_back({ - Vulkan::getTextureFormat(color.texture->getPixelFormat(), isPixelFormatSRGB(color.texture->getPixelFormat())).internalFormat, + Vulkan::getTextureFormat(color.texture->getPixelFormat()).internalFormat, VK_ATTACHMENT_LOAD_OP_LOAD, dynamic_cast(color.texture)->getMsaaSamples() }); if (rts.depthStencil.texture != nullptr) renderPassConfiguration.staticData.depthStencilAttachment = { - Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat(), false).internalFormat, + Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat()).internalFormat, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD, dynamic_cast(rts.depthStencil.texture)->getMsaaSamples() }; diff --git a/src/modules/graphics/vulkan/Graphics.h b/src/modules/graphics/vulkan/Graphics.h index 69ae238b5..e2ae0541b 100644 --- a/src/modules/graphics/vulkan/Graphics.h +++ b/src/modules/graphics/vulkan/Graphics.h @@ -297,7 +297,7 @@ public: void setBlendState(const BlendState &blend) override; void setPointSize(float size) override; void setWireframe(bool enable) override; - bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) override; + bool isPixelFormatSupported(PixelFormat format, uint32 usage) override; Renderer getRenderer() const override; bool usesGLSLES() const override; RendererInfo getRendererInfo() const override; diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 8a979789c..4eea47722 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -59,7 +59,7 @@ bool Texture::loadVolatile() if (isPixelFormatColor(format)) imageAspect |= VK_IMAGE_ASPECT_COLOR_BIT; - auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB); + auto vulkanFormat = Vulkan::getTextureFormat(format); VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | @@ -277,7 +277,7 @@ VkImageLayout Texture::getImageLayout() const void Texture::createTextureImageView() { - auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB); + auto vulkanFormat = Vulkan::getTextureFormat(format); VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -349,7 +349,7 @@ void Texture::clear() VkClearColorValue Texture::getClearValue() { - auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB); + auto vulkanFormat = Vulkan::getTextureFormat(format); VkClearColorValue clearColor{}; switch (vulkanFormat.internalFormatRepresentation) diff --git a/src/modules/graphics/vulkan/Vulkan.cpp b/src/modules/graphics/vulkan/Vulkan.cpp index 817f6fdb7..afd991fcd 100644 --- a/src/modules/graphics/vulkan/Vulkan.cpp +++ b/src/modules/graphics/vulkan/Vulkan.cpp @@ -130,16 +130,10 @@ VkFormat Vulkan::getVulkanVertexFormat(DataFormat format) } } -TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB) +TextureFormat Vulkan::getTextureFormat(PixelFormat format) { TextureFormat textureFormat{}; - if (sRGB) - format = getSRGBPixelFormat(format); - - if (!isPixelFormatCompressed(format) && !isPixelFormatSRGB(format)) - sRGB = false; - switch (format) { case PIXELFORMAT_UNKNOWN: @@ -231,13 +225,13 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB) case PIXELFORMAT_RGBA8_UNORM: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_UNORM; break; - case PIXELFORMAT_RGBA8_UNORM_sRGB: + case PIXELFORMAT_RGBA8_sRGB: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB; break; case PIXELFORMAT_BGRA8_UNORM: textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM; break; - case PIXELFORMAT_BGRA8_UNORM_sRGB: + case PIXELFORMAT_BGRA8_sRGB: textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB; break; case PIXELFORMAT_RGBA8_INT: @@ -308,13 +302,22 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB) textureFormat.internalFormat = VK_FORMAT_D32_SFLOAT_S8_UINT; break; case PIXELFORMAT_DXT1_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_BC1_RGBA_SRGB_BLOCK : VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + break; + case PIXELFORMAT_DXT1_sRGB: + textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_SRGB_BLOCK; break; case PIXELFORMAT_DXT3_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_BC2_SRGB_BLOCK : VK_FORMAT_BC2_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_BC2_UNORM_BLOCK; + break; + case PIXELFORMAT_DXT3_sRGB: + textureFormat.internalFormat = VK_FORMAT_BC2_SRGB_BLOCK; break; case PIXELFORMAT_DXT5_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_BC3_UNORM_BLOCK; + break; + case PIXELFORMAT_DXT5_sRGB: + textureFormat.internalFormat = VK_FORMAT_BC3_SRGB_BLOCK; break; case PIXELFORMAT_BC4_UNORM: textureFormat.internalFormat = VK_FORMAT_BC4_UNORM_BLOCK; @@ -335,31 +338,55 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB) textureFormat.internalFormat = VK_FORMAT_BC6H_SFLOAT_BLOCK; break; case PIXELFORMAT_BC7_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_BC7_UNORM_BLOCK; + break; + case PIXELFORMAT_BC7_sRGB: + textureFormat.internalFormat = VK_FORMAT_BC7_SRGB_BLOCK; break; case PIXELFORMAT_PVR1_RGB2_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + break; + case PIXELFORMAT_PVR1_RGB2_sRGB: + textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; break; case PIXELFORMAT_PVR1_RGB4_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + break; + case PIXELFORMAT_PVR1_RGB4_sRGB: + textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; break; case PIXELFORMAT_PVR1_RGBA2_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + break; + case PIXELFORMAT_PVR1_RGBA2_sRGB: + textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; break; case PIXELFORMAT_PVR1_RGBA4_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + break; + case PIXELFORMAT_PVR1_RGBA4_sRGB: + textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; break; case PIXELFORMAT_ETC1_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; break; case PIXELFORMAT_ETC2_RGB_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + break; + case PIXELFORMAT_ETC2_RGB_sRGB: + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; break; case PIXELFORMAT_ETC2_RGBA_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + break; + case PIXELFORMAT_ETC2_RGBA_sRGB: + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; break; case PIXELFORMAT_ETC2_RGBA1_UNORM: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + break; + case PIXELFORMAT_ETC2_RGBA1_sRGB: + textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; break; case PIXELFORMAT_EAC_R_UNORM: textureFormat.internalFormat = VK_FORMAT_EAC_R11_UNORM_BLOCK; @@ -373,47 +400,89 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB) case PIXELFORMAT_EAC_RG_SNORM: textureFormat.internalFormat = VK_FORMAT_EAC_R11G11_SNORM_BLOCK; break; - case PIXELFORMAT_ASTC_4x4: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_4x4_SRGB_BLOCK : VK_FORMAT_ASTC_4x4_UNORM_BLOCK; + case PIXELFORMAT_ASTC_4x4_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_5x4: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_5x4_SRGB_BLOCK : VK_FORMAT_ASTC_5x4_UNORM_BLOCK; + case PIXELFORMAT_ASTC_5x4_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_5x5: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_5x5_SRGB_BLOCK : VK_FORMAT_ASTC_5x5_UNORM_BLOCK; + case PIXELFORMAT_ASTC_5x5_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_6x5: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_6x5_SRGB_BLOCK : VK_FORMAT_ASTC_6x5_UNORM_BLOCK; + case PIXELFORMAT_ASTC_6x5_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_6x6: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_6x6_SRGB_BLOCK : VK_FORMAT_ASTC_6x6_UNORM_BLOCK; + case PIXELFORMAT_ASTC_6x6_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_8x5: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x5_SRGB_BLOCK : VK_FORMAT_ASTC_8x5_UNORM_BLOCK; + case PIXELFORMAT_ASTC_8x5_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_8x6: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x6_SRGB_BLOCK : VK_FORMAT_ASTC_8x6_UNORM_BLOCK; + case PIXELFORMAT_ASTC_8x6_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_8x8: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x8_SRGB_BLOCK : VK_FORMAT_ASTC_8x8_UNORM_BLOCK; + case PIXELFORMAT_ASTC_8x8_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_10x5: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x5_SRGB_BLOCK : VK_FORMAT_ASTC_10x5_UNORM_BLOCK; + case PIXELFORMAT_ASTC_10x5_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_10x6: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x6_SRGB_BLOCK : VK_FORMAT_ASTC_10x6_UNORM_BLOCK; + case PIXELFORMAT_ASTC_10x6_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_10x8: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x8_SRGB_BLOCK : VK_FORMAT_ASTC_10x8_UNORM_BLOCK; + case PIXELFORMAT_ASTC_10x8_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_10x10: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x10_SRGB_BLOCK : VK_FORMAT_ASTC_10x10_UNORM_BLOCK; + case PIXELFORMAT_ASTC_10x10_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_12x10: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_12x10_SRGB_BLOCK : VK_FORMAT_ASTC_12x10_UNORM_BLOCK; + case PIXELFORMAT_ASTC_12x10_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break; - case PIXELFORMAT_ASTC_12x12: - textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_12x12_SRGB_BLOCK : VK_FORMAT_ASTC_12x12_UNORM_BLOCK; + case PIXELFORMAT_ASTC_12x12_UNORM: + textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; + break; + case PIXELFORMAT_ASTC_4x4_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_5x4_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_5x5_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_6x5_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_6x6_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_8x5_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_8x6_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_8x8_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_10x5_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_10x6_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_10x8_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_10x10_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_12x10_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_SRGB_BLOCK; + break; + case PIXELFORMAT_ASTC_12x12_sRGB: + textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_SRGB_BLOCK; break; default: throw love::Exception("unknown pixel format"); diff --git a/src/modules/graphics/vulkan/Vulkan.h b/src/modules/graphics/vulkan/Vulkan.h index 2e512ab9d..46d27519f 100644 --- a/src/modules/graphics/vulkan/Vulkan.h +++ b/src/modules/graphics/vulkan/Vulkan.h @@ -59,7 +59,7 @@ public: static void resetShaderSwitches(); static VkFormat getVulkanVertexFormat(DataFormat format); - static TextureFormat getTextureFormat(PixelFormat, bool sRGB); + static TextureFormat getTextureFormat(PixelFormat format); static std::string getVendorName(uint32_t vendorId); static std::string getVulkanApiVersion(uint32_t apiVersion); static VkPrimitiveTopology getPrimitiveTypeTopology(graphics::PrimitiveType); diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 3a2eb613a..c5b9648ce 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -2783,7 +2783,6 @@ int w_getTextureFormats(lua_State *L) luaL_checktype(L, 1, LUA_TTABLE); bool rt = luax_checkboolflag(L, 1, Texture::getConstant(Texture::SETTING_RENDER_TARGET)); - bool linear = luax_boolflag(L, 1, Texture::getConstant(Texture::SETTING_LINEAR), false); bool computewrite = luax_boolflag(L, 1, Texture::getConstant(Texture::SETTING_COMPUTE_WRITE), false); OptionalBool readable; @@ -2808,8 +2807,6 @@ int w_getTextureFormats(lua_State *L) if (rt && isPixelFormatDepth(format)) continue; - bool sRGB = isGammaCorrect() && !linear; - uint32 usage = PIXELFORMATUSAGEFLAGS_NONE; if (rt) usage |= PIXELFORMATUSAGEFLAGS_RENDERTARGET; @@ -2818,7 +2815,7 @@ int w_getTextureFormats(lua_State *L) if (computewrite) usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE; - luax_pushboolean(L, instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, sRGB)); + luax_pushboolean(L, instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage)); lua_setfield(L, -2, name); } @@ -2862,14 +2859,14 @@ int w_getCanvasFormats(lua_State *L) supported = [](PixelFormat format) -> bool { const uint32 usage = PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET; - return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, false); + return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage); }; } else { supported = [](PixelFormat format) -> bool { - return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_RENDERTARGET, false); + return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_RENDERTARGET); }; } } @@ -2881,7 +2878,7 @@ int w_getCanvasFormats(lua_State *L) uint32 usage = PIXELFORMATUSAGEFLAGS_RENDERTARGET; if (readable) usage |= PIXELFORMATUSAGEFLAGS_SAMPLE; - return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, false); + return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage); }; } @@ -2894,7 +2891,7 @@ int w_getImageFormats(lua_State *L) const auto supported = [](PixelFormat format) -> bool { - return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_SAMPLE, false); + return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_SAMPLE); }; const auto ignore = [](PixelFormat format) -> bool diff --git a/src/modules/image/magpie/ASTCHandler.cpp b/src/modules/image/magpie/ASTCHandler.cpp index 8f2fb569f..fb9a395c2 100644 --- a/src/modules/image/magpie/ASTCHandler.cpp +++ b/src/modules/image/magpie/ASTCHandler.cpp @@ -54,33 +54,33 @@ static PixelFormat convertFormat(uint32 blockX, uint32 blockY, uint32 blockZ) return PIXELFORMAT_UNKNOWN; if (blockX == 4 && blockY == 4) - return PIXELFORMAT_ASTC_4x4; + return PIXELFORMAT_ASTC_4x4_UNORM; else if (blockX == 5 && blockY == 4) - return PIXELFORMAT_ASTC_5x4; + return PIXELFORMAT_ASTC_5x4_UNORM; else if (blockX == 5 && blockY == 5) - return PIXELFORMAT_ASTC_5x5; + return PIXELFORMAT_ASTC_5x5_UNORM; else if (blockX == 6 && blockY == 5) - return PIXELFORMAT_ASTC_6x5; + return PIXELFORMAT_ASTC_6x5_UNORM; else if (blockX == 6 && blockY == 6) - return PIXELFORMAT_ASTC_6x6; + return PIXELFORMAT_ASTC_6x6_UNORM; else if (blockX == 8 && blockY == 5) - return PIXELFORMAT_ASTC_8x5; + return PIXELFORMAT_ASTC_8x5_UNORM; else if (blockX == 8 && blockY == 6) - return PIXELFORMAT_ASTC_8x6; + return PIXELFORMAT_ASTC_8x6_UNORM; else if (blockX == 8 && blockY == 8) - return PIXELFORMAT_ASTC_8x8; + return PIXELFORMAT_ASTC_8x8_UNORM; else if (blockX == 10 && blockY == 5) - return PIXELFORMAT_ASTC_10x5; + return PIXELFORMAT_ASTC_10x5_UNORM; else if (blockX == 10 && blockY == 6) - return PIXELFORMAT_ASTC_10x6; + return PIXELFORMAT_ASTC_10x6_UNORM; else if (blockX == 10 && blockY == 8) - return PIXELFORMAT_ASTC_10x8; + return PIXELFORMAT_ASTC_10x8_UNORM; else if (blockX == 10 && blockY == 10) - return PIXELFORMAT_ASTC_10x10; + return PIXELFORMAT_ASTC_10x10_UNORM; else if (blockX == 12 && blockY == 10) - return PIXELFORMAT_ASTC_12x10; + return PIXELFORMAT_ASTC_12x10_UNORM; else if (blockX == 12 && blockY == 12) - return PIXELFORMAT_ASTC_12x12; + return PIXELFORMAT_ASTC_12x12_UNORM; return PIXELFORMAT_UNKNOWN; } diff --git a/src/modules/image/magpie/KTXHandler.cpp b/src/modules/image/magpie/KTXHandler.cpp index ac7f7ef03..758642b68 100644 --- a/src/modules/image/magpie/KTXHandler.cpp +++ b/src/modules/image/magpie/KTXHandler.cpp @@ -221,59 +221,59 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_4x4_KHR: - return PIXELFORMAT_ASTC_4x4; + return PIXELFORMAT_ASTC_4x4_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_5x4_KHR: - return PIXELFORMAT_ASTC_5x4; + return PIXELFORMAT_ASTC_5x4_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_5x5_KHR: - return PIXELFORMAT_ASTC_5x5; + return PIXELFORMAT_ASTC_5x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_6x5_KHR: - return PIXELFORMAT_ASTC_6x5; + return PIXELFORMAT_ASTC_6x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_6x6_KHR: - return PIXELFORMAT_ASTC_6x6; + return PIXELFORMAT_ASTC_6x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_8x5_KHR: - return PIXELFORMAT_ASTC_8x5; + return PIXELFORMAT_ASTC_8x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_8x6_KHR: - return PIXELFORMAT_ASTC_8x6; + return PIXELFORMAT_ASTC_8x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_8x8_KHR: - return PIXELFORMAT_ASTC_8x8; + return PIXELFORMAT_ASTC_8x8_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_10x5_KHR: - return PIXELFORMAT_ASTC_10x5; + return PIXELFORMAT_ASTC_10x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_10x6_KHR: - return PIXELFORMAT_ASTC_10x6; + return PIXELFORMAT_ASTC_10x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_10x8_KHR: - return PIXELFORMAT_ASTC_10x8; + return PIXELFORMAT_ASTC_10x8_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_10x10_KHR: - return PIXELFORMAT_ASTC_10x10; + return PIXELFORMAT_ASTC_10x10_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_12x10_KHR: - return PIXELFORMAT_ASTC_12x10; + return PIXELFORMAT_ASTC_12x10_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: sRGB = true; case KTX_GL_COMPRESSED_RGBA_ASTC_12x12_KHR: - return PIXELFORMAT_ASTC_12x12; + return PIXELFORMAT_ASTC_12x12_UNORM; default: return PIXELFORMAT_UNKNOWN; } diff --git a/src/modules/image/magpie/PVRHandler.cpp b/src/modules/image/magpie/PVRHandler.cpp index 21ebe6f0a..1259536ca 100644 --- a/src/modules/image/magpie/PVRHandler.cpp +++ b/src/modules/image/magpie/PVRHandler.cpp @@ -256,33 +256,33 @@ static PixelFormat convertFormat(PVRV3PixelFormat format, PVRV3ChannelType chann case ePVRTPF_EAC_RG: return snorm ? PIXELFORMAT_EAC_RG_SNORM : PIXELFORMAT_EAC_RG_UNORM; case ePVRTPF_ASTC_4x4: - return PIXELFORMAT_ASTC_4x4; + return PIXELFORMAT_ASTC_4x4_UNORM; case ePVRTPF_ASTC_5x4: - return PIXELFORMAT_ASTC_5x4; + return PIXELFORMAT_ASTC_5x4_UNORM; case ePVRTPF_ASTC_5x5: - return PIXELFORMAT_ASTC_5x5; + return PIXELFORMAT_ASTC_5x5_UNORM; case ePVRTPF_ASTC_6x5: - return PIXELFORMAT_ASTC_6x5; + return PIXELFORMAT_ASTC_6x5_UNORM; case ePVRTPF_ASTC_6x6: - return PIXELFORMAT_ASTC_6x6; + return PIXELFORMAT_ASTC_6x6_UNORM; case ePVRTPF_ASTC_8x5: - return PIXELFORMAT_ASTC_8x5; + return PIXELFORMAT_ASTC_8x5_UNORM; case ePVRTPF_ASTC_8x6: - return PIXELFORMAT_ASTC_8x6; + return PIXELFORMAT_ASTC_8x6_UNORM; case ePVRTPF_ASTC_8x8: - return PIXELFORMAT_ASTC_8x8; + return PIXELFORMAT_ASTC_8x8_UNORM; case ePVRTPF_ASTC_10x5: - return PIXELFORMAT_ASTC_10x5; + return PIXELFORMAT_ASTC_10x5_UNORM; case ePVRTPF_ASTC_10x6: - return PIXELFORMAT_ASTC_10x6; + return PIXELFORMAT_ASTC_10x6_UNORM; case ePVRTPF_ASTC_10x8: - return PIXELFORMAT_ASTC_10x8; + return PIXELFORMAT_ASTC_10x8_UNORM; case ePVRTPF_ASTC_10x10: - return PIXELFORMAT_ASTC_10x10; + return PIXELFORMAT_ASTC_10x10_UNORM; case ePVRTPF_ASTC_12x10: - return PIXELFORMAT_ASTC_12x10; + return PIXELFORMAT_ASTC_12x10_UNORM; case ePVRTPF_ASTC_12x12: - return PIXELFORMAT_ASTC_12x12; + return PIXELFORMAT_ASTC_12x12_UNORM; default: return PIXELFORMAT_UNKNOWN; } From bd55100d56f150d03a07dda4a05f0d3a361b4a00 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 14 Oct 2023 15:02:28 -0300 Subject: [PATCH 063/409] metal: fix compile error --- src/modules/graphics/metal/Shader.mm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/graphics/metal/Shader.mm b/src/modules/graphics/metal/Shader.mm index 5929e73ab..c9ffb8f21 100644 --- a/src/modules/graphics/metal/Shader.mm +++ b/src/modules/graphics/metal/Shader.mm @@ -1087,8 +1087,7 @@ id Shader::getCachedRenderPipeline(const RenderPipelineK MTLRenderPipelineColorAttachmentDescriptor *attachment = desc.colorAttachments[i]; - bool isSRGB = false; - auto formatdesc = Metal::convertPixelFormat(device, format, isSRGB); + auto formatdesc = Metal::convertPixelFormat(device, format); attachment.pixelFormat = formatdesc.format; if (key.blend.enable) @@ -1124,8 +1123,7 @@ id Shader::getCachedRenderPipeline(const RenderPipelineK { // We already don't really support metal on older systems, this just // silences a compiler warning about it. - bool isSRGB = false; - auto formatdesc = Metal::convertPixelFormat(device, dsformat, isSRGB); + auto formatdesc = Metal::convertPixelFormat(device, dsformat); if (isPixelFormatDepth(dsformat)) desc.depthAttachmentPixelFormat = formatdesc.format; if (isPixelFormatStencil(dsformat)) From 2aad15c865da4f0cce061c479100341430800f52 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 14 Oct 2023 16:42:31 -0300 Subject: [PATCH 064/409] Fix DistanceJoint type information --- src/modules/physics/box2d/DistanceJoint.cpp | 2 ++ src/modules/physics/box2d/DistanceJoint.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/modules/physics/box2d/DistanceJoint.cpp b/src/modules/physics/box2d/DistanceJoint.cpp index d85b9fa3c..0ed115b20 100644 --- a/src/modules/physics/box2d/DistanceJoint.cpp +++ b/src/modules/physics/box2d/DistanceJoint.cpp @@ -32,6 +32,8 @@ namespace physics namespace box2d { +love::Type DistanceJoint::type("DistanceJoint", &Joint::type); + DistanceJoint::DistanceJoint(Body *body1, Body *body2, float x1, float y1, float x2, float y2, bool collideConnected) : Joint(body1, body2) , joint(NULL) diff --git a/src/modules/physics/box2d/DistanceJoint.h b/src/modules/physics/box2d/DistanceJoint.h index 14060dee0..382efbbf6 100644 --- a/src/modules/physics/box2d/DistanceJoint.h +++ b/src/modules/physics/box2d/DistanceJoint.h @@ -39,6 +39,8 @@ class DistanceJoint : public Joint { public: + static love::Type type; + /** * Creates a DistanceJoint connecting body1 to body2. **/ From 8c13943f64750ab3f4b962e9716c003c9917a53e Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 14 Oct 2023 20:48:21 -0300 Subject: [PATCH 065/409] ImageData can track whether they're meant to be loaded into a Texture with a non-sRGB format when gamma correct rendering is enabled. Fixes #1556. * Add ImageData/CompressedImageData:setLinear and ImageData/CompressedImageData:isLinear. The flag is used as a hint when loading a texture from the data to determine if the format should not be treated as sRGB-encoded. The 'linear' flag in newImage overrides this. * love.graphics.readbackTexture automatically sets the linear flag on ImageData it returns when the texture's format is linear. This allows an ImageData generated via readback to be fed back into a new Texture and the format will match the original Canvas. * Also clean up some image decoding code. --- src/common/pixelformat.cpp | 10 +-- src/modules/graphics/GraphicsReadback.cpp | 4 +- src/modules/graphics/GraphicsReadback.h | 1 + src/modules/graphics/Texture.cpp | 6 +- src/modules/image/CompressedImageData.cpp | 18 ++++-- src/modules/image/CompressedImageData.h | 4 +- src/modules/image/CompressedSlice.cpp | 2 - src/modules/image/CompressedSlice.h | 2 - src/modules/image/FormatHandler.cpp | 2 +- src/modules/image/FormatHandler.h | 3 +- src/modules/image/ImageData.cpp | 9 ++- src/modules/image/ImageData.h | 3 +- src/modules/image/ImageDataBase.cpp | 11 ++++ src/modules/image/ImageDataBase.h | 5 +- src/modules/image/magpie/ASTCHandler.cpp | 4 +- src/modules/image/magpie/ASTCHandler.h | 2 +- src/modules/image/magpie/KTXHandler.cpp | 56 ++++++++--------- src/modules/image/magpie/KTXHandler.h | 2 +- src/modules/image/magpie/PKMHandler.cpp | 4 +- src/modules/image/magpie/PKMHandler.h | 2 +- src/modules/image/magpie/PVRHandler.cpp | 7 ++- src/modules/image/magpie/PVRHandler.h | 2 +- src/modules/image/magpie/ddsHandler.cpp | 61 +++++++++++-------- src/modules/image/magpie/ddsHandler.h | 2 +- .../image/wrap_CompressedImageData.cpp | 16 +++++ src/modules/image/wrap_ImageData.cpp | 16 +++++ 26 files changed, 149 insertions(+), 105 deletions(-) diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index 42325510f..ce8a3a690 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -364,11 +364,8 @@ PixelFormat getSRGBPixelFormat(PixelFormat format) case PIXELFORMAT_ASTC_10x10_UNORM: return PIXELFORMAT_ASTC_10x10_sRGB; case PIXELFORMAT_ASTC_12x10_UNORM: return PIXELFORMAT_ASTC_12x10_sRGB; case PIXELFORMAT_ASTC_12x12_UNORM: return PIXELFORMAT_ASTC_12x12_sRGB; - default: - break; + default: return format; } - - return format; } PixelFormat getLinearPixelFormat(PixelFormat format) @@ -398,11 +395,8 @@ PixelFormat getLinearPixelFormat(PixelFormat format) case PIXELFORMAT_ASTC_10x10_sRGB: return PIXELFORMAT_ASTC_10x10_UNORM; case PIXELFORMAT_ASTC_12x10_sRGB: return PIXELFORMAT_ASTC_12x10_UNORM; case PIXELFORMAT_ASTC_12x12_sRGB: return PIXELFORMAT_ASTC_12x12_UNORM; - default: - break; + default: return format; } - - return format; } size_t getPixelFormatBlockSize(PixelFormat format) diff --git a/src/modules/graphics/GraphicsReadback.cpp b/src/modules/graphics/GraphicsReadback.cpp index 935499ab5..0289bddf7 100644 --- a/src/modules/graphics/GraphicsReadback.cpp +++ b/src/modules/graphics/GraphicsReadback.cpp @@ -81,6 +81,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture } textureFormat = getLinearPixelFormat(texture->getPixelFormat()); + isFormatLinear = isGammaCorrect() && !isPixelFormatSRGB(texture->getPixelFormat()); if (!image::ImageData::validPixelFormat(textureFormat)) { @@ -96,7 +97,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture if (isRT && !caps.features[Graphics::FEATURE_COPY_RENDER_TARGET_TO_BUFFER]) throw love::Exception("readbackTextureAsync is not supported on this system."); else if (!isRT && !caps.features[Graphics::FEATURE_COPY_TEXTURE_TO_BUFFER]) - throw love::Exception("readbackTextureAsync a with non-render-target textures is not supported on this system."); + throw love::Exception("readbackTextureAsync with a non-render-target texture is not supported on this system."); } else { @@ -158,6 +159,7 @@ void *GraphicsReadback::prepareReadbackDest(size_t size) throw love::Exception("The love.image module must be loaded for readbackTexture."); imageData.set(module->newImageData(rect.w, rect.h, textureFormat, nullptr), Acquire::NORETAIN); + imageData->setLinear(isFormatLinear); return imageData->getData(); } } diff --git a/src/modules/graphics/GraphicsReadback.h b/src/modules/graphics/GraphicsReadback.h index 0524d4c2b..8990314d3 100644 --- a/src/modules/graphics/GraphicsReadback.h +++ b/src/modules/graphics/GraphicsReadback.h @@ -103,6 +103,7 @@ protected: StrongRef imageData; Rect rect = {}; PixelFormat textureFormat = PIXELFORMAT_UNKNOWN; + bool isFormatLinear = false; int imageDataX = 0; int imageDataY = 0; diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index 4d0e59fcf..2071ce6f1 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -203,7 +203,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) love::image::ImageDataBase *slice = slices->get(0, 0); format = slice->getFormat(); - if (isGammaCorrect() && !settings.linear) + if (isGammaCorrect() && !slice->isLinear()) format = getSRGBPixelFormat(format); pixelWidth = slice->getWidth(); @@ -886,6 +886,7 @@ bool Texture::Slices::validate() const int w = firstdata->getWidth(); int h = firstdata->getHeight(); PixelFormat format = firstdata->getFormat(); + bool linear = firstdata->isLinear(); if (textureType == TEXTURE_CUBE && w != h) throw love::Exception("Cube textures must have equal widths and heights for each cube face."); @@ -925,6 +926,9 @@ bool Texture::Slices::validate() const if (format != slicedata->getFormat()) throw love::Exception("All texture slices and mipmaps must have the same pixel format."); + + if (linear != slicedata->isLinear()) + throw love::Exception("All texture slices and mipmaps must have the same linear setting."); } mipw = std::max(mipw / 2, 1); diff --git a/src/modules/image/CompressedImageData.cpp b/src/modules/image/CompressedImageData.cpp index 0ff04cb5d..724367a12 100644 --- a/src/modules/image/CompressedImageData.cpp +++ b/src/modules/image/CompressedImageData.cpp @@ -30,7 +30,6 @@ love::Type CompressedImageData::type("CompressedImageData", &Data::type); CompressedImageData::CompressedImageData(const std::list &formats, Data *filedata) : format(PIXELFORMAT_UNKNOWN) - , sRGB(false) { FormatHandler *parser = nullptr; @@ -46,7 +45,7 @@ CompressedImageData::CompressedImageData(const std::list &forma if (parser == nullptr) throw love::Exception("Could not parse compressed data: Unknown format."); - memory = parser->parseCompressed(filedata, dataImages, format, sRGB); + memory = parser->parseCompressed(filedata, dataImages, format); if (memory == nullptr) throw love::Exception("Could not parse compressed data."); @@ -56,11 +55,14 @@ CompressedImageData::CompressedImageData(const std::list &forma if (dataImages.size() == 0 || memory->getSize() == 0) throw love::Exception("Could not parse compressed data: No valid data?"); + + // This throws away some information the decoder could give us, but we + // can't really rely on it I think... + format = getLinearPixelFormat(format); } CompressedImageData::CompressedImageData(const CompressedImageData &c) : format(c.format) - , sRGB(c.sRGB) { memory.set(c.memory->clone(), Acquire::NORETAIN); @@ -134,9 +136,15 @@ PixelFormat CompressedImageData::getFormat() const return format; } -bool CompressedImageData::isSRGB() const +void CompressedImageData::setLinear(bool linear) { - return sRGB; + for (auto &slice : dataImages) + slice->setLinear(linear); +} + +bool CompressedImageData::isLinear() const +{ + return dataImages.empty() ? false : dataImages[0]->isLinear(); } CompressedSlice *CompressedImageData::getSlice(int slice, int miplevel) const diff --git a/src/modules/image/CompressedImageData.h b/src/modules/image/CompressedImageData.h index e834935b1..70e55cc19 100644 --- a/src/modules/image/CompressedImageData.h +++ b/src/modules/image/CompressedImageData.h @@ -93,14 +93,14 @@ public: **/ PixelFormat getFormat() const; - bool isSRGB() const; + void setLinear(bool linear); + bool isLinear() const; CompressedSlice *getSlice(int slice, int miplevel) const; protected: PixelFormat format; - bool sRGB; // Single block of memory containing all of the sub-images. StrongRef memory; diff --git a/src/modules/image/CompressedSlice.cpp b/src/modules/image/CompressedSlice.cpp index a4ab37d6f..f2116a1d9 100644 --- a/src/modules/image/CompressedSlice.cpp +++ b/src/modules/image/CompressedSlice.cpp @@ -31,7 +31,6 @@ CompressedSlice::CompressedSlice(PixelFormat format, int width, int height, Byte , memory(memory) , offset(offset) , dataSize(size) - , sRGB(false) { } @@ -40,7 +39,6 @@ CompressedSlice::CompressedSlice(const CompressedSlice &s) , memory(s.memory) , offset(s.offset) , dataSize(s.dataSize) - , sRGB(s.sRGB) { } diff --git a/src/modules/image/CompressedSlice.h b/src/modules/image/CompressedSlice.h index 581641b9c..09d009adc 100644 --- a/src/modules/image/CompressedSlice.h +++ b/src/modules/image/CompressedSlice.h @@ -46,7 +46,6 @@ public: CompressedSlice *clone() const override; void *getData() const override { return (uint8 *) memory->getData() + offset; } size_t getSize() const override { return dataSize; } - bool isSRGB() const override { return sRGB; } size_t getOffset() const { return offset; } private: @@ -54,7 +53,6 @@ private: StrongRef memory; size_t offset; size_t dataSize; - bool sRGB; }; // CompressedSlice diff --git a/src/modules/image/FormatHandler.cpp b/src/modules/image/FormatHandler.cpp index b75b9a226..692d38e70 100644 --- a/src/modules/image/FormatHandler.cpp +++ b/src/modules/image/FormatHandler.cpp @@ -60,7 +60,7 @@ bool FormatHandler::canParseCompressed(Data* /*data*/) return false; } -StrongRef FormatHandler::parseCompressed(Data* /*filedata*/, std::vector>& /*images*/, PixelFormat& /*format*/, bool& /*sRGB*/) +StrongRef FormatHandler::parseCompressed(Data* /*filedata*/, std::vector>& /*images*/, PixelFormat& /*format*/) { throw love::Exception("Compressed image parsing is not implemented for this format backend."); } diff --git a/src/modules/image/FormatHandler.h b/src/modules/image/FormatHandler.h index 9fc6cab16..762905f82 100644 --- a/src/modules/image/FormatHandler.h +++ b/src/modules/image/FormatHandler.h @@ -106,13 +106,12 @@ public: * @param[out] images The list of sub-images generated. Byte data is a * pointer to the returned data. * @param[out] format The format of the Compressed Data. - * @param[out] sRGB Whether the texture is sRGB-encoded. * * @return The single block of memory containing the parsed images. **/ virtual StrongRef parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB); + PixelFormat &format); /** * Frees raw pixel memory allocated by the format handler. diff --git a/src/modules/image/ImageData.cpp b/src/modules/image/ImageData.cpp index 108a945ae..377569cc3 100644 --- a/src/modules/image/ImageData.cpp +++ b/src/modules/image/ImageData.cpp @@ -152,6 +152,10 @@ void ImageData::decode(Data *data) else delete[] this->data; + // This throws away some information the decoder could give us, but we + // can't really rely on it I think... + decodedimage.format = getLinearPixelFormat(decodedimage.format); + this->width = decodedimage.width; this->height = decodedimage.height; this->data = decodedimage.data; @@ -247,11 +251,6 @@ void *ImageData::getData() const return data; } -bool ImageData::isSRGB() const -{ - return false; -} - bool ImageData::inside(int x, int y) const { return x >= 0 && x < getWidth() && y >= 0 && y < getHeight(); diff --git a/src/modules/image/ImageData.h b/src/modules/image/ImageData.h index fa43a848c..c0fad8dba 100644 --- a/src/modules/image/ImageData.h +++ b/src/modules/image/ImageData.h @@ -62,7 +62,7 @@ public: static love::Type type; ImageData(Data *data); - ImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8_UNORM); + ImageData(int width, int height, PixelFormat format); ImageData(int width, int height, PixelFormat format, void *data, bool own); ImageData(const ImageData &c); virtual ~ImageData(); @@ -116,7 +116,6 @@ public: ImageData *clone() const override; void *getData() const override; size_t getSize() const override; - bool isSRGB() const override; size_t getPixelSize() const; diff --git a/src/modules/image/ImageDataBase.cpp b/src/modules/image/ImageDataBase.cpp index 1e7248c9c..56b698757 100644 --- a/src/modules/image/ImageDataBase.cpp +++ b/src/modules/image/ImageDataBase.cpp @@ -29,6 +29,7 @@ ImageDataBase::ImageDataBase(PixelFormat format, int width, int height) : format(format) , width(width) , height(height) + , linear(false) { } @@ -47,5 +48,15 @@ int ImageDataBase::getHeight() const return height; } +void ImageDataBase::setLinear(bool linear) +{ + this->linear = linear; +} + +bool ImageDataBase::isLinear() const +{ + return linear; +} + } // image } // love diff --git a/src/modules/image/ImageDataBase.h b/src/modules/image/ImageDataBase.h index 0f4f523ee..237f9872f 100644 --- a/src/modules/image/ImageDataBase.h +++ b/src/modules/image/ImageDataBase.h @@ -40,7 +40,8 @@ public: int getWidth() const; int getHeight() const; - virtual bool isSRGB() const = 0; + void setLinear(bool linear); + bool isLinear() const; protected: @@ -50,6 +51,8 @@ protected: int width; int height; + bool linear; + }; // ImageDataBase } // image diff --git a/src/modules/image/magpie/ASTCHandler.cpp b/src/modules/image/magpie/ASTCHandler.cpp index fb9a395c2..1f56d6d3f 100644 --- a/src/modules/image/magpie/ASTCHandler.cpp +++ b/src/modules/image/magpie/ASTCHandler.cpp @@ -105,7 +105,7 @@ bool ASTCHandler::canParseCompressed(Data *data) return true; } -StrongRef ASTCHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef ASTCHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not an .astc file?)"); @@ -138,8 +138,6 @@ StrongRef ASTCHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // ASTCHandler diff --git a/src/modules/image/magpie/KTXHandler.cpp b/src/modules/image/magpie/KTXHandler.cpp index 758642b68..37313735c 100644 --- a/src/modules/image/magpie/KTXHandler.cpp +++ b/src/modules/image/magpie/KTXHandler.cpp @@ -137,10 +137,8 @@ enum KTXGLInternalFormat KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD }; -PixelFormat convertFormat(uint32 glformat, bool &sRGB) +PixelFormat convertFormat(uint32 glformat) { - sRGB = false; - // hnnngg ASTC... switch (glformat) @@ -160,18 +158,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) case KTX_GL_COMPRESSED_RGB8_ETC2: return PIXELFORMAT_ETC2_RGB_UNORM; case KTX_GL_COMPRESSED_SRGB8_ETC2: - sRGB = true; - return PIXELFORMAT_ETC2_RGB_UNORM; + return PIXELFORMAT_ETC2_RGB_sRGB; case KTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return PIXELFORMAT_ETC2_RGBA1_UNORM; case KTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - sRGB = true; - return PIXELFORMAT_ETC2_RGBA1_UNORM; + return PIXELFORMAT_ETC2_RGBA1_sRGB; case KTX_GL_COMPRESSED_RGBA8_ETC2_EAC: return PIXELFORMAT_ETC2_RGBA_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - sRGB = true; - return PIXELFORMAT_ETC2_RGBA_UNORM; + return PIXELFORMAT_ETC2_RGBA_sRGB; // PVRTC. case KTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: @@ -185,15 +180,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) // DXT. case KTX_GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - sRGB = true; + return PIXELFORMAT_DXT1_sRGB; case KTX_GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return PIXELFORMAT_DXT1_UNORM; case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - sRGB = true; + return PIXELFORMAT_DXT3_sRGB; case KTX_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return PIXELFORMAT_DXT3_UNORM; case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - sRGB = true; + return PIXELFORMAT_DXT5_sRGB; case KTX_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return PIXELFORMAT_DXT5_UNORM; @@ -209,7 +204,7 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) // BC6 and BC7. case KTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: - sRGB = true; + return PIXELFORMAT_BC7_sRGB; case KTX_GL_COMPRESSED_RGBA_BPTC_UNORM: return PIXELFORMAT_BC7_UNORM; case KTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: @@ -219,59 +214,59 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB) // ASTC. case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_4x4_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_4x4_KHR: return PIXELFORMAT_ASTC_4x4_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_5x4_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_5x4_KHR: return PIXELFORMAT_ASTC_5x4_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_5x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_5x5_KHR: return PIXELFORMAT_ASTC_5x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_6x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_6x5_KHR: return PIXELFORMAT_ASTC_6x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_6x6_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_6x6_KHR: return PIXELFORMAT_ASTC_6x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_8x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_8x5_KHR: return PIXELFORMAT_ASTC_8x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_8x6_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_8x6_KHR: return PIXELFORMAT_ASTC_8x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_8x8_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_8x8_KHR: return PIXELFORMAT_ASTC_8x8_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x5_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x5_KHR: return PIXELFORMAT_ASTC_10x5_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x6_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x6_KHR: return PIXELFORMAT_ASTC_10x6_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x8_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x8_KHR: return PIXELFORMAT_ASTC_10x8_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_10x10_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_10x10_KHR: return PIXELFORMAT_ASTC_10x10_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_12x10_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_12x10_KHR: return PIXELFORMAT_ASTC_12x10_UNORM; case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: - sRGB = true; + return PIXELFORMAT_ASTC_12x12_sRGB; case KTX_GL_COMPRESSED_RGBA_ASTC_12x12_KHR: return PIXELFORMAT_ASTC_12x12_UNORM; default: @@ -298,7 +293,7 @@ bool KTXHandler::canParseCompressed(Data *data) return true; } -StrongRef KTXHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef KTXHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not a KTX file?)"); @@ -314,8 +309,7 @@ StrongRef KTXHandler::parseCompressed(Data *filedata, std::vector KTXHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // KTXHandler diff --git a/src/modules/image/magpie/PKMHandler.cpp b/src/modules/image/magpie/PKMHandler.cpp index 1fa13283f..746265aa3 100644 --- a/src/modules/image/magpie/PKMHandler.cpp +++ b/src/modules/image/magpie/PKMHandler.cpp @@ -114,7 +114,7 @@ bool PKMHandler::canParseCompressed(Data *data) return true; } -StrongRef PKMHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef PKMHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not a PKM file?)"); @@ -148,8 +148,6 @@ StrongRef PKMHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // PKMHandler diff --git a/src/modules/image/magpie/PVRHandler.cpp b/src/modules/image/magpie/PVRHandler.cpp index 1259536ca..f30f01b8b 100644 --- a/src/modules/image/magpie/PVRHandler.cpp +++ b/src/modules/image/magpie/PVRHandler.cpp @@ -475,7 +475,7 @@ bool PVRHandler::canParseCompressed(Data *data) return false; } -StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!canParseCompressed(filedata)) throw love::Exception("Could not decode compressed data (not a PVR file?)"); @@ -510,6 +510,9 @@ StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector PVRHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // PVRHandler diff --git a/src/modules/image/magpie/ddsHandler.cpp b/src/modules/image/magpie/ddsHandler.cpp index 974dec24e..cfe903b1d 100644 --- a/src/modules/image/magpie/ddsHandler.cpp +++ b/src/modules/image/magpie/ddsHandler.cpp @@ -32,13 +32,10 @@ namespace image namespace magpie { -static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, bool &bgra) +static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat) { using namespace dds::dxinfo; - sRGB = false; - bgra = false; - switch (dxformat) { case DXGI_FORMAT_R32G32B32A32_TYPELESS: @@ -65,9 +62,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b case DXGI_FORMAT_R8G8B8A8_TYPELESS: case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); return PIXELFORMAT_RGBA8_UNORM; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return PIXELFORMAT_RGBA8_sRGB; case DXGI_FORMAT_R16G16_TYPELESS: case DXGI_FORMAT_R16G16_FLOAT: @@ -98,21 +95,21 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b case DXGI_FORMAT_BC1_TYPELESS: case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_BC1_UNORM_SRGB); return PIXELFORMAT_DXT1_UNORM; + case DXGI_FORMAT_BC1_UNORM_SRGB: + return PIXELFORMAT_DXT1_sRGB; case DXGI_FORMAT_BC2_TYPELESS: case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_BC2_UNORM_SRGB); return PIXELFORMAT_DXT3_UNORM; + case DXGI_FORMAT_BC2_UNORM_SRGB: + return PIXELFORMAT_DXT3_sRGB; case DXGI_FORMAT_BC3_TYPELESS: case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_BC3_UNORM_SRGB); return PIXELFORMAT_DXT5_UNORM; + case DXGI_FORMAT_BC3_UNORM_SRGB: + return PIXELFORMAT_DXT5_sRGB; case DXGI_FORMAT_BC4_TYPELESS: case DXGI_FORMAT_BC4_UNORM: @@ -136,10 +133,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b case DXGI_FORMAT_B8G8R8A8_UNORM: case DXGI_FORMAT_B8G8R8A8_TYPELESS: + return PIXELFORMAT_BGRA8_UNORM; case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB); - bgra = true; - return PIXELFORMAT_RGBA8_UNORM; + return PIXELFORMAT_BGRA8_sRGB; case DXGI_FORMAT_BC6H_TYPELESS: case DXGI_FORMAT_BC6H_UF16: @@ -150,9 +146,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b case DXGI_FORMAT_BC7_TYPELESS: case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - sRGB = (dxformat == DXGI_FORMAT_BC7_UNORM_SRGB); return PIXELFORMAT_BC7_UNORM; + case DXGI_FORMAT_BC7_UNORM_SRGB: + return PIXELFORMAT_BC7_sRGB; default: return PIXELFORMAT_UNKNOWN; @@ -164,9 +160,13 @@ bool DDSHandler::canDecode(Data *data) using namespace dds::dxinfo; DXGIFormat dxformat = dds::getDDSPixelFormat(data->getData(), data->getSize()); - bool isSRGB = false; - bool bgra = false; - PixelFormat format = convertFormat(dxformat, isSRGB, bgra); + PixelFormat format = convertFormat(dxformat); + + // We convert BGRA to RGBA + if (format == PIXELFORMAT_BGRA8_UNORM) + format = PIXELFORMAT_RGBA8_UNORM; + else if (format == PIXELFORMAT_BGRA8_sRGB) + format = PIXELFORMAT_RGBA8_sRGB; return ImageData::validPixelFormat(format); } @@ -177,9 +177,19 @@ FormatHandler::DecodedImage DDSHandler::decode(Data *data) dds::Parser parser(data->getData(), data->getSize()); - bool isSRGB = false; + img.format = convertFormat(parser.getFormat()); + bool bgra = false; - img.format = convertFormat(parser.getFormat(), isSRGB, bgra); + if (img.format == PIXELFORMAT_BGRA8_UNORM) + { + img.format = PIXELFORMAT_RGBA8_UNORM; + bgra = true; + } + else if (img.format == PIXELFORMAT_BGRA8_sRGB) + { + img.format = PIXELFORMAT_RGBA8_sRGB; + bgra = true; + } if (!ImageData::validPixelFormat(img.format)) throw love::Exception("Could not parse DDS pixel data: Unsupported format."); @@ -229,14 +239,12 @@ bool DDSHandler::canParseCompressed(Data *data) return dds::isCompressedDDS(data->getData(), data->getSize()); } -StrongRef DDSHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format, bool &sRGB) +StrongRef DDSHandler::parseCompressed(Data *filedata, std::vector> &images, PixelFormat &format) { if (!dds::isCompressedDDS(filedata->getData(), filedata->getSize())) throw love::Exception("Could not decode compressed data (not a DDS file?)"); PixelFormat texformat = PIXELFORMAT_UNKNOWN; - bool isSRGB = false; - bool bgra = false; size_t dataSize = 0; @@ -245,7 +253,7 @@ StrongRef DDSHandler::parseCompressed(Data *filedata, std::vectorgetData(), filedata->getSize()); - texformat = convertFormat(parser.getFormat(), isSRGB, bgra); + texformat = convertFormat(parser.getFormat()); if (texformat == PIXELFORMAT_UNKNOWN) throw love::Exception("Could not parse compressed data: Unsupported format."); @@ -280,7 +288,6 @@ StrongRef DDSHandler::parseCompressed(Data *filedata, std::vector parseCompressed(Data *filedata, std::vector> &images, - PixelFormat &format, bool &sRGB) override; + PixelFormat &format) override; }; // DDSHandler diff --git a/src/modules/image/wrap_CompressedImageData.cpp b/src/modules/image/wrap_CompressedImageData.cpp index 15f8908e2..ee8655326 100644 --- a/src/modules/image/wrap_CompressedImageData.cpp +++ b/src/modules/image/wrap_CompressedImageData.cpp @@ -103,6 +103,20 @@ int w_CompressedImageData_getFormat(lua_State *L) return 1; } +int w_CompressedImageData_setLinear(lua_State *L) +{ + CompressedImageData *t = luax_checkcompressedimagedata(L, 1); + t->setLinear(luax_checkboolean(L, 2)); + return 0; +} + +int w_CompressedImageData_isLinear(lua_State *L) +{ + CompressedImageData *t = luax_checkcompressedimagedata(L, 1); + luax_pushboolean(L, t->isLinear()); + return 1; +} + static const luaL_Reg w_CompressedImageData_functions[] = { { "clone", w_CompressedImageData_clone }, @@ -111,6 +125,8 @@ static const luaL_Reg w_CompressedImageData_functions[] = { "getDimensions", w_CompressedImageData_getDimensions }, { "getMipmapCount", w_CompressedImageData_getMipmapCount }, { "getFormat", w_CompressedImageData_getFormat }, + { "setLinear", w_CompressedImageData_setLinear }, + { "isLinear", w_CompressedImageData_isLinear }, { 0, 0 }, }; diff --git a/src/modules/image/wrap_ImageData.cpp b/src/modules/image/wrap_ImageData.cpp index 754ad01c5..e717a0fb3 100644 --- a/src/modules/image/wrap_ImageData.cpp +++ b/src/modules/image/wrap_ImageData.cpp @@ -66,6 +66,20 @@ int w_ImageData_getFormat(lua_State *L) return 1; } +int w_ImageData_setLinear(lua_State *L) +{ + ImageData *t = luax_checkimagedata(L, 1); + t->setLinear(luax_checkboolean(L, 2)); + return 0; +} + +int w_ImageData_isLinear(lua_State *L) +{ + ImageData *t = luax_checkimagedata(L, 1); + luax_pushboolean(L, t->isLinear()); + return 1; +} + int w_ImageData_getWidth(lua_State *L) { ImageData *t = luax_checkimagedata(L, 1); @@ -314,6 +328,8 @@ static const luaL_Reg w_ImageData_functions[] = { { "clone", w_ImageData_clone }, { "getFormat", w_ImageData_getFormat }, + { "setLinear", w_ImageData_setLinear }, + { "isLinear", w_ImageData_isLinear }, { "getWidth", w_ImageData_getWidth }, { "getHeight", w_ImageData_getHeight }, { "getDimensions", w_ImageData_getDimensions }, From 5a0a6a1a27dec0fbd429c98a8c4b11989fb0b719 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Fri, 20 Oct 2023 20:19:30 -0300 Subject: [PATCH 066/409] All constructors for making a TrueType font take an optional settings table. This supersedes the existing optional hinting and dpi scale parameters. The table's fields are: { hinting = "normal", dpiscale = 1, -- nil will default to the current window DPI scale. } --- src/common/Optional.h | 2 +- src/modules/font/Font.cpp | 16 +--- src/modules/font/Font.h | 7 +- src/modules/font/TrueTypeRasterizer.h | 7 ++ src/modules/font/freetype/Font.cpp | 15 ++-- src/modules/font/freetype/Font.h | 3 +- .../font/freetype/TrueTypeRasterizer.cpp | 8 +- .../font/freetype/TrueTypeRasterizer.h | 2 +- src/modules/font/wrap_Font.cpp | 81 ++++++++++++------- src/modules/graphics/Deprecations.cpp | 6 +- src/modules/graphics/Graphics.cpp | 9 ++- src/modules/graphics/Graphics.h | 2 +- 12 files changed, 84 insertions(+), 74 deletions(-) diff --git a/src/common/Optional.h b/src/common/Optional.h index fe3b4b2ef..d0fc11ea9 100644 --- a/src/common/Optional.h +++ b/src/common/Optional.h @@ -46,7 +46,7 @@ struct Optional hasValue = true; } - T get(T defaultVal) + T get(T defaultVal) const { return hasValue ? value : defaultVal; } diff --git a/src/modules/font/Font.cpp b/src/modules/font/Font.cpp index 818e3facf..f3f85bfa5 100644 --- a/src/modules/font/Font.cpp +++ b/src/modules/font/Font.cpp @@ -45,14 +45,9 @@ Font::Font() defaultFontData.set(new data::ByteData(fontdata, rawsize, true), Acquire::NORETAIN); } -Rasterizer *Font::newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting) +Rasterizer *Font::newTrueTypeRasterizer(int size, const TrueTypeRasterizer::Settings &settings) { - return newTrueTypeRasterizer(defaultFontData.get(), size, hinting); -} - -Rasterizer *Font::newTrueTypeRasterizer(int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) -{ - return newTrueTypeRasterizer(defaultFontData.get(), size, dpiscale, hinting); + return newTrueTypeRasterizer(defaultFontData.get(), size, settings); } Rasterizer *Font::newBMFontRasterizer(love::filesystem::FileData *fontdef, const std::vector &images, float dpiscale) @@ -78,12 +73,7 @@ Rasterizer *Font::newImageRasterizer(love::image::ImageData *data, const std::st throw love::Exception("UTF-8 decoding error: %s", e.what()); } - return newImageRasterizer(data, &glyphs[0], (int) glyphs.size(), extraspacing, dpiscale); -} - -Rasterizer *Font::newImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int numglyphs, int extraspacing, float dpiscale) -{ - return new ImageRasterizer(data, glyphs, numglyphs, extraspacing, dpiscale); + return new ImageRasterizer(data, glyphs.data(), (int) glyphs.size(), extraspacing, dpiscale); } GlyphData *Font::newGlyphData(Rasterizer *r, const std::string &text) diff --git a/src/modules/font/Font.h b/src/modules/font/Font.h index ed01557df..3b217a33a 100644 --- a/src/modules/font/Font.h +++ b/src/modules/font/Font.h @@ -48,15 +48,12 @@ public: virtual Rasterizer *newRasterizer(love::filesystem::FileData *data) = 0; - virtual Rasterizer *newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting); - virtual Rasterizer *newTrueTypeRasterizer(int size, float dpiscale, TrueTypeRasterizer::Hinting hinting); - virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) = 0; - virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) = 0; + Rasterizer *newTrueTypeRasterizer(int size, const TrueTypeRasterizer::Settings &settings); + virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const TrueTypeRasterizer::Settings &settings) = 0; virtual Rasterizer *newBMFontRasterizer(love::filesystem::FileData *fontdef, const std::vector &images, float dpiscale); virtual Rasterizer *newImageRasterizer(love::image::ImageData *data, const std::string &glyphs, int extraspacing, float dpiscale); - virtual Rasterizer *newImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int length, int extraspacing, float dpiscale); virtual GlyphData *newGlyphData(Rasterizer *r, const std::string &glyph); virtual GlyphData *newGlyphData(Rasterizer *r, uint32 glyph); diff --git a/src/modules/font/TrueTypeRasterizer.h b/src/modules/font/TrueTypeRasterizer.h index 62b225927..62d7253ab 100644 --- a/src/modules/font/TrueTypeRasterizer.h +++ b/src/modules/font/TrueTypeRasterizer.h @@ -24,6 +24,7 @@ // LOVE #include "Rasterizer.h" #include "common/StringMap.h" +#include "common/Optional.h" namespace love { @@ -44,6 +45,12 @@ public: HINTING_MAX_ENUM }; + struct Settings + { + Hinting hinting = HINTING_NORMAL; + OptionalFloat dpiScale; + }; + virtual ~TrueTypeRasterizer() {} static bool getConstant(const char *in, Hinting &out); diff --git a/src/modules/font/freetype/Font.cpp b/src/modules/font/freetype/Font.cpp index ec7fe9c27..9a52f7b08 100644 --- a/src/modules/font/freetype/Font.cpp +++ b/src/modules/font/freetype/Font.cpp @@ -49,26 +49,21 @@ Font::~Font() Rasterizer *Font::newRasterizer(love::filesystem::FileData *data) { if (TrueTypeRasterizer::accepts(library, data)) - return newTrueTypeRasterizer(data, 12, TrueTypeRasterizer::HINTING_NORMAL); + return newTrueTypeRasterizer(data, 12, font::TrueTypeRasterizer::Settings()); else if (BMFontRasterizer::accepts(data)) return newBMFontRasterizer(data, {}, 1.0f); throw love::Exception("Invalid font file: %s", data->getFilename().c_str()); } -Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) +Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings) { - float dpiscale = 1.0f; + float defaultdpiscale = 1.0f; auto window = Module::getInstance(Module::M_WINDOW); if (window != nullptr) - dpiscale = window->getDPIScale(); + defaultdpiscale = window->getDPIScale(); - return newTrueTypeRasterizer(data, size, dpiscale, hinting); -} - -Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) -{ - return new TrueTypeRasterizer(library, data, size, dpiscale, hinting); + return new TrueTypeRasterizer(library, data, size, settings, defaultdpiscale); } const char *Font::getName() const diff --git a/src/modules/font/freetype/Font.h b/src/modules/font/freetype/Font.h index 8d023cf48..0a4c70e86 100644 --- a/src/modules/font/freetype/Font.h +++ b/src/modules/font/freetype/Font.h @@ -45,8 +45,7 @@ public: // Implements Font Rasterizer *newRasterizer(love::filesystem::FileData *data) override; - Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) override; - Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) override; + Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings) override; // Implement Module const char *getName() const override; diff --git a/src/modules/font/freetype/TrueTypeRasterizer.cpp b/src/modules/font/freetype/TrueTypeRasterizer.cpp index b48f63cb2..1baed329a 100644 --- a/src/modules/font/freetype/TrueTypeRasterizer.cpp +++ b/src/modules/font/freetype/TrueTypeRasterizer.cpp @@ -33,12 +33,12 @@ namespace font namespace freetype { -TrueTypeRasterizer::TrueTypeRasterizer(FT_Library library, love::Data *data, int size, float dpiscale, Hinting hinting) +TrueTypeRasterizer::TrueTypeRasterizer(FT_Library library, love::Data *data, int size, const Settings &settings, float defaultdpiscale) : data(data) - , hinting(hinting) + , hinting(settings.hinting) { - this->dpiScale = dpiscale; - size = floorf(size * dpiscale + 0.5f); + dpiScale = settings.dpiScale.get(defaultdpiscale); + size = floorf(size * dpiScale + 0.5f); if (size <= 0) throw love::Exception("Invalid TrueType font size: %d", size); diff --git a/src/modules/font/freetype/TrueTypeRasterizer.h b/src/modules/font/freetype/TrueTypeRasterizer.h index e97e91967..e26b79646 100644 --- a/src/modules/font/freetype/TrueTypeRasterizer.h +++ b/src/modules/font/freetype/TrueTypeRasterizer.h @@ -44,7 +44,7 @@ class TrueTypeRasterizer : public love::font::TrueTypeRasterizer { public: - TrueTypeRasterizer(FT_Library library, love::Data *data, int size, float dpiscale, Hinting hinting); + TrueTypeRasterizer(FT_Library library, love::Data *data, int size, const Settings &settings, float defaultdpiscale); virtual ~TrueTypeRasterizer(); // Implement Rasterizer diff --git a/src/modules/font/wrap_Font.cpp b/src/modules/font/wrap_Font.cpp index 499583b03..e2ec84f08 100644 --- a/src/modules/font/wrap_Font.cpp +++ b/src/modules/font/wrap_Font.cpp @@ -64,6 +64,42 @@ int w_newRasterizer(lua_State *L) } } +static TrueTypeRasterizer::Settings luax_checktruetypesettings(lua_State* L, int startidx) +{ + TrueTypeRasterizer::Settings s; + + if (lua_type(L, startidx) == LUA_TSTRING) + { + // Legacy parameters. + const char *hintstr = lua_isnoneornil(L, startidx) ? nullptr : luaL_checkstring(L, startidx); + if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, s.hinting)) + luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(s.hinting), hintstr); + + if (!lua_isnoneornil(L, startidx + 1)) + s.dpiScale.set((float)luaL_checknumber(L, startidx + 1)); + } + else + { + luaL_checktype(L, startidx, LUA_TTABLE); + + lua_getfield(L, startidx, "hinting"); + if (!lua_isnoneornil(L, -1)) + { + const char *hintstr = luaL_checkstring(L, -1); + if (!TrueTypeRasterizer::getConstant(hintstr, s.hinting)) + luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(s.hinting), hintstr); + } + lua_pop(L, 1); + + lua_getfield(L, startidx, "dpiscale"); + if (!lua_isnoneornil(L, -1)) + s.dpiScale.set((float)luaL_checknumber(L, -1)); + lua_pop(L, 1); + } + + return s; +} + int w_newTrueTypeRasterizer(lua_State *L) { Rasterizer *t = nullptr; @@ -74,20 +110,20 @@ int w_newTrueTypeRasterizer(lua_State *L) // First argument is a number: use the default TrueType font. int size = (int) luaL_optinteger(L, 1, 13); - const char *hintstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2); - if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting)) - return luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(hinting), hintstr); + TrueTypeRasterizer::Settings settings; + if (!lua_isnoneornil(L, 2)) + settings = luax_checktruetypesettings(L, 2); - if (lua_isnoneornil(L, 3)) - luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, hinting); }); - else - { - float dpiscale = (float) luaL_checknumber(L, 3); - luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, dpiscale, hinting); }); - } + luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, settings); }); } else { + int size = (int) luaL_optinteger(L, 2, 12); + + TrueTypeRasterizer::Settings settings; + if (!lua_isnoneornil(L, 3)) + settings = luax_checktruetypesettings(L, 3); + love::Data *d = nullptr; if (luax_istype(L, 1, love::Data::type)) @@ -98,27 +134,10 @@ int w_newTrueTypeRasterizer(lua_State *L) else d = filesystem::luax_getfiledata(L, 1); - int size = (int) luaL_optinteger(L, 2, 12); - - const char *hintstr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3); - if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting)) - return luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(hinting), hintstr); - - if (lua_isnoneornil(L, 4)) - { - luax_catchexcept(L, - [&]() { t = instance()->newTrueTypeRasterizer(d, size, hinting); }, - [&](bool) { d->release(); } - ); - } - else - { - float dpiscale = (float) luaL_checknumber(L, 4); - luax_catchexcept(L, - [&]() { t = instance()->newTrueTypeRasterizer(d, size, dpiscale, hinting); }, - [&](bool) { d->release(); } - ); - } + luax_catchexcept(L, + [&]() { t = instance()->newTrueTypeRasterizer(d, size, settings); }, + [&](bool) { d->release(); } + ); } luax_pushtype(L, t); diff --git a/src/modules/graphics/Deprecations.cpp b/src/modules/graphics/Deprecations.cpp index 92a5d51c5..6e43a9350 100644 --- a/src/modules/graphics/Deprecations.cpp +++ b/src/modules/graphics/Deprecations.cpp @@ -74,12 +74,12 @@ void Deprecations::draw(Graphics *gfx) if (font.get() == nullptr) { - auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL; + font::TrueTypeRasterizer::Settings settings; if (!isGammaCorrect() && gfx->getScreenDPIScale() <= 1.0) - hinting = font::TrueTypeRasterizer::HINTING_LIGHT; + settings.hinting = font::TrueTypeRasterizer::HINTING_LIGHT; - font.set(gfx->newDefaultFont(9, hinting), Acquire::NORETAIN); + font.set(gfx->newDefaultFont(9, settings), Acquire::NORETAIN); } gfx->flushBatchedDraws(); diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 3d32b727b..4704daabc 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -294,13 +294,13 @@ Font *Graphics::newFont(love::font::Rasterizer *data) return new Font(data, states.back().defaultSamplerState); } -Font *Graphics::newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting) +Font *Graphics::newDefaultFont(int size, const font::TrueTypeRasterizer::Settings &settings) { 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); + StrongRef r(fontmodule->newTrueTypeRasterizer(size, settings), Acquire::NORETAIN); return newFont(r.get()); } @@ -731,7 +731,10 @@ void Graphics::checkSetDefaultFont() // Create a new default font if we don't have one yet. if (!defaultFont.get()) - defaultFont.set(newDefaultFont(13, font::TrueTypeRasterizer::HINTING_NORMAL), Acquire::NORETAIN); + { + font::TrueTypeRasterizer::Settings settings; + defaultFont.set(newDefaultFont(13, settings), Acquire::NORETAIN); + } states.back().font.set(defaultFont.get()); } diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index d2989213d..32ac208b0 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -459,7 +459,7 @@ public: Quad *newQuad(Quad::Viewport v, double sw, double sh); Font *newFont(love::font::Rasterizer *data); - Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting); + Font *newDefaultFont(int size, const font::TrueTypeRasterizer::Settings &settings); Video *newVideo(love::video::VideoStream *stream, float dpiscale); SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferDataUsage usage); From 6aaf0b22bf0ff91fd48c8254de2b9689f8e33e7c Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sat, 21 Oct 2023 13:55:43 -0300 Subject: [PATCH 067/409] Address some compiler warnings --- src/modules/data/wrap_ByteData.cpp | 2 +- src/modules/font/freetype/HarfbuzzShaper.cpp | 12 ++++++------ src/modules/font/freetype/HarfbuzzShaper.h | 2 +- src/modules/font/wrap_Font.cpp | 1 - src/modules/image/magpie/PVRHandler.cpp | 2 +- src/modules/sensor/sdl/Sensor.cpp | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/modules/data/wrap_ByteData.cpp b/src/modules/data/wrap_ByteData.cpp index e299cbae3..57ff5f975 100644 --- a/src/modules/data/wrap_ByteData.cpp +++ b/src/modules/data/wrap_ByteData.cpp @@ -56,7 +56,7 @@ int w_ByteData_setString(lua_State *L) if (size == 0) return 0; - if (offset < 0 || offset + size > (int64) t->getSize()) + if (offset < 0 || offset + (int64) size > (int64) t->getSize()) return luaL_error(L, "The given string offset and size don't fit within the Data's size."); memcpy((char *) t->getData() + (size_t) offset, str, size); diff --git a/src/modules/font/freetype/HarfbuzzShaper.cpp b/src/modules/font/freetype/HarfbuzzShaper.cpp index 70767dada..f7828cecf 100644 --- a/src/modules/font/freetype/HarfbuzzShaper.cpp +++ b/src/modules/font/freetype/HarfbuzzShaper.cpp @@ -153,18 +153,18 @@ void HarfbuzzShaper::computeBufferRanges(const ColoredCodepoints &codepoints, Ra hb_shape(hbFonts[rasti], hbb, nullptr, 0); - int glyphcount = (int)hb_buffer_get_length(hbb); + size_t glyphcount = (size_t)hb_buffer_get_length(hbb); const hb_glyph_info_t *glyphinfos = hb_buffer_get_glyph_infos(hbb, nullptr); hb_direction_t direction = hb_buffer_get_direction(hbb); fallbackranges.clear(); - for (int i = 0; i < glyphcount; i++) + for (size_t i = 0; i < glyphcount; i++) { if (isValidGlyph(glyphinfos[i].codepoint, codepoints.cps, glyphinfos[i].cluster)) { if (bufferranges.empty() || bufferranges.back().index != rasti || bufferranges.back().range.getMax() + 1 != i) - bufferranges.push_back({(int)rasti, (int)glyphinfos[i].cluster, Range(i, 1)}); + bufferranges.push_back({rasti, (int)glyphinfos[i].cluster, Range(i, 1)}); else bufferranges.back().range.last++; } @@ -247,7 +247,7 @@ void HarfbuzzShaper::computeGlyphPositions(const ColoredCodepoints &codepoints, // TODO: this doesn't handle situations where the user inserted a color // change in the middle of some characters that get combined into a single // cluster. - if (colors && colorindex < ncolors && codepoints.colors[colorindex].index == info.cluster) + if (colors && colorindex < ncolors && codepoints.colors[colorindex].index == (int)info.cluster) { colorToAdd.set(codepoints.colors[colorindex].color); colorindex++; @@ -273,7 +273,7 @@ void HarfbuzzShaper::computeGlyphPositions(const ColoredCodepoints &codepoints, continue; // This is a glyph index at this point, despite the name. - GlyphIndex gindex = { (int) info.codepoint, bufferrange.index }; + GlyphIndex gindex = { (int) info.codepoint, (int)bufferrange.index }; if (clustercodepoint == '\t' && isUsingSpacesForTab()) { @@ -390,7 +390,7 @@ int HarfbuzzShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ra if (newwidth > wraplimit) { // If this is the first character, wrap from the next one instead of this one. - int wrapindex = info.cluster > (int) range.first ? info.cluster : (int) range.first + 1; + int wrapindex = (int)info.cluster > (int)range.first ? (int)info.cluster : (int)range.first + 1; // Rewind to after the last seen space when wrapping. if (firstindexafterspace != -1) diff --git a/src/modules/font/freetype/HarfbuzzShaper.h b/src/modules/font/freetype/HarfbuzzShaper.h index 3a71a5b8b..8324b0a7c 100644 --- a/src/modules/font/freetype/HarfbuzzShaper.h +++ b/src/modules/font/freetype/HarfbuzzShaper.h @@ -53,7 +53,7 @@ private: struct BufferRange { - int index; + size_t index; int codepointStart; Range range; }; diff --git a/src/modules/font/wrap_Font.cpp b/src/modules/font/wrap_Font.cpp index e2ec84f08..8a843c413 100644 --- a/src/modules/font/wrap_Font.cpp +++ b/src/modules/font/wrap_Font.cpp @@ -103,7 +103,6 @@ static TrueTypeRasterizer::Settings luax_checktruetypesettings(lua_State* L, int int w_newTrueTypeRasterizer(lua_State *L) { Rasterizer *t = nullptr; - TrueTypeRasterizer::Hinting hinting = TrueTypeRasterizer::HINTING_NORMAL; if (lua_type(L, 1) == LUA_TNUMBER || lua_isnone(L, 1)) { diff --git a/src/modules/image/magpie/PVRHandler.cpp b/src/modules/image/magpie/PVRHandler.cpp index f30f01b8b..ef074f0f8 100644 --- a/src/modules/image/magpie/PVRHandler.cpp +++ b/src/modules/image/magpie/PVRHandler.cpp @@ -511,7 +511,7 @@ StrongRef PVRHandler::parseCompressed(Data *filedata, std::vector Sensor::getHandles() { std::vector nativeSensor; - for (const std::pair &data: sensors) + for (std::pair data : sensors) { if (data.second) nativeSensor.push_back(data.second); From 17362b68441e62fcd75c60b529181c79334a541e Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Mon, 30 Oct 2023 18:55:26 -0300 Subject: [PATCH 068/409] Restore no-parameter variant of love.graphics.setColorMask. --- src/modules/graphics/wrap_Graphics.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index c5b9648ce..27338cdc6 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -2355,7 +2355,11 @@ int w_setColorMask(lua_State *L) { ColorChannelMask mask; - if (lua_gettop(L) <= 1) + if (lua_isnoneornil(L, 1)) + { + mask.r = mask.g = mask.b = mask.a = true; + } + else if (lua_gettop(L) <= 1) { // Set all color components if a single argument is given. mask.r = mask.g = mask.b = mask.a = luax_checkboolean(L, 1); From a3a6e29ef04713ffba0423e73da3910f4ca443d2 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Tue, 7 Nov 2023 20:27:42 -0400 Subject: [PATCH 069/409] Update changelog --- changes.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/changes.txt b/changes.txt index 406fb8d27..ffd39733a 100644 --- a/changes.txt +++ b/changes.txt @@ -3,11 +3,23 @@ LOVE 11.5 [Mysterious Mysteries] Released: N/A +* Fixed inconsistent and buggy behaviour of 'pairs' by updating LuaJIT. +* Fixed "unexpected alignment" errors when running love on some 32 bit Linux systems. +* Fixed running fused games on Windows when the executable has been code-signed. +* Fixed undefined behaviour in love.data.hash's implementation. +* Fixed writing files when a symlink exists in the save directory's path. * Fixed love.threaderror not being called if the error message is an empty string. * Fixed a race condition when a Thread is destroyed immediately after Thread:start. * Fixed unexpectedly slow first frames on macOS. +* Fixed love.joystick.setGamepadMapping when replacing an existing mapping. +* Fixed love.joystick.getGamepadMappingString. +* Fixed duplicate platform fields in love.joystick.saveGamepadMappings. +* Fixed DistanceJoint type information. * Fixed time drift in Source:tell after a Source loops. * Fixed audio not always pausing when the app is minimized on Android. +* Fixed RecordingDevice:start to return false instead of hard-crashing on iOS. +* Fixed identical frames in Ogg Theora videos being skipped. +* Fixed love.font.newBMFontRasterizer's single file parameter variant. * Fixed the original window size not always being restored when exiting fullscreen on Linux. * Fixed some cases of framerate hitches in Windows when vsync is enabled in windowed mode. * Fixed colors appearing over-saturated on P3 displays in macOS. From 658c75b5c3478d1d3e43938371db7fec4f30d611 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 09:47:36 +0000 Subject: [PATCH 070/409] latest from love-test --- .github/workflows/main.yml | 11 + testing/classes/TestMethod.lua | 13 +- testing/classes/TestModule.lua | 2 - testing/classes/TestSuite.lua | 52 +- testing/examples/lovetest_runAllTests.html | 2 +- testing/examples/lovetest_runAllTests.md | 43 +- testing/examples/lovetest_runAllTests.xml | 533 ++++++++++----------- testing/readme.md | 26 +- testing/resources/alsoft.conf | 489 ++++++++++++++++++- testing/tests/audio.lua | 54 +-- testing/tests/graphics.lua | 55 ++- testing/tests/window.lua | 104 ++-- testing/todo.md | 26 - 13 files changed, 930 insertions(+), 480 deletions(-) delete mode 100644 testing/todo.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9ce1d327b..57c697ac4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -311,33 +311,40 @@ jobs: title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl path: testing/output/lovetest_runAllTests.md - name: Zip Test Output (opengl) + if: steps.vars.outputs.arch != 'ARM64' run: | 7z a -tzip test-output-windows-opengl.zip testing/output/ - name: Artifact Test Output (opengl) + if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 with: name: test-output-windows-opengl path: test-output-windows-opengl.zip # windows opengles test - name: Run Tests (opengles) + if: steps.vars.outputs.arch != 'ARM64' run: | $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 powershell.exe ./install/lovec.exe ./testing/main.lua - name: Love Test Report (opengles) + if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: name: Love Testsuite Windows (opengles) title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles path: testing/output/lovetest_runAllTests.md - name: Zip Test Output (opengles) + if: steps.vars.outputs.arch != 'ARM64' run: | 7z a -tzip test-output-windows-opengles.zip testing/output/ - name: Artifact Test Output (opengles) + if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 with: name: test-output-windows-opengles path: test-output-windows-opengles.zip - name: Install Vulkan + if: steps.vars.outputs.arch != 'ARM64' run: | curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma @@ -350,19 +357,23 @@ jobs: powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary # windows vulkan tests - name: Run Tests (vulkan) + if: steps.vars.outputs.arch != 'ARM64' run: | $ENV:LOVE_GRAPHICS_DEBUG=1 powershell.exe ./install/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan - name: Love Test Report (vulkan) + if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: name: Love Testsuite Windows (vulkan) title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan path: testing/output/lovetest_runAllTests.md - name: Zip Test Output (vulkan) + if: steps.vars.outputs.arch != 'ARM64' run: | 7z a -tzip test-output-windows-vulkan.zip testing/output - name: Artifact Test Output (vulkan) + if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 with: name: test-output-windows-vulkan diff --git a/testing/classes/TestMethod.lua b/testing/classes/TestMethod.lua index 4c7705693..a89ba2035 100644 --- a/testing/classes/TestMethod.lua +++ b/testing/classes/TestMethod.lua @@ -42,7 +42,8 @@ TestMethod = { imgs = 1, delay = 0, delayed = false, - store = {} + store = {}, + co = nil } setmetatable(test, self) self.__index = self @@ -281,14 +282,8 @@ TestMethod = { end, - -- currently unused - setDelay = function(self, frames) - self.delay = frames - self.delayed = true - love.test.delayed = self - end, - isDelayed = function(self) - return self.delayed + waitFrames = function(self, frames) + for i=1,frames do coroutine.yield() end end, diff --git a/testing/classes/TestModule.lua b/testing/classes/TestModule.lua index dae7d82ed..f66d247ed 100644 --- a/testing/classes/TestModule.lua +++ b/testing/classes/TestModule.lua @@ -10,9 +10,7 @@ TestModule = { -- @return {table} - returns the new Suite object new = function(self, module, method) local testmodule = { - timer = 0, time = 0, - delay = 0.01, spacer = ' ', colors = { PASS = 'green', FAIL = 'red', SKIP = 'grey' diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 4ac04a4be..39c76b472 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -59,9 +59,7 @@ TestSuite = { -- stagger between tests if self.module ~= nil then - self.module.timer = self.module.timer + delta - if self.module.timer >= self.module.delay then - self.module.timer = self.module.timer - self.module.delay + if self.module.start == true then -- work through each test method 1 by 1 @@ -74,43 +72,25 @@ TestSuite = { self.test = TestMethod:new(method, self.module) TextRun:set('love.' .. self.module.module .. '.' .. method) - -- check method exists in love first - if love[self.module.module] == nil then - local tested = 'love.' .. self.module.module .. '.' .. method .. '()' - local matching = string.sub(self.module.spacer, string.len(tested), 40) - self.module:log(self.module.colors['FAIL'], - tested .. matching, - ' ==> FAIL (0/0) - call failed - method does not exist' - ) - -- otherwise run the test method - else - local ok, chunk, err = pcall(self[self.module.module][method], self.test) + self.test.co = coroutine.create(function() + local ok, chunk, err = pcall(love.test[love.test.module.module][method], love.test.test) if ok == false then - self.test.passed = false - self.test.fatal = tostring(chunk) .. tostring(err) + love.test.test.passed = false + love.test.test.fatal = tostring(chunk) .. tostring(err) end - end + end) - -- once we've run check delay + eval + + -- once called we have a corouting, so just call resume every frame + -- until we have finished else - -- @TODO use coroutines? - -- if we have a test method that needs a delay - -- we wait for the delay to run out first - if self.delayed ~= nil then - self.delayed.delay = self.delayed.delay - 1 - -- re-run the test method again when delay ends - -- its up to the test to handle the :isDelayed() property - if self.delayed.delay <= 0 then - local ok, chunk, err = pcall(self[self.module.module][self.delayed.method], self.test) - if ok == false then - self.test.passed = false - self.test.fatal = tostring(chunk) .. tostring(err) - end - self.delayed = nil - end - else + -- move onto next yield if any + -- pauses can be set with TestMethod:waitFrames(frames) + coroutine.resume(self.test.co) + -- when wait finished (or no yields) + if coroutine.status(self.test.co) == 'dead' then -- now we're all done evaluate the test local ok, chunk, err = pcall(self.test.evaluateTest, self.test) if ok == false then @@ -118,11 +98,9 @@ TestSuite = { self.test.fatal = tostring(chunk) .. tostring(err) end -- save having to :release() anything we made in the last test - -- 7251ms > 7543ms collectgarbage("collect") -- move onto the next test self.module.index = self.module.index + 1 - end end @@ -148,7 +126,7 @@ TestSuite = { end end end - end + end, diff --git a/testing/examples/lovetest_runAllTests.html b/testing/examples/lovetest_runAllTests.html index 641d05999..5a0be8304 100644 --- a/testing/examples/lovetest_runAllTests.html +++ b/testing/examples/lovetest_runAllTests.html @@ -1 +1 @@ -

🔴 love.test

  • 🟢 254 Tests
  • 🔴 1 Failures
  • 🟡 50 Skipped
  • 12.195s


🟢 love.audio

  • 🟢 26 Tests
  • 🔴 0 Failures
  • 🟡 2 Skipped
  • 0.473s


    • MethodTimeDetails
      🟡RecordingDevice0.024stest class needs writing
      🟡Source0.017stest class needs writing
      🟢getActiveEffects0.016s
      🟢getActiveSourceCount0.016s
      🟢getDistanceModel0.017s
      🟢getDopplerScale0.016s
      🟢getEffect0.016s
      🟢getMaxSceneEffects0.017s
      🟢getMaxSourceEffects0.015s
      🟢getOrientation0.017s
      🟢getPosition0.017s
      🟢getRecordingDevices0.017s
      🟢getVelocity0.016s
      🟢getVolume0.017s
      🟢isEffectsSupported0.016s
      🟢newQueueableSource0.015s
      🟢newSource0.014s
      🟢pause0.016s
      🟢play0.017s
      🟢setDistanceModel0.019s
      🟢setDopplerScale0.017s
      🟢setEffect0.017s
      🟢setMixWithSystem0.017s
      🟢setOrientation0.017s
      🟢setPosition0.018s
      🟢setVelocity0.017s
      🟢setVolume0.016s
      🟢stop0.018s

      🟢 love.data

      • 🟢 7 Tests
      • 🔴 0 Failures
      • 🟡 5 Skipped
      • 0.212s


        • MethodTimeDetails
          🟡ByteData0.016stest class needs writing
          🟡CompressedData0.017stest class needs writing
          🟢compress0.017s
          🟢decode0.018s
          🟢decompress0.018s
          🟢encode0.019s
          🟡getPackedSize0.019stest class needs writing
          🟢hash0.017s
          🟢newByteData0.017s
          🟢newDataView0.017s
          🟡pack0.018stest class needs writing
          🟡unpack0.018stest class needs writing

          🟢 love.event

          • 🟢 4 Tests
          • 🔴 0 Failures
          • 🟡 2 Skipped
          • 0.108s


            • MethodTimeDetails
              🟢clear0.017s
              🟢poll0.017s
              🟡pump0.019snot sure can be tested as used internally
              🟢push0.018s
              🟢quit0.019s
              🟡wait0.018stest class needs writing

              🟢 love.filesystem

              • 🟢 28 Tests
              • 🔴 0 Failures
              • 🟡 3 Skipped
              • 0.556s


                • MethodTimeDetails
                  🟢File0.017s
                  🟡FileData0.019stest class needs writing
                  🟢append0.019s
                  🟢areSymlinksEnabled0.017s
                  🟢createDirectory0.017s
                  🟢getAppdataDirectory0.018s
                  🟢getCRequirePath0.017s
                  🟢getDirectoryItems0.018s
                  🟢getIdentity0.019s
                  🟢getInfo0.019s
                  🟢getRealDirectory0.018s
                  🟢getRequirePath0.018s
                  🟢getSaveDirectory0.018s
                  🟡getSource0.018snot sure can be tested as used internally
                  🟢getSourceBaseDirectory0.018s
                  🟢getUserDirectory0.019s
                  🟢getWorkingDirectory0.019s
                  🟢isFused0.017s
                  🟢lines0.018s
                  🟢load0.016s
                  🟢mount0.019s
                  🟢newFileData0.018s
                  🟢openFile0.019s
                  🟢read0.017s
                  🟢remove0.018s
                  🟢setCRequirePath0.018s
                  🟢setIdentity0.018s
                  🟢setRequirePath0.018s
                  🟡setSource0.018snot sure can be tested as used internally
                  🟢unmount0.018s
                  🟢write0.019s

                  🟢 love.font

                  • 🟢 4 Tests
                  • 🔴 0 Failures
                  • 🟡 3 Skipped
                  • 0.127s


                    • MethodTimeDetails
                      🟡GlyphData0.017stest class needs writing
                      🟡Rasterizer0.018stest class needs writing
                      🟡newBMFontRasterizer0.018swiki and source dont match, not sure expected usage
                      🟢newGlyphData0.020s
                      🟢newImageRasterizer0.020s
                      🟢newRasterizer0.018s
                      🟢newTrueTypeRasterizer0.017s

                      🔴 love.graphics

                      • 🟢 91 Tests
                      • 🔴 1 Failures
                      • 🟡 15 Skipped
                      • 2.091s


                        • MethodTimeDetails
                          🟡Canvas0.016stest class needs writing
                          🟡Font0.017stest class needs writing
                          🟡Image0.019stest class needs writing
                          🟡Mesh0.019stest class needs writing
                          🟡ParticleSystem0.017stest class needs writing
                          🟡Quad0.019stest class needs writing
                          🟡Shader0.018stest class needs writing
                          🟡SpriteBatch0.018stest class needs writing
                          🟡Text0.018stest class needs writing
                          🟡Texture0.018stest class needs writing
                          🟡Video0.019stest class needs writing
                          🟢applyTransform0.018s

                          Expected

                          Actual

                          🟢arc0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢captureScreenshot0.183s
                          🟢circle0.017s

                          Expected

                          Actual

                          🟢clear0.017s

                          Expected

                          Actual

                          🟡discard0.017scant test this worked
                          🟢draw0.018s

                          Expected

                          Actual

                          🟡drawInstanced0.020stest class needs writing
                          🟢drawLayer0.018s

                          Expected

                          Actual

                          🟢ellipse0.018s

                          Expected

                          Actual

                          🟡flushBatch0.018snot sure can be tested as used internally
                          🟢getBackgroundColor0.018s
                          🟢getBlendMode0.018s
                          🟢getCanvas0.018s
                          🟢getColor0.017s
                          🟢getColorMask0.018s
                          🟢getDPIScale0.019s
                          🟢getDefaultFilter0.018s
                          🟢getDepthMode0.018s
                          🟢getDimensions0.017s
                          🟢getFont0.018s
                          🟢getFrontFaceWinding0.019s
                          🟢getHeight0.017s
                          🟢getLineJoin0.018s
                          🟢getLineStyle0.017s
                          🟢getLineWidth0.019s
                          🟢getMeshCullMode0.018s
                          🟢getPixelDimensions0.018s
                          🟢getPixelHeight0.018s
                          🟢getPixelWidth0.018s
                          🟢getPointSize0.019s
                          🟢getRendererInfo0.018s
                          🟢getScissor0.018s
                          🟢getShader0.018s
                          🟢getStackDepth0.018s
                          🟢getStats0.017s
                          🟢getStencilMode0.018s
                          🟢getSupported0.018s
                          🟢getSystemLimits0.019s
                          🟢getTextureFormats0.020s
                          🟢getTextureTypes0.017s
                          🟢getWidth0.018s
                          🟢intersectScissor0.018s

                          Expected

                          Actual

                          🟢inverseTransformPoint0.018s
                          🟢isActive0.018s
                          🟢isGammaCorrect0.019s
                          🟢isWireframe0.017s
                          🟢line0.016s

                          Expected

                          Actual

                          🟢newArrayImage0.018s
                          🟢newCanvas0.019s
                          🟢newCubeImage0.019s
                          🟢newFont0.019s
                          🟢newImage0.018s
                          🟢newImageFont0.017s
                          🟢newMesh0.018s
                          🟢newParticleSystem0.019s
                          🟢newQuad0.018s
                          🟢newShader0.018s
                          🟢newSpriteBatch0.018s
                          🟢newTextBatch0.017s
                          🟢newVideo0.017s
                          🟢newVolumeImage0.018s
                          🟢origin0.018s

                          Expected

                          Actual

                          🟢points0.018s

                          Expected

                          Actual

                          🟢polygon0.018s

                          Expected

                          Actual

                          🟢pop0.019s

                          Expected

                          Actual

                          🟡present0.018stest class needs writing
                          🟢print0.017s

                          Expected

                          Actual

                          🟢printf0.018s

                          Expected

                          Actual

                          🟢push0.018s

                          Expected

                          Actual

                          🟢rectangle0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢replaceTransform0.018s

                          Expected

                          Actual

                          🟢reset0.019s
                          🟢rotate0.019s

                          Expected

                          Actual

                          🟢scale0.017s
                          🟢setBackgroundColor0.017s
                          🟢setBlendMode0.017s

                          Expected

                          Actual

                          🟢setCanvas0.018s

                          Expected

                          Actual

                          🟢setColor0.018s

                          Expected

                          Actual

                          🔴setColorMask0.018sassert #7 [check pixel b for yellow at 0,0(set color mask)] expected '0' got '1'

                          Expected

                          Actual

                          🟢setDefaultFilter0.018s
                          🟢setDepthMode0.018s
                          🟢setFont0.018s

                          Expected

                          Actual

                          🟢setFrontFaceWinding0.019s
                          🟢setLineJoin0.017s

                          Expected

                          Actual

                          🟢setLineStyle0.018s

                          Expected

                          Actual

                          🟢setLineWidth0.018s

                          Expected

                          Actual

                          🟢setMeshCullMode0.018s
                          🟢setScissor0.018s

                          Expected

                          Actual

                          🟢setShader0.018s

                          Expected

                          Actual

                          🟢setStencilTest0.018s

                          Expected

                          Actual

                          🟢setWireframe0.016s

                          Expected

                          Actual

                          🟢shear0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢transformPoint0.018s
                          🟢translate0.019s

                          Expected

                          Actual

                          🟢validateShader0.019s

                          🟢 love.image

                          • 🟢 3 Tests
                          • 🔴 0 Failures
                          • 🟡 2 Skipped
                          • 0.087s


                            • MethodTimeDetails
                              🟡CompressedImageData0.015stest class needs writing
                              🟡ImageData0.018stest class needs writing
                              🟢isCompressed0.019s
                              🟢newCompressedData0.017s
                              🟢newImageData0.018s

                              🟢 love.math

                              • 🟢 17 Tests
                              • 🔴 0 Failures
                              • 🟡 3 Skipped
                              • 0.358s


                                • MethodTimeDetails
                                  🟡BezierCurve0.016stest class needs writing
                                  🟡RandomGenerator0.018stest class needs writing
                                  🟡Transform0.019stest class needs writing
                                  🟢colorFromBytes0.017s
                                  🟢colorToBytes0.018s
                                  🟢gammaToLinear0.017s
                                  🟢getRandomSeed0.018s
                                  🟢getRandomState0.017s
                                  🟢isConvex0.018s
                                  🟢linearToGamma0.017s
                                  🟢newBezierCurve0.018s
                                  🟢newRandomGenerator0.018s
                                  🟢newTransform0.020s
                                  🟢perlinNoise0.018s
                                  🟢random0.019s
                                  🟢randomNormal0.017s
                                  🟢setRandomSeed0.018s
                                  🟢setRandomState0.018s
                                  🟢simplexNoise0.018s
                                  🟢triangulate0.018s

                                  🟢 love.physics

                                  • 🟢 22 Tests
                                  • 🔴 0 Failures
                                  • 🟡 6 Skipped
                                  • 0.492s


                                    • MethodTimeDetails
                                      🟡Body0.015stest class needs writing
                                      🟡Contact0.017stest class needs writing
                                      🟡Fixture0.017stest class needs writing
                                      🟡Joint0.018stest class needs writing
                                      🟡Shape0.018stest class needs writing
                                      🟡World0.018stest class needs writing
                                      🟢getDistance0.017s
                                      🟢getMeter0.016s
                                      🟢newBody0.017s
                                      🟢newChainShape0.018s
                                      🟢newCircleShape0.019s
                                      🟢newDistanceJoint0.018s
                                      🟢newEdgeShape0.017s
                                      🟢newFixture0.019s
                                      🟢newFrictionJoint0.019s
                                      🟢newGearJoint0.019s
                                      🟢newMotorJoint0.018s
                                      🟢newMouseJoint0.017s
                                      🟢newPolygonShape0.017s
                                      🟢newPrismaticJoint0.017s
                                      🟢newPulleyJoint0.017s
                                      🟢newRectangleShape0.018s
                                      🟢newRevoluteJoint0.017s
                                      🟢newRopeJoint0.018s
                                      🟢newWeldJoint0.019s
                                      🟢newWheelJoint0.016s
                                      🟢newWorld0.018s
                                      🟢setMeter0.018s

                                      🟢 love.sound

                                      • 🟢 2 Tests
                                      • 🔴 0 Failures
                                      • 🟡 2 Skipped
                                      • 0.072s


                                        • MethodTimeDetails
                                          🟡Decoder0.016stest class needs writing
                                          🟡SoundData0.019stest class needs writing
                                          🟢newDecoder0.020s
                                          🟢newSoundData0.017s

                                          🟢 love.system

                                          • 🟢 6 Tests
                                          • 🔴 0 Failures
                                          • 🟡 2 Skipped
                                          • 0.142s


                                            • MethodTimeDetails
                                              🟢getClipboardText0.016s
                                              🟢getOS0.017s
                                              🟢getPowerInfo0.018s
                                              🟢getProcessorCount0.018s
                                              🟢hasBackgroundMusic0.019s
                                              🟡openURL0.018scant test this worked
                                              🟢setClipboardText0.018s
                                              🟡vibrate0.018scant test this worked

                                              🟢 love.thread

                                              • 🟢 3 Tests
                                              • 🔴 0 Failures
                                              • 🟡 2 Skipped
                                              • 0.088s


                                                • MethodTimeDetails
                                                  🟡Channel0.015stest class needs writing
                                                  🟡Thread0.018stest class needs writing
                                                  🟢getChannel0.018s
                                                  🟢newChannel0.019s
                                                  🟢newThread0.018s

                                                  🟢 love.timer

                                                  • 🟢 6 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 0 Skipped
                                                  • 2.086s


                                                    • MethodTimeDetails
                                                      🟢getAverageDelta0.015s
                                                      🟢getDelta0.017s
                                                      🟢getFPS0.018s
                                                      🟢getTime1.008s
                                                      🟢sleep1.011s
                                                      🟢step0.018s

                                                      🟢 love.video

                                                      • 🟢 1 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 1 Skipped
                                                      • 0.031s


                                                        • MethodTimeDetails
                                                          🟡VideoStream0.014stest class needs writing
                                                          🟢newVideoStream0.017s

                                                          🟢 love.window

                                                          • 🟢 34 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 2 Skipped
                                                          • 5.273s


                                                            • MethodTimeDetails
                                                              🟢close0.035s
                                                              🟢fromPixels0.002s
                                                              🟢getDPIScale0.002s
                                                              🟢getDesktopDimensions0.016s
                                                              🟢getDisplayCount0.018s
                                                              🟢getDisplayName0.018s
                                                              🟢getDisplayOrientation0.019s
                                                              🟢getFullscreen1.346s
                                                              🟢getFullscreenModes0.017s
                                                              🟢getIcon0.016s
                                                              🟢getMode0.017s
                                                              🟢getPosition0.017s
                                                              🟢getSafeArea0.017s
                                                              🟢getTitle0.017s
                                                              🟢getVSync0.018s
                                                              🟢hasFocus0.018s
                                                              🟢hasMouseFocus0.018s
                                                              🟢isDisplaySleepEnabled0.018s
                                                              🟢isMaximized0.186s
                                                              🟢isMinimized0.655s
                                                              🟢isOpen0.045s
                                                              🟢isVisible0.032s
                                                              🟢maximize0.172s
                                                              🟢minimize0.637s
                                                              🟡requestAttention0.003scant test this worked
                                                              🟢restore0.650s
                                                              🟢setDisplaySleepEnabled0.012s
                                                              🟢setFullscreen1.122s
                                                              🟢setIcon0.006s
                                                              🟢setMode0.018s
                                                              🟢setPosition0.017s
                                                              🟢setTitle0.018s
                                                              🟢setVSync0.017s
                                                              🟡showMessageBox0.017scant test this worked
                                                              🟢toPixels0.018s
                                                              🟢updateMode0.019s
\ No newline at end of file +

🔴 love.test

  • 🟢 275 Tests
  • 🔴 2 Failures
  • 🟡 28 Skipped
  • 16.781s


🔴 love.audio

  • 🟢 27 Tests
  • 🔴 1 Failures
  • 🟡 0 Skipped
  • 4.898s


    • MethodTimeDetails
      🟢RecordingDevice4.419s
      🔴Source0.019sassert 53 [check effect was applied] expected 'true' got 'false'
      🟢getActiveEffects0.013s
      🟢getActiveSourceCount0.018s
      🟢getDistanceModel0.018s
      🟢getDopplerScale0.019s
      🟢getEffect0.018s
      🟢getMaxSceneEffects0.017s
      🟢getMaxSourceEffects0.016s
      🟢getOrientation0.018s
      🟢getPosition0.017s
      🟢getRecordingDevices0.017s
      🟢getVelocity0.018s
      🟢getVolume0.018s
      🟢isEffectsSupported0.017s
      🟢newQueueableSource0.016s
      🟢newSource0.019s
      🟢pause0.019s
      🟢play0.019s
      🟢setDistanceModel0.019s
      🟢setDopplerScale0.018s
      🟢setEffect0.017s
      🟢setMixWithSystem0.017s
      🟢setOrientation0.019s
      🟢setPosition0.019s
      🟢setVelocity0.018s
      🟢setVolume0.017s
      🟢stop0.019s

      🟢 love.data

      • 🟢 12 Tests
      • 🔴 0 Failures
      • 🟡 0 Skipped
      • 0.213s


        • MethodTimeDetails
          🟢ByteData0.017s
          🟢CompressedData0.017s
          🟢compress0.018s
          🟢decode0.018s
          🟢decompress0.018s
          🟢encode0.018s
          🟢getPackedSize0.018s
          🟢hash0.019s
          🟢newByteData0.017s
          🟢newDataView0.017s
          🟢pack0.017s
          🟢unpack0.018s

          🟢 love.event

          • 🟢 4 Tests
          • 🔴 0 Failures
          • 🟡 2 Skipped
          • 0.103s


            • MethodTimeDetails
              🟢clear0.015s
              🟢poll0.017s
              🟡pump0.018sused internally
              🟢push0.018s
              🟢quit0.018s
              🟡wait0.017stest class needs writing

              🟢 love.filesystem

              • 🟢 29 Tests
              • 🔴 0 Failures
              • 🟡 2 Skipped
              • 0.561s


                • MethodTimeDetails
                  🟢File0.018s
                  🟢FileData0.019s
                  🟢append0.020s
                  🟢areSymlinksEnabled0.017s
                  🟢createDirectory0.019s
                  🟢getAppdataDirectory0.018s
                  🟢getCRequirePath0.017s
                  🟢getDirectoryItems0.018s
                  🟢getIdentity0.018s
                  🟢getInfo0.019s
                  🟢getRealDirectory0.018s
                  🟢getRequirePath0.017s
                  🟢getSaveDirectory0.017s
                  🟡getSource0.016sused internally
                  🟢getSourceBaseDirectory0.018s
                  🟢getUserDirectory0.017s
                  🟢getWorkingDirectory0.018s
                  🟢isFused0.018s
                  🟢lines0.022s
                  🟢load0.017s
                  🟢mount0.018s
                  🟢newFileData0.018s
                  🟢openFile0.018s
                  🟢read0.018s
                  🟢remove0.018s
                  🟢setCRequirePath0.018s
                  🟢setIdentity0.019s
                  🟢setRequirePath0.019s
                  🟡setSource0.017sused internally
                  🟢unmount0.018s
                  🟢write0.019s

                  🔴 love.font

                  • 🟢 6 Tests
                  • 🔴 1 Failures
                  • 🟡 0 Skipped
                  • 0.123s


                    • MethodTimeDetails
                      🔴GlyphData0.017sassert 8 [check glyph number] expected '97' got '0'
                      🟢Rasterizer0.018s
                      🟢newBMFontRasterizer0.018s
                      🟢newGlyphData0.018s
                      🟢newImageRasterizer0.018s
                      🟢newRasterizer0.017s
                      🟢newTrueTypeRasterizer0.019s

                      🟢 love.graphics

                      • 🟢 93 Tests
                      • 🔴 0 Failures
                      • 🟡 14 Skipped
                      • 2.106s


                        • MethodTimeDetails
                          🟡Canvas0.017stest class needs writing
                          🟡Font0.018stest class needs writing
                          🟡Image0.017stest class needs writing
                          🟡Mesh0.017stest class needs writing
                          🟡ParticleSystem0.017stest class needs writing
                          🟡Quad0.017stest class needs writing
                          🟡Shader0.018stest class needs writing
                          🟡SpriteBatch0.018stest class needs writing
                          🟡Text0.018stest class needs writing
                          🟡Texture0.018stest class needs writing
                          🟡Video0.007stest class needs writing
                          🟢applyTransform0.019s

                          Expected

                          Actual

                          🟢arc0.024s

                          Expected

                          Actual

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢captureScreenshot0.184s
                          🟢circle0.021s

                          Expected

                          Actual

                          🟢clear0.018s

                          Expected

                          Actual

                          🟡discard0.016scant test this worked
                          🟢draw0.018s

                          Expected

                          Actual

                          🟡drawInstanced0.018stest class needs writing
                          🟢drawLayer0.020s

                          Expected

                          Actual

                          🟢ellipse0.018s

                          Expected

                          Actual

                          🟢flushBatch0.017s
                          🟢getBackgroundColor0.018s
                          🟢getBlendMode0.018s
                          🟢getCanvas0.019s
                          🟢getColor0.017s
                          🟢getColorMask0.018s
                          🟢getDPIScale0.017s
                          🟢getDefaultFilter0.018s
                          🟢getDepthMode0.017s
                          🟢getDimensions0.018s
                          🟢getFont0.019s
                          🟢getFrontFaceWinding0.017s
                          🟢getHeight0.017s
                          🟢getLineJoin0.017s
                          🟢getLineStyle0.020s
                          🟢getLineWidth0.016s
                          🟢getMeshCullMode0.016s
                          🟢getPixelDimensions0.018s
                          🟢getPixelHeight0.018s
                          🟢getPixelWidth0.018s
                          🟢getPointSize0.016s
                          🟢getRendererInfo0.019s
                          🟢getScissor0.017s
                          🟢getShader0.019s
                          🟢getStackDepth0.018s
                          🟢getStats0.018s
                          🟢getStencilMode0.017s
                          🟢getSupported0.018s
                          🟢getSystemLimits0.018s
                          🟢getTextureFormats0.019s
                          🟢getTextureTypes0.018s
                          🟢getWidth0.017s
                          🟢intersectScissor0.019s

                          Expected

                          Actual

                          🟢inverseTransformPoint0.017s
                          🟢isActive0.017s
                          🟢isGammaCorrect0.018s
                          🟢isWireframe0.018s
                          🟢line0.019s

                          Expected

                          Actual

                          🟢newArrayImage0.019s
                          🟢newCanvas0.015s
                          🟢newCubeImage0.020s
                          🟢newFont0.018s
                          🟢newImage0.017s
                          🟢newImageFont0.019s
                          🟢newMesh0.018s
                          🟢newParticleSystem0.018s
                          🟢newQuad0.017s
                          🟢newShader0.022s
                          🟢newSpriteBatch0.019s
                          🟢newTextBatch0.016s
                          🟢newVideo0.021s
                          🟢newVolumeImage0.019s
                          🟢origin0.018s

                          Expected

                          Actual

                          🟢points0.019s

                          Expected

                          Actual

                          🟢polygon0.016s

                          Expected

                          Actual

                          🟢pop0.019s

                          Expected

                          Actual

                          🟡present0.018stest class needs writing
                          🟢print0.019s

                          Expected

                          Actual

                          🟢printf0.019s

                          Expected

                          Actual

                          🟢push0.021s

                          Expected

                          Actual

                          🟢rectangle0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢replaceTransform0.017s

                          Expected

                          Actual

                          🟢reset0.017s
                          🟢rotate0.020s

                          Expected

                          Actual

                          🟢scale0.020s
                          🟢setBackgroundColor0.017s
                          🟢setBlendMode0.020s

                          Expected

                          Actual

                          🟢setCanvas0.019s

                          Expected

                          Actual

                          🟢setColor0.018s

                          Expected

                          Actual

                          🟢setColorMask0.019s

                          Expected

                          Actual

                          🟢setDefaultFilter0.018s
                          🟢setDepthMode0.018s
                          🟢setFont0.018s

                          Expected

                          Actual

                          🟢setFrontFaceWinding0.018s
                          🟢setLineJoin0.020s

                          Expected

                          Actual

                          🟢setLineStyle0.017s

                          Expected

                          Actual

                          🟢setLineWidth0.018s

                          Expected

                          Actual

                          🟢setMeshCullMode0.018s
                          🟢setScissor0.018s

                          Expected

                          Actual

                          🟢setShader0.024s

                          Expected

                          Actual

                          🟢setStencilTest0.018s

                          Expected

                          Actual

                          🟢setWireframe0.019s

                          Expected

                          Actual

                          🟢shear0.021s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢transformPoint0.016s
                          🟢translate0.020s

                          Expected

                          Actual

                          🟢validateShader0.021s

                          🟢 love.image

                          • 🟢 5 Tests
                          • 🔴 0 Failures
                          • 🟡 0 Skipped
                          • 0.088s


                            • MethodTimeDetails
                              🟢CompressedImageData0.018s
                              🟢ImageData0.018s
                              🟢isCompressed0.017s
                              🟢newCompressedData0.018s
                              🟢newImageData0.018s

                              🟢 love.math

                              • 🟢 20 Tests
                              • 🔴 0 Failures
                              • 🟡 0 Skipped
                              • 0.284s


                                • MethodTimeDetails
                                  🟢BezierCurve0.016s
                                  🟢RandomGenerator0.017s
                                  🟢Transform0.017s
                                  🟢colorFromBytes0.018s
                                  🟢colorToBytes0.018s
                                  🟢gammaToLinear0.017s
                                  🟢getRandomSeed0.017s
                                  🟢getRandomState0.018s
                                  🟢isConvex0.018s
                                  🟢linearToGamma0.018s
                                  🟢newBezierCurve0.018s
                                  🟢newRandomGenerator0.018s
                                  🟢newTransform0.017s
                                  🟢perlinNoise0.019s
                                  🟢random0.012s
                                  🟢randomNormal0.017s
                                  🟢setRandomSeed0.002s
                                  🟢setRandomState0.002s
                                  🟢simplexNoise0.002s
                                  🟢triangulate0.003s

                                  🟢 love.physics

                                  • 🟢 22 Tests
                                  • 🔴 0 Failures
                                  • 🟡 6 Skipped
                                  • 0.059s


                                    • MethodTimeDetails
                                      🟡Body0.002stest class needs writing
                                      🟡Contact0.002stest class needs writing
                                      🟡Fixture0.002stest class needs writing
                                      🟡Joint0.002stest class needs writing
                                      🟡Shape0.002stest class needs writing
                                      🟡World0.002stest class needs writing
                                      🟢getDistance0.002s
                                      🟢getMeter0.002s
                                      🟢newBody0.002s
                                      🟢newChainShape0.002s
                                      🟢newCircleShape0.005s
                                      🟢newDistanceJoint0.002s
                                      🟢newEdgeShape0.002s
                                      🟢newFixture0.002s
                                      🟢newFrictionJoint0.002s
                                      🟢newGearJoint0.002s
                                      🟢newMotorJoint0.002s
                                      🟢newMouseJoint0.002s
                                      🟢newPolygonShape0.002s
                                      🟢newPrismaticJoint0.002s
                                      🟢newPulleyJoint0.002s
                                      🟢newRectangleShape0.002s
                                      🟢newRevoluteJoint0.002s
                                      🟢newRopeJoint0.002s
                                      🟢newWeldJoint0.002s
                                      🟢newWheelJoint0.002s
                                      🟢newWorld0.002s
                                      🟢setMeter0.002s

                                      🟢 love.sound

                                      • 🟢 4 Tests
                                      • 🔴 0 Failures
                                      • 🟡 0 Skipped
                                      • 0.015s


                                        • MethodTimeDetails
                                          🟢Decoder0.007s
                                          🟢SoundData0.003s
                                          🟢newDecoder0.002s
                                          🟢newSoundData0.003s

                                          🟢 love.system

                                          • 🟢 6 Tests
                                          • 🔴 0 Failures
                                          • 🟡 2 Skipped
                                          • 0.023s


                                            • MethodTimeDetails
                                              🟢getClipboardText0.004s
                                              🟢getOS0.007s
                                              🟢getPowerInfo0.002s
                                              🟢getProcessorCount0.002s
                                              🟢hasBackgroundMusic0.002s
                                              🟡openURL0.002scant test this worked
                                              🟢setClipboardText0.003s
                                              🟡vibrate0.002scant test this worked

                                              🟢 love.thread

                                              • 🟢 5 Tests
                                              • 🔴 0 Failures
                                              • 🟡 0 Skipped
                                              • 0.318s


                                                • MethodTimeDetails
                                                  🟢Channel0.220s
                                                  🟢Thread0.092s
                                                  🟢getChannel0.002s
                                                  🟢newChannel0.002s
                                                  🟢newThread0.002s

                                                  🟢 love.timer

                                                  • 🟢 6 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 0 Skipped
                                                  • 2.020s


                                                    • MethodTimeDetails
                                                      🟢getAverageDelta0.002s
                                                      🟢getDelta0.002s
                                                      🟢getFPS0.002s
                                                      🟢getTime1.003s
                                                      🟢sleep1.006s
                                                      🟢step0.004s

                                                      🟢 love.video

                                                      • 🟢 2 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 0 Skipped
                                                      • 0.016s


                                                        • MethodTimeDetails
                                                          🟢VideoStream0.009s
                                                          🟢newVideoStream0.007s

                                                          🟢 love.window

                                                          • 🟢 34 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 2 Skipped
                                                          • 5.954s


                                                            • MethodTimeDetails
                                                              🟢close0.054s
                                                              🟢fromPixels0.002s
                                                              🟢getDPIScale0.002s
                                                              🟢getDesktopDimensions0.002s
                                                              🟢getDisplayCount0.002s
                                                              🟢getDisplayName0.015s
                                                              🟢getDisplayOrientation0.017s
                                                              🟢getFullscreen1.340s
                                                              🟢getFullscreenModes0.009s
                                                              🟢getIcon0.019s
                                                              🟢getMode0.014s
                                                              🟢getPosition0.017s
                                                              🟢getSafeArea0.017s
                                                              🟢getTitle0.018s
                                                              🟢getVSync0.017s
                                                              🟢hasFocus0.018s
                                                              🟢hasMouseFocus0.018s
                                                              🟢isDisplaySleepEnabled0.017s
                                                              🟢isMaximized0.186s
                                                              🟢isMinimized0.744s
                                                              🟢isOpen0.054s
                                                              🟢isVisible0.031s
                                                              🟢maximize0.173s
                                                              🟢minimize0.740s
                                                              🟡requestAttention0.003scant test this worked
                                                              🟢restore0.840s
                                                              🟢setDisplaySleepEnabled0.016s
                                                              🟢setFullscreen1.335s
                                                              🟢setIcon0.013s
                                                              🟢setMode0.021s
                                                              🟢setPosition0.178s
                                                              🟢setTitle0.003s
                                                              🟢setVSync0.002s
                                                              🟡showMessageBox0.002scant test this worked
                                                              🟢toPixels0.002s
                                                              🟢updateMode0.014s
\ No newline at end of file diff --git a/testing/examples/lovetest_runAllTests.md b/testing/examples/lovetest_runAllTests.md index cfe0105b0..c69865ba7 100644 --- a/testing/examples/lovetest_runAllTests.md +++ b/testing/examples/lovetest_runAllTests.md @@ -1,28 +1,31 @@ - + -**305** tests were completed in **12.195s** with **254** passed, **1** failed, and **50** skipped +**305** tests were completed in **16.781s** with **275** passed, **2** failed, and **28** skipped ### Report -| Module | Passed | Failed | Skipped | Time | +| Module | Pass | Fail | Skip | Time | | --------------------- | ------ | ------ | ------- | ------ | -| 🟢 audio | 26 | 0 | 2 | 0.473s | -| 🟢 data | 7 | 0 | 5 | 0.212s | -| 🟢 event | 4 | 0 | 2 | 0.108s | -| 🟢 filesystem | 28 | 0 | 3 | 0.556s | -| 🟢 font | 4 | 0 | 3 | 0.127s | -| 🔴 graphics | 91 | 1 | 15 | 2.091s | -| 🟢 image | 3 | 0 | 2 | 0.087s | -| 🟢 math | 17 | 0 | 3 | 0.358s | -| 🟢 physics | 22 | 0 | 6 | 0.492s | -| 🟢 sound | 2 | 0 | 2 | 0.072s | -| 🟢 system | 6 | 0 | 2 | 0.142s | -| 🟢 thread | 3 | 0 | 2 | 0.088s | -| 🟢 timer | 6 | 0 | 0 | 2.086s | -| 🟢 video | 1 | 0 | 1 | 0.031s | -| 🟢 window | 34 | 0 | 2 | 5.273s | +| 🔴 audio | 27 | 1 | 0 | 4.898s | +| 🟢 data | 12 | 0 | 0 | 0.213s | +| 🟢 event | 4 | 0 | 2 | 0.103s | +| 🟢 filesystem | 29 | 0 | 2 | 0.561s | +| 🔴 font | 6 | 1 | 0 | 0.123s | +| 🟢 graphics | 93 | 0 | 14 | 2.106s | +| 🟢 image | 5 | 0 | 0 | 0.088s | +| 🟢 math | 20 | 0 | 0 | 0.284s | +| 🟢 physics | 22 | 0 | 6 | 0.059s | +| 🟢 sound | 4 | 0 | 0 | 0.015s | +| 🟢 system | 6 | 0 | 2 | 0.023s | +| 🟢 thread | 5 | 0 | 0 | 0.318s | +| 🟢 timer | 6 | 0 | 0 | 2.020s | +| 🟢 video | 2 | 0 | 0 | 0.016s | +| 🟢 window | 34 | 0 | 2 | 5.954s | ### Failures -> 🔴 setColorMask -> assert #7 [check pixel b for yellow at 0,0(set color mask)] expected '0' got '1' +> 🔴 Source +> assert 53 [check effect was applied] expected 'true' got 'false' + +> 🔴 GlyphData +> assert 8 [check glyph number] expected '97' got '0' diff --git a/testing/examples/lovetest_runAllTests.xml b/testing/examples/lovetest_runAllTests.xml index 73ada5cba..deb2d4201 100644 --- a/testing/examples/lovetest_runAllTests.xml +++ b/testing/examples/lovetest_runAllTests.xml @@ -1,122 +1,115 @@ - - - - + + + - - + + assert 53 [check effect was applied] expected 'true' got 'false' - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + - - + - + - + - - + - + - - + - - + - - + + - - + + - + - + - - + + - - + - + - + @@ -124,91 +117,89 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + assert 8 [check glyph number] expected '97' got '0' - - + - - + - + - + - + - + - - + + - + - + - + - + @@ -223,65 +214,64 @@ - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + @@ -289,107 +279,106 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - assert #7 [check pixel b for yellow at 0,0(set color mask)] expected '0' got '1' + @@ -397,11 +386,11 @@ - + - + - + @@ -409,285 +398,275 @@ - + - + - + - + - + - + - - - + + - - + - + - + - - - + + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + - - + - + - + - - + + - + - + - + - + - + - + - + - - - + + - - + - + - + - + - - + + - + - + - + - + - + - - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + \ No newline at end of file diff --git a/testing/readme.md b/testing/readme.md index f9fdfd2cc..2f6f8bb42 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -101,6 +101,8 @@ love.test.filesystem.read = function(test) end ``` +Each test is run inside it's own coroutine - you can use `test:waitFrames(frames)` to pause the test for a small period if you need to check things that won't happen for a few seconds. + After each test method is ran, the assertions are totalled up, printed, and we move onto the next method! Once all methods in the suite are run a total pass/fail/skip is given for that module and we move onto the next module (if any) For sanity-checking, if it's currently not covered or it's not possible to test the method we can set the test to be skipped with `test:skipTest(reason)` - this way we still see the method listed in the test output without it affected the pass/fail totals @@ -108,13 +110,23 @@ For sanity-checking, if it's currently not covered or it's not possible to test --- ## Todo -Modules with some small bits needed or needing sense checking: -- **love.event** - love.event.wait or love.event.pump need writing if possible I dunno how to check -- **love.font** - newBMFontRasterizer() wiki entry is wrong so not sure whats expected -- **love.graphics** - still need to do tests for the main drawing methods -- **love.image** - ideally isCompressed should have an example of all compressed files love can take -- **love.*.objects** - all objects tests still to be done -- **love.graphics.setStencilTest** - deprecated, replaced by setStencilMode() +Things still left to do: +- [ ] physics.Body, physics.Contact, physics.Fixture, + physics.Joint, physics.Shape, physics.World +- [ ] graphics.Canvas, graphics.Font, graphics.Image, graphics.Mesh, + graphics.ParticleSystem, graphics.Quad, graphics.Shader, + graphics.SpriteBatch, graphics.Text, graphics.Texture, graphics.Video +- [ ] event.wait +- [ ] graphics.present +- [ ] graphics.drawInstanced +- [ ] graphics.setDepthMode (needs actual graphical comparison if possible) +- [ ] graphics.setFrontFaceWinding (needs actual graphical comparison if possible) +- [ ] graphics.setMeshCullMode (needs actual graphical comparison if possible) +- [ ] @deprecated setStencilTest (use setStencilMode) +- [ ] @deprecated physics methods (sasha changes) +- [ ] check 12.0 wiki page for new methods +- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) +- [ ] ideally graphics.isCompressed should have an example of all compressed files love can take --- diff --git a/testing/resources/alsoft.conf b/testing/resources/alsoft.conf index 3e28208eb..6d1add00f 100644 --- a/testing/resources/alsoft.conf +++ b/testing/resources/alsoft.conf @@ -1,4 +1,491 @@ +# OpenAL config file. +# +# Option blocks may appear multiple times, and duplicated options will take the +# last value specified. Environment variables may be specified within option +# values, and are automatically substituted when the config file is loaded. +# Environment variable names may only contain alpha-numeric characters (a-z, +# A-Z, 0-9) and underscores (_), and are prefixed with $. For example, +# specifying "$HOME/file.ext" would typically result in something like +# "/home/user/file.ext". To specify an actual "$" character, use "$$". +# +# Device-specific values may be specified by including the device name in the +# block name, with "general" replaced by the device name. That is, general +# options for the device "Name of Device" would be in the [Name of Device] +# block, while ALSA options would be in the [alsa/Name of Device] block. +# Options marked as "(global)" are not influenced by the device. +# +# The system-wide settings can be put in /etc/openal/alsoft.conf and user- +# specific override settings in $HOME/.alsoftrc. +# For Windows, these settings should go into $AppData\alsoft.ini +# +# Option and block names are case-senstive. The supplied values are only hints +# and may not be honored (though generally it'll try to get as close as +# possible). Note: options that are left unset may default to app- or system- +# specified values. These are the current available settings: + +## +## General stuff +## [general] + +## disable-cpu-exts: (global) +# Disables use of specialized methods that use specific CPU intrinsics. +# Certain methods may utilize CPU extensions for improved performance, and +# this option is useful for preventing some or all of those methods from being +# used. The available extensions are: sse, sse2, sse3, sse4.1, and neon. +# Specifying 'all' disables use of all such specialized methods. +#disable-cpu-exts = + +## drivers: (global) +# Sets the backend driver list order, comma-seperated. Unknown backends and +# duplicated names are ignored. Unlisted backends won't be considered for use +# unless the list is ended with a comma (e.g. 'oss,' will try OSS first before +# other backends, while 'oss' will try OSS only). Backends prepended with - +# won't be considered for use (e.g. '-oss,' will try all available backends +# except OSS). An empty list means to try all backends. drivers = wave + +## channels: +# Sets the output channel configuration. If left unspecified, one will try to +# be detected from the system, and defaulting to stereo. The available values +# are: mono, stereo, quad, surround51, surround51rear, surround61, surround71, +# ambi1, ambi2, ambi3. Note that the ambi* configurations provide ambisonic +# channels of the given order (using ACN ordering and SN3D normalization by +# default), which need to be decoded to play correctly on speakers. +#channels = + +## sample-type: +# Sets the output sample type. Currently, all mixing is done with 32-bit float +# and converted to the output sample type as needed. Available values are: +# int8 - signed 8-bit int +# uint8 - unsigned 8-bit int +# int16 - signed 16-bit int +# uint16 - unsigned 16-bit int +# int32 - signed 32-bit int +# uint32 - unsigned 32-bit int +# float32 - 32-bit float +#sample-type = float32 + +## frequency: +# Sets the output frequency. If left unspecified it will try to detect a +# default from the system, otherwise it will default to 44100. +#frequency = + +## period_size: +# Sets the update period size, in frames. This is the number of frames needed +# for each mixing update. Acceptable values range between 64 and 8192. +#period_size = 1024 + +## periods: +# Sets the number of update periods. Higher values create a larger mix ahead, +# which helps protect against skips when the CPU is under load, but increases +# the delay between a sound getting mixed and being heard. Acceptable values +# range between 2 and 16. +#periods = 3 + +## stereo-mode: +# Specifies if stereo output is treated as being headphones or speakers. With +# headphones, HRTF or crossfeed filters may be used for better audio quality. +# Valid settings are auto, speakers, and headphones. +#stereo-mode = auto + +## stereo-encoding: +# Specifies the encoding method for non-HRTF stereo output. 'panpot' (default) +# uses standard amplitude panning (aka pair-wise, stereo pair, etc) between +# -30 and +30 degrees, while 'uhj' creates stereo-compatible two-channel UHJ +# output, which encodes some surround sound information into stereo output +# that can be decoded with a surround sound receiver. If crossfeed filters are +# used, UHJ is disabled. +#stereo-encoding = panpot + +## ambi-format: +# Specifies the channel order and normalization for the "ambi*" set of channel +# configurations. Valid settings are: fuma, acn+sn3d, acn+n3d +#ambi-format = acn+sn3d + +## hrtf: +# Controls HRTF processing. These filters provide better spatialization of +# sounds while using headphones, but do require a bit more CPU power. The +# default filters will only work with 44100hz or 48000hz stereo output. While +# HRTF is used, the cf_level option is ignored. Setting this to auto (default) +# will allow HRTF to be used when headphones are detected or the app requests +# it, while setting true or false will forcefully enable or disable HRTF +# respectively. +#hrtf = auto + +## default-hrtf: +# Specifies the default HRTF to use. When multiple HRTFs are available, this +# determines the preferred one to use if none are specifically requested. Note +# that this is the enumerated HRTF name, not necessarily the filename. +#default-hrtf = + +## hrtf-paths: +# Specifies a comma-separated list of paths containing HRTF data sets. The +# format of the files are described in docs/hrtf.txt. The files within the +# directories must have the .mhr file extension to be recognized. By default, +# OS-dependent data paths will be used. They will also be used if the list +# ends with a comma. On Windows this is: +# $AppData\openal\hrtf +# And on other systems, it's (in order): +# $XDG_DATA_HOME/openal/hrtf (defaults to $HOME/.local/share/openal/hrtf) +# $XDG_DATA_DIRS/openal/hrtf (defaults to /usr/local/share/openal/hrtf and +# /usr/share/openal/hrtf) +#hrtf-paths = + +## cf_level: +# Sets the crossfeed level for stereo output. Valid values are: +# 0 - No crossfeed +# 1 - Low crossfeed +# 2 - Middle crossfeed +# 3 - High crossfeed (virtual speakers are closer to itself) +# 4 - Low easy crossfeed +# 5 - Middle easy crossfeed +# 6 - High easy crossfeed +# Users of headphones may want to try various settings. Has no effect on non- +# stereo modes. +#cf_level = 0 + +## resampler: (global) +# Selects the resampler used when mixing sources. Valid values are: +# point - nearest sample, no interpolation +# linear - extrapolates samples using a linear slope between samples +# cubic - extrapolates samples using a Catmull-Rom spline +# bsinc12 - extrapolates samples using a band-limited Sinc filter (varying +# between 12 and 24 points, with anti-aliasing) +# bsinc24 - extrapolates samples using a band-limited Sinc filter (varying +# between 24 and 48 points, with anti-aliasing) +#resampler = linear + +## rt-prio: (global) +# Sets real-time priority for the mixing thread. Not all drivers may use this +# (eg. PortAudio) as they already control the priority of the mixing thread. +# 0 and negative values will disable it. Note that this may constitute a +# security risk since a real-time priority thread can indefinitely block +# normal-priority threads if it fails to wait. As such, the default is +# disabled. +#rt-prio = 0 + +## sources: +# Sets the maximum number of allocatable sources. Lower values may help for +# systems with apps that try to play more sounds than the CPU can handle. +#sources = 256 + +## slots: +# Sets the maximum number of Auxiliary Effect Slots an app can create. A slot +# can use a non-negligible amount of CPU time if an effect is set on it even +# if no sources are feeding it, so this may help when apps use more than the +# system can handle. +#slots = 64 + +## sends: +# Limits the number of auxiliary sends allowed per source. Setting this higher +# than the default has no effect. +#sends = 16 + +## front-stablizer: +# Applies filters to "stablize" front sound imaging. A psychoacoustic method +# is used to generate a front-center channel signal from the front-left and +# front-right channels, improving the front response by reducing the combing +# artifacts and phase errors. Consequently, it will only work with channel +# configurations that include front-left, front-right, and front-center. +#front-stablizer = false + +## output-limiter: +# Applies a gain limiter on the final mixed output. This reduces the volume +# when the output samples would otherwise clamp, avoiding excessive clipping +# noise. +#output-limiter = true + +## dither: +# Applies dithering on the final mix, for 8- and 16-bit output by default. +# This replaces the distortion created by nearest-value quantization with low- +# level whitenoise. +#dither = true + +## dither-depth: +# Quantization bit-depth for dithered output. A value of 0 (or less) will +# match the output sample depth. For int32, uint32, and float32 output, 0 will +# disable dithering because they're at or beyond the rendered precision. The +# maximum dither depth is 24. +#dither-depth = 0 + +## volume-adjust: +# A global volume adjustment for source output, expressed in decibels. The +# value is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will +# be a scale of 4x, etc. Similarly, -6 will be x1/2, and -12 is about x1/4. A +# value of 0 means no change. +#volume-adjust = 0 + +## excludefx: (global) +# Sets which effects to exclude, preventing apps from using them. This can +# help for apps that try to use effects which are too CPU intensive for the +# system to handle. Available effects are: eaxreverb,reverb,autowah,chorus, +# compressor,distortion,echo,equalizer,flanger,modulator,dedicated,pshifter, +# fshifter +#excludefx = + +## default-reverb: (global) +# A reverb preset that applies by default to all sources on send 0 +# (applications that set their own slots on send 0 will override this). +# Available presets are: None, Generic, PaddedCell, Room, Bathroom, +# Livingroom, Stoneroom, Auditorium, ConcertHall, Cave, Arena, Hangar, +# CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Moutains, +# Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic. +#default-reverb = + +## trap-alc-error: (global) +# Generates a SIGTRAP signal when an ALC device error is generated, on systems +# that support it. This helps when debugging, while trying to find the cause +# of a device error. On Windows, a breakpoint exception is generated. +#trap-alc-error = false + +## trap-al-error: (global) +# Generates a SIGTRAP signal when an AL context error is generated, on systems +# that support it. This helps when debugging, while trying to find the cause +# of a context error. On Windows, a breakpoint exception is generated. +#trap-al-error = false + +## +## Ambisonic decoder stuff +## +[decoder] + +## hq-mode: +# Enables a high-quality ambisonic decoder. This mode is capable of frequency- +# dependent processing, creating a better reproduction of 3D sound rendering +# over surround sound speakers. Enabling this also requires specifying decoder +# configuration files for the appropriate speaker configuration you intend to +# use (see the quad, surround51, etc options below). Currently, up to third- +# order decoding is supported. +hq-mode = false + +## distance-comp: +# Enables compensation for the speakers' relative distances to the listener. +# This applies the necessary delays and attenuation to make the speakers +# behave as though they are all equidistant, which is important for proper +# playback of 3D sound rendering. Requires the proper distances to be +# specified in the decoder configuration file. +distance-comp = true + +## nfc: +# Enables near-field control filters. This simulates and compensates for low- +# frequency effects caused by the curvature of nearby sound-waves, which +# creates a more realistic perception of sound distance. Note that the effect +# may be stronger or weaker than intended if the application doesn't use or +# specify an appropriate unit scale, or if incorrect speaker distances are set +# in the decoder configuration file. Requires hq-mode to be enabled. +nfc = true + +## nfc-ref-delay +# Specifies the reference delay value for ambisonic output. When channels is +# set to one of the ambi* formats, this option enables NFC-HOA output with the +# specified Reference Delay parameter. The specified value can then be shared +# with an appropriate NFC-HOA decoder to reproduce correct near-field effects. +# Keep in mind that despite being designed for higher-order ambisonics, this +# applies to first-order output all the same. When left unset, normal output +# is created with no near-field simulation. +nfc-ref-delay = + +## quad: +# Decoder configuration file for Quadraphonic channel output. See +# docs/ambdec.txt for a description of the file format. +quad = + +## surround51: +# Decoder configuration file for 5.1 Surround (Side and Rear) channel output. +# See docs/ambdec.txt for a description of the file format. +surround51 = + +## surround61: +# Decoder configuration file for 6.1 Surround channel output. See +# docs/ambdec.txt for a description of the file format. +surround61 = + +## surround71: +# Decoder configuration file for 7.1 Surround channel output. See +# docs/ambdec.txt for a description of the file format. Note: This can be used +# to enable 3D7.1 with the appropriate configuration and speaker placement, +# see docs/3D7.1.txt. +surround71 = + +## +## Reverb effect stuff (includes EAX reverb) +## +[reverb] + +## boost: (global) +# A global amplification for reverb output, expressed in decibels. The value +# is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a +# scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A +# value of 0 means no change. +#boost = 0 + +## +## PulseAudio backend stuff +## +[pulse] + +## spawn-server: (global) +# Attempts to autospawn a PulseAudio server whenever needed (initializing the +# backend, enumerating devices, etc). Setting autospawn to false in Pulse's +# client.conf will still prevent autospawning even if this is set to true. +#spawn-server = true + +## allow-moves: (global) +# Allows PulseAudio to move active streams to different devices. Note that the +# device specifier (seen by applications) will not be updated when this +# occurs, and neither will the AL device configuration (sample rate, format, +# etc). +#allow-moves = false + +## fix-rate: +# Specifies whether to match the playback stream's sample rate to the device's +# sample rate. Enabling this forces OpenAL Soft to mix sources and effects +# directly to the actual output rate, avoiding a second resample pass by the +# PulseAudio server. +#fix-rate = false + +## +## ALSA backend stuff +## +[alsa] + +## device: (global) +# Sets the device name for the default playback device. +#device = default + +## device-prefix: (global) +# Sets the prefix used by the discovered (non-default) playback devices. This +# will be appended with "CARD=c,DEV=d", where c is the card id and d is the +# device index for the requested device name. +#device-prefix = plughw: + +## device-prefix-*: (global) +# Card- and device-specific prefixes may be used to override the device-prefix +# option. The option may specify the card id (eg, device-prefix-NVidia), or +# the card id and device index (eg, device-prefix-NVidia-0). The card id is +# case-sensitive. +#device-prefix- = + +## capture: (global) +# Sets the device name for the default capture device. +#capture = default + +## capture-prefix: (global) +# Sets the prefix used by the discovered (non-default) capture devices. This +# will be appended with "CARD=c,DEV=d", where c is the card id and d is the +# device number for the requested device name. +#capture-prefix = plughw: + +## capture-prefix-*: (global) +# Card- and device-specific prefixes may be used to override the +# capture-prefix option. The option may specify the card id (eg, +# capture-prefix-NVidia), or the card id and device index (eg, +# capture-prefix-NVidia-0). The card id is case-sensitive. +#capture-prefix- = + +## mmap: +# Sets whether to try using mmap mode (helps reduce latencies and CPU +# consumption). If mmap isn't available, it will automatically fall back to +# non-mmap mode. True, yes, on, and non-0 values will attempt to use mmap. 0 +# and anything else will force mmap off. +#mmap = true + +## allow-resampler: +# Specifies whether to allow ALSA's built-in resampler. Enabling this will +# allow the playback device to be set to a different sample rate than the +# actual output, causing ALSA to apply its own resampling pass after OpenAL +# Soft resamples and mixes the sources and effects for output. +#allow-resampler = false + +## +## OSS backend stuff +## +[oss] + +## device: (global) +# Sets the device name for OSS output. +#device = /dev/dsp + +## capture: (global) +# Sets the device name for OSS capture. +#capture = /dev/dsp + +## +## Solaris backend stuff +## +[solaris] + +## device: (global) +# Sets the device name for Solaris output. +#device = /dev/audio + +## +## QSA backend stuff +## +[qsa] + +## +## JACK backend stuff +## +[jack] + +## spawn-server: (global) +# Attempts to autospawn a JACK server whenever needed (initializing the +# backend, opening devices, etc). +#spawn-server = false + +## buffer-size: +# Sets the update buffer size, in samples, that the backend will keep buffered +# to handle the server's real-time processing requests. This value must be a +# power of 2, or else it will be rounded up to the next power of 2. If it is +# less than JACK's buffer update size, it will be clamped. This option may +# be useful in case the server's update size is too small and doesn't give the +# mixer time to keep enough audio available for the processing requests. +#buffer-size = 0 + +## +## WASAPI backend stuff +## +[wasapi] + +## +## DirectSound backend stuff +## +[dsound] + +## +## Windows Multimedia backend stuff +## +[winmm] + +## +## PortAudio backend stuff +## +[port] + +## device: (global) +# Sets the device index for output. Negative values will use the default as +# given by PortAudio itself. +#device = -1 + +## capture: (global) +# Sets the device index for capture. Negative values will use the default as +# given by PortAudio itself. +#capture = -1 + +## +## Wave File Writer stuff +## [wave] -file = output.wav \ No newline at end of file + +## file: (global) +# Sets the filename of the wave file to write to. An empty name prevents the +# backend from opening, even when explicitly requested. +# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION! +file = output.wav + +## bformat: (global) +# Creates AMB format files using first-order ambisonics instead of a standard +# single- or multi-channel .wav file. +#bformat = false \ No newline at end of file diff --git a/testing/tests/audio.lua b/testing/tests/audio.lua index 86912966e..f1450d577 100644 --- a/testing/tests/audio.lua +++ b/testing/tests/audio.lua @@ -15,36 +15,32 @@ love.test.audio.RecordingDevice = function(test) if #devices == 0 then return test:skipTest('cant test this works: no recording devices found') end - -- test device - if test:isDelayed() == false then - -- check object created and basics - local device = devices[1] - test.store.device = device - test:assertObject(device) - test:assertMatch({1, 2}, device:getChannelCount(), 'check channel count is 1 or 2') - test:assertNotEquals(nil, device:getName(), 'check has name') - -- check initial data is empty as we haven't recorded anything yet - test:assertNotNil(device:getBitDepth()) - test:assertEquals(nil, device:getData(), 'check initial data empty') - test:assertEquals(0, device:getSampleCount(), 'check initial sample empty') - test:assertNotNil(device:getSampleRate()) - test:assertEquals(false, device:isRecording(), 'check not recording') - -- start recording for a short time - local startrecording = device:start(32000, 4000, 16, 1) - test:assertEquals(true, startrecording, 'check recording started') - test:assertEquals(true, device:isRecording(), 'check now recording') - test:assertEquals(4000, device:getSampleRate(), 'check sample rate set') - test:assertEquals(16, device:getBitDepth(), 'check bit depth set') - test:assertEquals(1, device:getChannelCount(), 'check channel count set') - test:setDelay(20) + -- check object created and basics + local device = devices[1] + test:assertObject(device) + test:assertMatch({1, 2}, device:getChannelCount(), 'check channel count is 1 or 2') + test:assertNotEquals(nil, device:getName(), 'check has name') + -- check initial data is empty as we haven't recorded anything yet + test:assertNotNil(device:getBitDepth()) + test:assertEquals(nil, device:getData(), 'check initial data empty') + test:assertEquals(0, device:getSampleCount(), 'check initial sample empty') + test:assertNotNil(device:getSampleRate()) + test:assertEquals(false, device:isRecording(), 'check not recording') + -- start recording for a short time + -- @TODO needs delay for VMs + local startrecording = device:start(32000, 4000, 16, 1) + test:waitFrames(120) + test:assertEquals(true, startrecording, 'check recording started') + test:assertEquals(true, device:isRecording(), 'check now recording') + test:assertEquals(4000, device:getSampleRate(), 'check sample rate set') + test:assertEquals(16, device:getBitDepth(), 'check bit depth set') + test:assertEquals(1, device:getChannelCount(), 'check channel count set') + local recording = device:stop() + test:waitFrames(120) -- after recording - else - local device = test.store.device - local recording = device:stop() - test:assertEquals(false, device:isRecording(), 'check not recording') - test:assertEquals(nil, device:getData(), 'using stop should clear buffer') - test:assertObject(recording) - end + test:assertEquals(false, device:isRecording(), 'check not recording') + test:assertEquals(nil, device:getData(), 'using stop should clear buffer') + test:assertObject(recording) end diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua index 8a1d0f28b..53f229bc5 100644 --- a/testing/tests/graphics.lua +++ b/testing/tests/graphics.lua @@ -10,7 +10,49 @@ -- Canvas (love.graphics.newCanvas) love.test.graphics.Canvas = function(test) - test:skipTest('test class needs writing') + -- create canvas + local canvas = love.graphics.newCanvas(32, 32, { + + }) + test:assertObject(canvas) + -- check basic properties + test:assertNotNil(canvas:getMSAA()) + test:assertEquals('none', canvas:getMipmapMode(), 'check default mipmap') + --[[ + + Texture:getDPIScale check not nil + Texture:getDepth check >= 0 + Texture:getDimensions w, h + + Texture:getFormat (list of vals) + Texture:getHeight h + Texture:getLayerCount >= 0 + Texture:getMipmapCount >= 1 + Texture:getPixelDimensions w, h + dpi + Texture:getPixelHeight h + dpi + Texture:getPixelWidth w + dpi + Texture:getTextureType teture types (4 types) + Texture:getWidth w + Texture:isReadable true unless stencil/depth pixel formats + + Texture:getWrap + Texture:setWrap horiz, vert, depth + + Texture:getDepthSampleMode + Texture:setDepthSampleMode compare (list of vals) + + Texture:getFilter + Texture:setFilter min, mag, anisotrop + + Texture:getMipmapFilter + Texture:setMipmapFilter mode, sharpness + ]] + -- check rendering + canvas:renderTo(function() + + end) + local data = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) + -- check some pixels end @@ -489,14 +531,11 @@ end -- love.graphics.captureScreenshot love.test.graphics.captureScreenshot = function(test) - if test:isDelayed() == false then - love.graphics.captureScreenshot('example-screenshot.png') - test:setDelay(10) + love.graphics.captureScreenshot('example-screenshot.png') + test:waitFrames(10) -- need to wait until end of the frame for the screenshot - else - test:assertNotNil(love.filesystem.openFile('example-screenshot.png', 'r')) - love.filesystem.remove('example-screenshot.png') - end + test:assertNotNil(love.filesystem.openFile('example-screenshot.png', 'r')) + love.filesystem.remove('example-screenshot.png') end diff --git a/testing/tests/window.lua b/testing/tests/window.lua index 44d21a235..17e2ebca0 100644 --- a/testing/tests/window.lua +++ b/testing/tests/window.lua @@ -168,31 +168,25 @@ end -- love.window.isMaximized love.test.window.isMaximized = function(test) - if test:isDelayed() == false then - test:assertEquals(false, love.window.isMaximized(), 'check window not maximized') - love.window.maximize() - test:setDelay(10) - else - -- on MACOS maximize wont get recognised immedietely so wait a few frames - test:assertEquals(true, love.window.isMaximized(), 'check window now maximized') - love.window.restore() - end + test:assertEquals(false, love.window.isMaximized(), 'check window not maximized') + love.window.maximize() + test:waitFrames(10) + -- on MACOS maximize wont get recognised immedietely so wait a few frames + test:assertEquals(true, love.window.isMaximized(), 'check window now maximized') + love.window.restore() end -- love.window.isMinimized love.test.window.isMinimized = function(test) - if test:isDelayed() == false then - -- check not minimized to start - test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') - -- try to minimize - love.window.minimize() - test:setDelay(10) - else - -- on linux minimize won't get recognized immediately, so wait a few frames - test:assertEquals(true, love.window.isMinimized(), 'check window minimized') - love.window.restore() - end + -- check not minimized to start + test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') + -- try to minimize + love.window.minimize() + test:waitFrames(10) + -- on linux minimize won't get recognized immediately, so wait a few frames + test:assertEquals(true, love.window.isMinimized(), 'check window minimized') + love.window.restore() end @@ -220,31 +214,25 @@ end -- love.window.maximize love.test.window.maximize = function(test) - if test:isDelayed() == false then - test:assertEquals(false, love.window.isMaximized(), 'check window not maximized') - -- check maximizing is set - love.window.maximize() - test:setDelay(10) - else - -- on macos we need to wait a few frames - test:assertEquals(true, love.window.isMaximized(), 'check window maximized') - love.window.restore() - end + test:assertEquals(false, love.window.isMaximized(), 'check window not maximized') + -- check maximizing is set + love.window.maximize() + test:waitFrames(10) + -- on macos we need to wait a few frames + test:assertEquals(true, love.window.isMaximized(), 'check window maximized') + love.window.restore() end -- love.window.minimize love.test.window.minimize = function(test) - if test:isDelayed() == false then - test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') - -- check minimizing is set - love.window.minimize() - test:setDelay(10) - else - -- on linux we need to wait a few frames - test:assertEquals(true, love.window.isMinimized(), 'check window maximized') - love.window.restore() - end + test:assertEquals(false, love.window.isMinimized(), 'check window not minimized') + -- check minimizing is set + love.window.minimize() + test:waitFrames(10) + -- on linux we need to wait a few frames + test:assertEquals(true, love.window.isMinimized(), 'check window maximized') + love.window.restore() end @@ -256,20 +244,13 @@ end -- love.window.restore love.test.window.restore = function(test) - - -- TODO: for linux runner - -- test doesn't pass because the current test delay system can't wait twice - - if test:isDelayed() == false then - -- check minimized to start - love.window.minimize() - love.window.restore() - test:setDelay(10) - else - -- check restoring the state of the window - test:assertEquals(false, love.window.isMinimized(), 'check window restored') - end - + -- check minimized to start + love.window.minimize() + test:waitFrames(10) + love.window.restore() + test:waitFrames(10) + -- check restoring the state of the window + test:assertEquals(false, love.window.isMinimized(), 'check window restored') end @@ -327,15 +308,12 @@ end -- love.window.setPosition love.test.window.setPosition = function(test) - if test:isDelayed() == false then - -- check position is returned - love.window.setPosition(100, 100, 1) - test:setDelay(10) - else - local x, y, _ = love.window.getPosition() - test:assertEquals(100, x, 'check position x') - test:assertEquals(100, y, 'check position y') - end + -- check position is returned + love.window.setPosition(100, 100, 1) + test:waitFrames(10) + local x, y, _ = love.window.getPosition() + test:assertEquals(100, x, 'check position x') + test:assertEquals(100, y, 'check position y') end diff --git a/testing/todo.md b/testing/todo.md deleted file mode 100644 index b84d8d527..000000000 --- a/testing/todo.md +++ /dev/null @@ -1,26 +0,0 @@ -`/Applications/love_12.app/Contents/MacOS/love ./testing` - -## GENERAL -- [ ] check 12.0 wiki page for new methods -- [ ] change delay system to use coroutines -- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) - -## OBJECT TESTS -- [ ] physics.Body, physics.Contact, physics.Fixture, - physics.Joint, physics.Shape, physics.World -- [ ] threads.Channel, threads.Thread - -## METHOD TESTS -- [ ] event.wait -- [ ] graphics.present -- [ ] graphics.drawInstanced - -## DEPRECATED -- [ ] deprecated setStencilTest (use setStencilMode) -- [ ] deprecated physics methods - -## GRAPHIC TESTS -Methods that need a actual graphic pixel checks if possible: -- [ ] setDepthMode -- [ ] setFrontFaceWinding -- [ ] setMeshCullMode From 137126656a30492333e3a5eef03e4c9f73f15d6a Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 13:00:09 +0000 Subject: [PATCH 071/409] update ci run --- .github/workflows/main.yml | 9 +++++--- testing/tests/audio.lua | 4 ++-- testing/tests/graphics.lua | 44 +------------------------------------- 3 files changed, 9 insertions(+), 48 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 57c697ac4..20e108c56 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -70,7 +70,7 @@ jobs: echo "OPENBOXPID=$!" >> $GITHUB_ENV # linux opengl tests - name: Run All Tests (opengl) - run: xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua + run: ./love-${{ github.sha }}.AppImage ./testing/main.lua - name: Love Test Report (opengl) uses: ellraiser/love-test-report@main with: @@ -89,7 +89,7 @@ jobs: - name: Run Test Suite (opengles) run: | export LOVE_GRAPHICS_USE_OPENGLES=1 - xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua + ./love-${{ github.sha }}.AppImage ./testing/main.lua - name: Love Test Report (opengles) uses: ellraiser/love-test-report@main with: @@ -108,7 +108,7 @@ jobs: - name: Run Test Suite (vulkan) run: | export LOVE_GRAPHICS_DEBUG=1 - xvfb-run ./love-${{ github.sha }}.AppImage ./testing/main.lua --runAllTests --renderers vulkan + ./love-${{ github.sha }}.AppImage ./testing/main.lua --runAllTests --renderers vulkan - name: Love Test Report (vulkan) uses: ellraiser/love-test-report@main with: @@ -297,9 +297,12 @@ jobs: - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install + - name: Checkout + uses: actions/checkout@v3 - name: Run Tests (opengl) if: steps.vars.outputs.arch != 'ARM64' run: | + echo 'check dir' dir powershell.exe ./install/lovec.exe ./testing/main.lua # windows opengl test diff --git a/testing/tests/audio.lua b/testing/tests/audio.lua index f1450d577..436d5b6e7 100644 --- a/testing/tests/audio.lua +++ b/testing/tests/audio.lua @@ -29,14 +29,14 @@ love.test.audio.RecordingDevice = function(test) -- start recording for a short time -- @TODO needs delay for VMs local startrecording = device:start(32000, 4000, 16, 1) - test:waitFrames(120) + test:waitFrames(10) test:assertEquals(true, startrecording, 'check recording started') test:assertEquals(true, device:isRecording(), 'check now recording') test:assertEquals(4000, device:getSampleRate(), 'check sample rate set') test:assertEquals(16, device:getBitDepth(), 'check bit depth set') test:assertEquals(1, device:getChannelCount(), 'check channel count set') local recording = device:stop() - test:waitFrames(120) + test:waitFrames(10) -- after recording test:assertEquals(false, device:isRecording(), 'check not recording') test:assertEquals(nil, device:getData(), 'using stop should clear buffer') diff --git a/testing/tests/graphics.lua b/testing/tests/graphics.lua index 53f229bc5..43b389fa4 100644 --- a/testing/tests/graphics.lua +++ b/testing/tests/graphics.lua @@ -10,49 +10,7 @@ -- Canvas (love.graphics.newCanvas) love.test.graphics.Canvas = function(test) - -- create canvas - local canvas = love.graphics.newCanvas(32, 32, { - - }) - test:assertObject(canvas) - -- check basic properties - test:assertNotNil(canvas:getMSAA()) - test:assertEquals('none', canvas:getMipmapMode(), 'check default mipmap') - --[[ - - Texture:getDPIScale check not nil - Texture:getDepth check >= 0 - Texture:getDimensions w, h - - Texture:getFormat (list of vals) - Texture:getHeight h - Texture:getLayerCount >= 0 - Texture:getMipmapCount >= 1 - Texture:getPixelDimensions w, h + dpi - Texture:getPixelHeight h + dpi - Texture:getPixelWidth w + dpi - Texture:getTextureType teture types (4 types) - Texture:getWidth w - Texture:isReadable true unless stencil/depth pixel formats - - Texture:getWrap - Texture:setWrap horiz, vert, depth - - Texture:getDepthSampleMode - Texture:setDepthSampleMode compare (list of vals) - - Texture:getFilter - Texture:setFilter min, mag, anisotrop - - Texture:getMipmapFilter - Texture:setMipmapFilter mode, sharpness - ]] - -- check rendering - canvas:renderTo(function() - - end) - local data = love.graphics.readbackTexture(canvas, {16, 0, 0, 0, 16, 16}) - -- check some pixels + test:skipTest('test class needs writing') end From a9a550745551018adf31c30cf5b83cce934b9308 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:52:04 +0000 Subject: [PATCH 072/409] add missing linux lib req --- .github/workflows/main.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 20e108c56..75d060d9f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,12 +20,14 @@ jobs: libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ - vulkan-validationlayers + vulkan-validationlayers libcurl4-openssl-dev - name: Checkout love-appimage-source uses: actions/checkout@v3 with: repository: love2d/love-appimage-source ref: 12.x + - name: Checkout Repo + uses: actions/checkout@v3 - name: Checkout LÖVE uses: actions/checkout@v3 with: @@ -70,7 +72,9 @@ jobs: echo "OPENBOXPID=$!" >> $GITHUB_ENV # linux opengl tests - name: Run All Tests (opengl) - run: ./love-${{ github.sha }}.AppImage ./testing/main.lua + run: | + ls + ./love-${{ github.sha }}.AppImage ./testing/main.lua - name: Love Test Report (opengl) uses: ellraiser/love-test-report@main with: @@ -223,6 +227,8 @@ jobs: result = subprocess.run("git -C megasource rev-parse HEAD".split(), check=True, capture_output=True, encoding="UTF-8") commit = result.stdout.split()[0] with open(os.environ["GITHUB_OUTPUT"], "w", encoding="UTF-8") as f: f.write(f"commit={commit}") + - name: Checkout + uses: actions/checkout@v3 - name: Checkout uses: actions/checkout@v3 with: @@ -297,7 +303,6 @@ jobs: - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - - name: Checkout uses: actions/checkout@v3 - name: Run Tests (opengl) if: steps.vars.outputs.arch != 'ARM64' From 75c2667c53a01a4066c0a958536794b3f7bb2a88 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:53:13 +0000 Subject: [PATCH 073/409] Update main.yml --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 75d060d9f..934a6f2fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -303,7 +303,6 @@ jobs: - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install - uses: actions/checkout@v3 - name: Run Tests (opengl) if: steps.vars.outputs.arch != 'ARM64' run: | From c682ba15d90c9a66696608c1e4373c6b51b9aac8 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:01:34 +0000 Subject: [PATCH 074/409] use 12.0dev workflow --- .github/workflows/main.yml | 202 +-------------- .github/workflows/testsuite.yml | 445 ++++++++++++++++++++++++++++++++ 2 files changed, 448 insertions(+), 199 deletions(-) create mode 100644 .github/workflows/testsuite.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 934a6f2fd..f3922d769 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,10 +3,7 @@ on: [push, pull_request] jobs: linux-os: - runs-on: ubuntu-22.04 - env: - ALSOFT_CONF: resources/alsoft.conf - DISPLAY: :99 + runs-on: ubuntu-20.04 steps: - name: Update APT run: sudo apt-get update @@ -19,15 +16,12 @@ jobs: libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ - libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ - vulkan-validationlayers libcurl4-openssl-dev + libcurl4-openssl-dev - name: Checkout love-appimage-source uses: actions/checkout@v3 with: repository: love2d/love-appimage-source ref: 12.x - - name: Checkout Repo - uses: actions/checkout@v3 - name: Checkout LÖVE uses: actions/checkout@v3 with: @@ -56,89 +50,8 @@ jobs: with: name: love-x86_64-AppImage-debug path: love-${{ github.sha }}.AppImage-debug.tar.gz - - name: Make Runnable - run: | - chmod a+x love-${{ github.sha }}.AppImage - echo "ready to run" - ls - - name: Start xvfb and openbox - run: | - echo "Starting XVFB on $DISPLAY" - Xvfb $DISPLAY -screen 0, 360x240x24 & - echo "XVFBPID=$!" >> $GITHUB_ENV - # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) - sleep 3 - openbox & - echo "OPENBOXPID=$!" >> $GITHUB_ENV - # linux opengl tests - - name: Run All Tests (opengl) - run: | - ls - ./love-${{ github.sha }}.AppImage ./testing/main.lua - - name: Love Test Report (opengl) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-opengl - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengl) - run: | - 7z a -tzip test-output-linux-opengl.zip testing/output/ - - name: Artifact Test Output (opengl) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-opengl - path: test-output-linux-opengl.zip - # linux opengles tests - - name: Run Test Suite (opengles) - run: | - export LOVE_GRAPHICS_USE_OPENGLES=1 - ./love-${{ github.sha }}.AppImage ./testing/main.lua - - name: Love Test Report (opengles) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-opengles - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengles) - run: | - 7z a -tzip test-output-linux-opengles.zip testing/output/ - - name: Artifact Test Output (opengles) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-opengles - path: test-output-linux-opengles.zip - # linux vulkan tests - - name: Run Test Suite (vulkan) - run: | - export LOVE_GRAPHICS_DEBUG=1 - ./love-${{ github.sha }}.AppImage ./testing/main.lua --runAllTests --renderers vulkan - - name: Love Test Report (vulkan) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-vulkan - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (vulkan) - run: | - 7z a -tzip test-output-linux-vulkan.zip testing/output/ - - name: Artifact Test Output (vulkan) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-vulkan - path: test-output-linux-vulkan.zip - - name: Stop xvfb and openbox - # should always stop xvfb and openbox even if other steps failed - if: always() - run: | - kill $XVFBPID - kill $OPENBOXPID windows-os: runs-on: windows-latest - env: - ALSOFT_CONF: resources/alsoft.conf - VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json - VULKAN_SDK: C:/VulkanSDK/1.3.231.1 strategy: matrix: platform: [Win32, x64, ARM64] @@ -227,8 +140,6 @@ jobs: result = subprocess.run("git -C megasource rev-parse HEAD".split(), check=True, capture_output=True, encoding="UTF-8") commit = result.stdout.split()[0] with open(os.environ["GITHUB_OUTPUT"], "w", encoding="UTF-8") as f: f.write(f"commit={commit}") - - name: Checkout - uses: actions/checkout@v3 - name: Checkout uses: actions/checkout@v3 with: @@ -294,97 +205,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg - path: pdb/Release/*.pdb - - name: Install Mesa - run: | - curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z - 7z x mesa.7z -o* - powershell.exe mesa\systemwidedeploy.cmd 1 - - name: Build Test Exe - if: steps.vars.outputs.arch != 'ARM64' - run: cmake --build build --config Release --target install - - name: Run Tests (opengl) - if: steps.vars.outputs.arch != 'ARM64' - run: | - echo 'check dir' - dir - powershell.exe ./install/lovec.exe ./testing/main.lua - # windows opengl test - - name: Love Test Report (opengl) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (opengl) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengl) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-opengl.zip testing/output/ - - name: Artifact Test Output (opengl) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-opengl - path: test-output-windows-opengl.zip - # windows opengles test - - name: Run Tests (opengles) - if: steps.vars.outputs.arch != 'ARM64' - run: | - $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 - powershell.exe ./install/lovec.exe ./testing/main.lua - - name: Love Test Report (opengles) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (opengles) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengles) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-opengles.zip testing/output/ - - name: Artifact Test Output (opengles) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-opengles - path: test-output-windows-opengles.zip - - name: Install Vulkan - if: steps.vars.outputs.arch != 'ARM64' - run: | - curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe - ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma - curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip - 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" - reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 - powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary - # windows vulkan tests - - name: Run Tests (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: | - $ENV:LOVE_GRAPHICS_DEBUG=1 - powershell.exe ./install/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan - - name: Love Test Report (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (vulkan) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-vulkan.zip testing/output - - name: Artifact Test Output (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-vulkan - path: test-output-windows-vulkan.zip + path: pdb/Release/*.pdb macOS: runs-on: macos-latest steps: @@ -413,23 +234,6 @@ jobs: with: name: love-macos path: love-macos.zip - # macos opengl tests - - name: Run Tests - run: love-macos/love.app/Contents/MacOS/love testing/main.lua - - name: Love Test Report - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite MacOS - title: test-report-macos - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output - run: | - 7z a -tzip test-output-macos-opengl.zip testing/output/ - - name: Artifact Test Output - uses: actions/upload-artifact@v3 - with: - name: test-output-macos-opengl - path: test-output-macos-opengl.zip iOS-Simulator: runs-on: macos-latest steps: diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml new file mode 100644 index 000000000..2ca8483d1 --- /dev/null +++ b/.github/workflows/testsuite.yml @@ -0,0 +1,445 @@ +name: continuous-integration +on: [push, pull_request] + +jobs: + linux-os: + runs-on: ubuntu-22.04 + env: + ALSOFT_CONF: resources/alsoft.conf + DISPLAY: :99 + steps: + - name: Update APT + run: sudo apt-get update + - name: Install Dependencies + run: | + sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \ + libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \ + libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \ + libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ + libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ + libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ + libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ + libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ + vulkan-validationlayers libcurl4-openssl-dev + - name: Checkout love-appimage-source + uses: actions/checkout@v3 + with: + repository: love2d/love-appimage-source + ref: 12.x + - name: Checkout LÖVE + uses: actions/checkout@v3 + with: + path: love2d-${{ github.sha }} + - name: Get Dependencies for AppImage + shell: python + env: + LOVE_BRANCH: ${{ github.sha }} + run: | + import os + for i in range(250): + if os.system(f"make getdeps LOVE_BRANCH={os.environ['LOVE_BRANCH']}") == 0: + raise SystemExit(0) + raise Exception("make getdeps failed") + - name: Build AppImage + run: make LOVE_BRANCH=${{ github.sha }} + - name: Print LuaJIT branch + run: git -C LuaJIT-v2.1 branch -v + - name: Artifact + uses: actions/upload-artifact@v3 + with: + name: love-linux-x86_64.AppImage + path: love-${{ github.sha }}.AppImage + - name: Artifact Debug Symbols + uses: actions/upload-artifact@v3 + with: + name: love-x86_64-AppImage-debug + path: love-${{ github.sha }}.AppImage-debug.tar.gz + - name: Make Runnable + run: | + chmod a+x love-${{ github.sha }}.AppImage + echo "ready to run" + ls + - name: Start xvfb and openbox + run: | + echo "Starting XVFB on $DISPLAY" + Xvfb $DISPLAY -screen 0, 360x240x24 & + echo "XVFBPID=$!" >> $GITHUB_ENV + # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) + sleep 3 + openbox & + echo "OPENBOXPID=$!" >> $GITHUB_ENV + # linux opengl tests + - name: Run All Tests (opengl) + run: | + ls + ./love-${{ github.sha }}.AppImage ./testing/main.lua + - name: Love Test Report (opengl) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-opengl + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengl) + run: | + 7z a -tzip test-output-linux-opengl.zip testing/output/ + - name: Artifact Test Output (opengl) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-opengl + path: test-output-linux-opengl.zip + # linux opengles tests + - name: Run Test Suite (opengles) + run: | + export LOVE_GRAPHICS_USE_OPENGLES=1 + ./love-${{ github.sha }}.AppImage ./testing/main.lua + - name: Love Test Report (opengles) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-opengles + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengles) + run: | + 7z a -tzip test-output-linux-opengles.zip testing/output/ + - name: Artifact Test Output (opengles) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-opengles + path: test-output-linux-opengles.zip + # linux vulkan tests + - name: Run Test Suite (vulkan) + run: | + export LOVE_GRAPHICS_DEBUG=1 + ./love-${{ github.sha }}.AppImage ./testing/main.lua --runAllTests --renderers vulkan + - name: Love Test Report (vulkan) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-vulkan + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (vulkan) + run: | + 7z a -tzip test-output-linux-vulkan.zip testing/output/ + - name: Artifact Test Output (vulkan) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-vulkan + path: test-output-linux-vulkan.zip + - name: Stop xvfb and openbox + # should always stop xvfb and openbox even if other steps failed + if: always() + run: | + kill $XVFBPID + kill $OPENBOXPID + windows-os: + runs-on: windows-latest + env: + ALSOFT_CONF: resources/alsoft.conf + VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json + VULKAN_SDK: C:/VulkanSDK/1.3.231.1 + strategy: + matrix: + platform: [Win32, x64, ARM64] + install: [compat, modern] + exclude: + - platform: ARM64 + install: compat + defaults: + run: + shell: cmd + continue-on-error: ${{ matrix.platform == 'ARM64' }} + steps: + - name: Define Variables + id: vars + run: | + rem Compat/Modern switch + if "${{ matrix.install }}" == "compat" ( + echo moredef=-DLOVE_INSTALL_UCRT=ON>> "%GITHUB_OUTPUT%" + echo compatname=-compat>> "%GITHUB_OUTPUT%" + ) else ( + echo moredef=>> "%GITHUB_OUTPUT%" + echo compatname=>> "%GITHUB_OUTPUT%" + ) + + rem JIT Modules + if "${{ matrix.platform }}-${{ matrix.install }}" == "x64-modern" ( + (echo jitmodules=1)>> "%GITHUB_OUTPUT%" + ) else ( + (echo jitmodules=0)>> "%GITHUB_OUTPUT%" + ) + + rem Architecture-Specific Switch + goto ${{ matrix.platform }} + exit /b 1 + + :Win32 + (echo arch=x86)>> "%GITHUB_OUTPUT%" + (echo angle=0)>> "%GITHUB_OUTPUT%" + echo nofiles=warn>> "%GITHUB_OUTPUT%" + exit /b 0 + + :x64 + (echo arch=x64)>> "%GITHUB_OUTPUT%" + (echo angle=0)>> "%GITHUB_OUTPUT%" + echo nofiles=warn>> "%GITHUB_OUTPUT%" + exit /b 0 + + :ARM64 + (echo arch=arm64)>> "%GITHUB_OUTPUT%" + (echo angle=1)>> "%GITHUB_OUTPUT%" + echo nofiles=ignore>> "%GITHUB_OUTPUT%" + echo moredef=-DLOVE_EXTRA_DLLS=%CD%\angle\libEGL.dll;%CD%\angle\libGLESv2.dll>> "%GITHUB_OUTPUT%" + exit /b 0 + - name: Download Windows SDK Setup 10.0.20348 + run: curl -Lo winsdksetup.exe https://go.microsoft.com/fwlink/?linkid=2164145 + - name: Install Debugging Tools for Windows + id: windbg + run: | + setlocal enabledelayedexpansion + start /WAIT %CD%\winsdksetup.exe /features OptionId.WindowsDesktopDebuggers /q /log %CD%\log.txt + echo ERRORLEVEL=!ERRORLEVEL! >> %GITHUB_OUTPUT% + - name: Print Debugging Tools Install Log + if: always() + run: | + type log.txt + exit /b ${{ steps.windbg.outputs.ERRORLEVEL }} + - name: Setup Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Download source_index.py + run: curl -Lo source_index.py https://gist.github.com/MikuAuahDark/d9c099f5714e09a765496471c2827a55/raw/df34956052035f3473c5f01861dfb53930d06843/source_index.py + - name: Clone Megasource + uses: actions/checkout@v3 + with: + path: megasource + repository: love2d/megasource + ref: 12.x + - id: megasource + name: Get Megasource Commit SHA + shell: python + run: | + import os + import subprocess + + result = subprocess.run("git -C megasource rev-parse HEAD".split(), check=True, capture_output=True, encoding="UTF-8") + commit = result.stdout.split()[0] + with open(os.environ["GITHUB_OUTPUT"], "w", encoding="UTF-8") as f: f.write(f"commit={commit}") + - name: Checkout + uses: actions/checkout@v3 + with: + path: megasource/libs/love + - name: Download ANGLE + uses: robinraju/release-downloader@v1.7 + if: steps.vars.outputs.angle == '1' + with: + repository: MikuAuahDark/angle-winbuild + tag: cr_5249 + fileName: angle-win-${{ steps.vars.outputs.arch }}.zip + tarBall: false + zipBall: false + out-file-path: angle + - name: Extract ANGLE + if: steps.vars.outputs.angle == '1' + working-directory: angle + run: 7z x angle-win-${{ steps.vars.outputs.arch }}.zip + - name: Delete Strawbery Perl + # https://github.com/actions/runner-images/issues/6627 + # In particular, this is not pretty, but even CMAKE_IGNORE_PREFIX_PATH + # cannot help in this case. Delete the whole folder! + run: | + rmdir /s /q C:\Strawberry + exit /b 0 + - name: Configure + env: + CFLAGS: /Zi + CXXFLAGS: /Zi + LDFLAGS: /DEBUG:FULL /OPT:REF /OPT:ICF + run: cmake -Bbuild -Smegasource -T v142 -A ${{ matrix.platform }} --install-prefix %CD%\install -DCMAKE_PDB_OUTPUT_DIRECTORY=%CD%\pdb ${{ steps.vars.outputs.moredef }} + - name: Install + run: cmake --build build --target PACKAGE --config Release -j2 + - name: Copy LuaJIT lua51.pdb + run: | + copy /Y build\libs\LuaJIT\src\lua51.pdb pdb\Release\lua51.pdb + exit /b 0 + - name: Add srcsrv to PATH + run: | + echo C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\srcsrv>>%GITHUB_PATH% + - name: Embed Source Index into PDBs + run: | + python source_index.py ^ + --source %CD%\megasource\libs\love https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }} ^ + --source %CD%\megasource https://raw.githubusercontent.com/love2d/megasource/${{ steps.megasource.outputs.commit }} ^ + --source %CD%\build\libs\LuaJIT https://raw.githubusercontent.com/love2d/megasource/${{ steps.megasource.outputs.commit }}/libs/LuaJIT ^ + pdb\Release\*.pdb + - name: Artifact + uses: actions/upload-artifact@v3 + with: + name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }} + path: | + build/*.zip + build/*.exe + if-no-files-found: ${{ steps.vars.outputs.nofiles }} + - name: Artifact JIT Modules + if: steps.vars.outputs.jitmodules == '1' + uses: actions/upload-artifact@v3 + with: + name: love-windows-jitmodules + path: build/libs/LuaJIT/src/jit/*.lua + - name: Artifact PDB + uses: actions/upload-artifact@v3 + with: + name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg + path: pdb/Release/*.pdb + - name: Install Mesa + run: | + curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z + 7z x mesa.7z -o* + powershell.exe mesa\systemwidedeploy.cmd 1 + - name: Build Test Exe + if: steps.vars.outputs.arch != 'ARM64' + run: cmake --build build --config Release --target install + - name: Run Tests (opengl) + if: steps.vars.outputs.arch != 'ARM64' + run: | + echo 'check dir' + dir + powershell.exe ./install/lovec.exe ./testing/main.lua + # windows opengl test + - name: Love Test Report (opengl) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (opengl) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengl) + if: steps.vars.outputs.arch != 'ARM64' + run: | + 7z a -tzip test-output-windows-opengl.zip testing/output/ + - name: Artifact Test Output (opengl) + if: steps.vars.outputs.arch != 'ARM64' + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-opengl + path: test-output-windows-opengl.zip + # windows opengles test + - name: Run Tests (opengles) + if: steps.vars.outputs.arch != 'ARM64' + run: | + $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 + powershell.exe ./install/lovec.exe ./testing/main.lua + - name: Love Test Report (opengles) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (opengles) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengles) + if: steps.vars.outputs.arch != 'ARM64' + run: | + 7z a -tzip test-output-windows-opengles.zip testing/output/ + - name: Artifact Test Output (opengles) + if: steps.vars.outputs.arch != 'ARM64' + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-opengles + path: test-output-windows-opengles.zip + - name: Install Vulkan + if: steps.vars.outputs.arch != 'ARM64' + run: | + curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe + ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma + curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip + 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" + reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 + powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary + # windows vulkan tests + - name: Run Tests (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + run: | + $ENV:LOVE_GRAPHICS_DEBUG=1 + powershell.exe ./install/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan + - name: Love Test Report (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (vulkan) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + run: | + 7z a -tzip test-output-windows-vulkan.zip testing/output + - name: Artifact Test Output (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-vulkan + path: test-output-windows-vulkan.zip + macOS: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Clone Dependencies + uses: actions/checkout@v3 + with: + path: apple-dependencies + repository: love2d/love-apple-dependencies + ref: 12.x + - name: Move Dependencies + run: + mv apple-dependencies/macOS/Frameworks platform/xcode/macosx + - name: Build + run: + xcodebuild clean archive -project platform/xcode/love.xcodeproj -scheme love-macosx -configuration Release -archivePath love-macos.xcarchive + - name: Export Archive + run: + xcodebuild -exportArchive -archivePath love-macos.xcarchive -exportPath love-macos -exportOptionsPlist platform/xcode/macosx/macos-copy-app.plist + - name: Zip Archive + run: + ditto -c -k --sequesterRsrc --keepParent love-macos/love.app love-macos.zip + - name: Artifact + uses: actions/upload-artifact@v3 + with: + name: love-macos + path: love-macos.zip + # macos opengl tests + - name: Run Tests + run: love-macos/love.app/Contents/MacOS/love testing/main.lua + - name: Love Test Report + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite MacOS + title: test-report-macos + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output + run: | + 7z a -tzip test-output-macos-opengl.zip testing/output/ + - name: Artifact Test Output + uses: actions/upload-artifact@v3 + with: + name: test-output-macos-opengl + path: test-output-macos-opengl.zip + iOS-Simulator: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Clone Dependencies + uses: actions/checkout@v3 + with: + path: apple-dependencies + repository: love2d/love-apple-dependencies + ref: 12.x + - name: Move Dependencies + run: | + mv apple-dependencies/iOS/libraries platform/xcode/ios + - name: Build + run: + xcodebuild -project platform/xcode/love.xcodeproj -scheme love-ios -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11' From d23c3968133ff21415548ad0cede403f7f487937 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:15:37 +0000 Subject: [PATCH 075/409] split workflow --- .github/workflows/testsuite.yml | 452 +------------------------------- 1 file changed, 12 insertions(+), 440 deletions(-) diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml index 2ca8483d1..4590ad5b2 100644 --- a/.github/workflows/testsuite.yml +++ b/.github/workflows/testsuite.yml @@ -1,445 +1,17 @@ -name: continuous-integration -on: [push, pull_request] +name: testsuite + +on: + workflow_run: + workflows: ["continuous-integration"] + types: + - completed jobs: - linux-os: - runs-on: ubuntu-22.04 - env: - ALSOFT_CONF: resources/alsoft.conf - DISPLAY: :99 - steps: - - name: Update APT - run: sudo apt-get update - - name: Install Dependencies - run: | - sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \ - libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \ - libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \ - libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ - libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ - libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ - libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ - libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ - vulkan-validationlayers libcurl4-openssl-dev - - name: Checkout love-appimage-source - uses: actions/checkout@v3 - with: - repository: love2d/love-appimage-source - ref: 12.x - - name: Checkout LÖVE - uses: actions/checkout@v3 - with: - path: love2d-${{ github.sha }} - - name: Get Dependencies for AppImage - shell: python - env: - LOVE_BRANCH: ${{ github.sha }} - run: | - import os - for i in range(250): - if os.system(f"make getdeps LOVE_BRANCH={os.environ['LOVE_BRANCH']}") == 0: - raise SystemExit(0) - raise Exception("make getdeps failed") - - name: Build AppImage - run: make LOVE_BRANCH=${{ github.sha }} - - name: Print LuaJIT branch - run: git -C LuaJIT-v2.1 branch -v - - name: Artifact - uses: actions/upload-artifact@v3 - with: - name: love-linux-x86_64.AppImage - path: love-${{ github.sha }}.AppImage - - name: Artifact Debug Symbols - uses: actions/upload-artifact@v3 - with: - name: love-x86_64-AppImage-debug - path: love-${{ github.sha }}.AppImage-debug.tar.gz - - name: Make Runnable - run: | - chmod a+x love-${{ github.sha }}.AppImage - echo "ready to run" - ls - - name: Start xvfb and openbox - run: | - echo "Starting XVFB on $DISPLAY" - Xvfb $DISPLAY -screen 0, 360x240x24 & - echo "XVFBPID=$!" >> $GITHUB_ENV - # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) - sleep 3 - openbox & - echo "OPENBOXPID=$!" >> $GITHUB_ENV - # linux opengl tests - - name: Run All Tests (opengl) - run: | - ls - ./love-${{ github.sha }}.AppImage ./testing/main.lua - - name: Love Test Report (opengl) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-opengl - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengl) - run: | - 7z a -tzip test-output-linux-opengl.zip testing/output/ - - name: Artifact Test Output (opengl) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-opengl - path: test-output-linux-opengl.zip - # linux opengles tests - - name: Run Test Suite (opengles) - run: | - export LOVE_GRAPHICS_USE_OPENGLES=1 - ./love-${{ github.sha }}.AppImage ./testing/main.lua - - name: Love Test Report (opengles) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-opengles - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengles) - run: | - 7z a -tzip test-output-linux-opengles.zip testing/output/ - - name: Artifact Test Output (opengles) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-opengles - path: test-output-linux-opengles.zip - # linux vulkan tests - - name: Run Test Suite (vulkan) - run: | - export LOVE_GRAPHICS_DEBUG=1 - ./love-${{ github.sha }}.AppImage ./testing/main.lua --runAllTests --renderers vulkan - - name: Love Test Report (vulkan) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-vulkan - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (vulkan) - run: | - 7z a -tzip test-output-linux-vulkan.zip testing/output/ - - name: Artifact Test Output (vulkan) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-vulkan - path: test-output-linux-vulkan.zip - - name: Stop xvfb and openbox - # should always stop xvfb and openbox even if other steps failed - if: always() - run: | - kill $XVFBPID - kill $OPENBOXPID - windows-os: - runs-on: windows-latest - env: - ALSOFT_CONF: resources/alsoft.conf - VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json - VULKAN_SDK: C:/VulkanSDK/1.3.231.1 - strategy: - matrix: - platform: [Win32, x64, ARM64] - install: [compat, modern] - exclude: - - platform: ARM64 - install: compat - defaults: - run: - shell: cmd - continue-on-error: ${{ matrix.platform == 'ARM64' }} - steps: - - name: Define Variables - id: vars - run: | - rem Compat/Modern switch - if "${{ matrix.install }}" == "compat" ( - echo moredef=-DLOVE_INSTALL_UCRT=ON>> "%GITHUB_OUTPUT%" - echo compatname=-compat>> "%GITHUB_OUTPUT%" - ) else ( - echo moredef=>> "%GITHUB_OUTPUT%" - echo compatname=>> "%GITHUB_OUTPUT%" - ) - - rem JIT Modules - if "${{ matrix.platform }}-${{ matrix.install }}" == "x64-modern" ( - (echo jitmodules=1)>> "%GITHUB_OUTPUT%" - ) else ( - (echo jitmodules=0)>> "%GITHUB_OUTPUT%" - ) - - rem Architecture-Specific Switch - goto ${{ matrix.platform }} - exit /b 1 - - :Win32 - (echo arch=x86)>> "%GITHUB_OUTPUT%" - (echo angle=0)>> "%GITHUB_OUTPUT%" - echo nofiles=warn>> "%GITHUB_OUTPUT%" - exit /b 0 - - :x64 - (echo arch=x64)>> "%GITHUB_OUTPUT%" - (echo angle=0)>> "%GITHUB_OUTPUT%" - echo nofiles=warn>> "%GITHUB_OUTPUT%" - exit /b 0 - - :ARM64 - (echo arch=arm64)>> "%GITHUB_OUTPUT%" - (echo angle=1)>> "%GITHUB_OUTPUT%" - echo nofiles=ignore>> "%GITHUB_OUTPUT%" - echo moredef=-DLOVE_EXTRA_DLLS=%CD%\angle\libEGL.dll;%CD%\angle\libGLESv2.dll>> "%GITHUB_OUTPUT%" - exit /b 0 - - name: Download Windows SDK Setup 10.0.20348 - run: curl -Lo winsdksetup.exe https://go.microsoft.com/fwlink/?linkid=2164145 - - name: Install Debugging Tools for Windows - id: windbg - run: | - setlocal enabledelayedexpansion - start /WAIT %CD%\winsdksetup.exe /features OptionId.WindowsDesktopDebuggers /q /log %CD%\log.txt - echo ERRORLEVEL=!ERRORLEVEL! >> %GITHUB_OUTPUT% - - name: Print Debugging Tools Install Log - if: always() - run: | - type log.txt - exit /b ${{ steps.windbg.outputs.ERRORLEVEL }} - - name: Setup Python 3.10 - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - name: Download source_index.py - run: curl -Lo source_index.py https://gist.github.com/MikuAuahDark/d9c099f5714e09a765496471c2827a55/raw/df34956052035f3473c5f01861dfb53930d06843/source_index.py - - name: Clone Megasource - uses: actions/checkout@v3 - with: - path: megasource - repository: love2d/megasource - ref: 12.x - - id: megasource - name: Get Megasource Commit SHA - shell: python - run: | - import os - import subprocess - - result = subprocess.run("git -C megasource rev-parse HEAD".split(), check=True, capture_output=True, encoding="UTF-8") - commit = result.stdout.split()[0] - with open(os.environ["GITHUB_OUTPUT"], "w", encoding="UTF-8") as f: f.write(f"commit={commit}") - - name: Checkout - uses: actions/checkout@v3 - with: - path: megasource/libs/love - - name: Download ANGLE - uses: robinraju/release-downloader@v1.7 - if: steps.vars.outputs.angle == '1' - with: - repository: MikuAuahDark/angle-winbuild - tag: cr_5249 - fileName: angle-win-${{ steps.vars.outputs.arch }}.zip - tarBall: false - zipBall: false - out-file-path: angle - - name: Extract ANGLE - if: steps.vars.outputs.angle == '1' - working-directory: angle - run: 7z x angle-win-${{ steps.vars.outputs.arch }}.zip - - name: Delete Strawbery Perl - # https://github.com/actions/runner-images/issues/6627 - # In particular, this is not pretty, but even CMAKE_IGNORE_PREFIX_PATH - # cannot help in this case. Delete the whole folder! - run: | - rmdir /s /q C:\Strawberry - exit /b 0 - - name: Configure - env: - CFLAGS: /Zi - CXXFLAGS: /Zi - LDFLAGS: /DEBUG:FULL /OPT:REF /OPT:ICF - run: cmake -Bbuild -Smegasource -T v142 -A ${{ matrix.platform }} --install-prefix %CD%\install -DCMAKE_PDB_OUTPUT_DIRECTORY=%CD%\pdb ${{ steps.vars.outputs.moredef }} - - name: Install - run: cmake --build build --target PACKAGE --config Release -j2 - - name: Copy LuaJIT lua51.pdb - run: | - copy /Y build\libs\LuaJIT\src\lua51.pdb pdb\Release\lua51.pdb - exit /b 0 - - name: Add srcsrv to PATH - run: | - echo C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\srcsrv>>%GITHUB_PATH% - - name: Embed Source Index into PDBs - run: | - python source_index.py ^ - --source %CD%\megasource\libs\love https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }} ^ - --source %CD%\megasource https://raw.githubusercontent.com/love2d/megasource/${{ steps.megasource.outputs.commit }} ^ - --source %CD%\build\libs\LuaJIT https://raw.githubusercontent.com/love2d/megasource/${{ steps.megasource.outputs.commit }}/libs/LuaJIT ^ - pdb\Release\*.pdb - - name: Artifact - uses: actions/upload-artifact@v3 - with: - name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }} - path: | - build/*.zip - build/*.exe - if-no-files-found: ${{ steps.vars.outputs.nofiles }} - - name: Artifact JIT Modules - if: steps.vars.outputs.jitmodules == '1' - uses: actions/upload-artifact@v3 - with: - name: love-windows-jitmodules - path: build/libs/LuaJIT/src/jit/*.lua - - name: Artifact PDB - uses: actions/upload-artifact@v3 - with: - name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg - path: pdb/Release/*.pdb - - name: Install Mesa - run: | - curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z - 7z x mesa.7z -o* - powershell.exe mesa\systemwidedeploy.cmd 1 - - name: Build Test Exe - if: steps.vars.outputs.arch != 'ARM64' - run: cmake --build build --config Release --target install - - name: Run Tests (opengl) - if: steps.vars.outputs.arch != 'ARM64' - run: | - echo 'check dir' - dir - powershell.exe ./install/lovec.exe ./testing/main.lua - # windows opengl test - - name: Love Test Report (opengl) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (opengl) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengl) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-opengl.zip testing/output/ - - name: Artifact Test Output (opengl) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-opengl - path: test-output-windows-opengl.zip - # windows opengles test - - name: Run Tests (opengles) - if: steps.vars.outputs.arch != 'ARM64' - run: | - $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 - powershell.exe ./install/lovec.exe ./testing/main.lua - - name: Love Test Report (opengles) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (opengles) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (opengles) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-opengles.zip testing/output/ - - name: Artifact Test Output (opengles) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-opengles - path: test-output-windows-opengles.zip - - name: Install Vulkan - if: steps.vars.outputs.arch != 'ARM64' - run: | - curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe - ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma - curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip - 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" - reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 - powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary - # windows vulkan tests - - name: Run Tests (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: | - $ENV:LOVE_GRAPHICS_DEBUG=1 - powershell.exe ./install/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan - - name: Love Test Report (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows (vulkan) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-vulkan.zip testing/output - - name: Artifact Test Output (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-vulkan - path: test-output-windows-vulkan.zip - macOS: + macos-latest: runs-on: macos-latest steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Clone Dependencies - uses: actions/checkout@v3 + - name: Download artifact + uses: dawidd6/action-download-artifact@v2 with: - path: apple-dependencies - repository: love2d/love-apple-dependencies - ref: 12.x - - name: Move Dependencies - run: - mv apple-dependencies/macOS/Frameworks platform/xcode/macosx - - name: Build - run: - xcodebuild clean archive -project platform/xcode/love.xcodeproj -scheme love-macosx -configuration Release -archivePath love-macos.xcarchive - - name: Export Archive - run: - xcodebuild -exportArchive -archivePath love-macos.xcarchive -exportPath love-macos -exportOptionsPlist platform/xcode/macosx/macos-copy-app.plist - - name: Zip Archive - run: - ditto -c -k --sequesterRsrc --keepParent love-macos/love.app love-macos.zip - - name: Artifact - uses: actions/upload-artifact@v3 - with: - name: love-macos - path: love-macos.zip - # macos opengl tests - - name: Run Tests - run: love-macos/love.app/Contents/MacOS/love testing/main.lua - - name: Love Test Report - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite MacOS - title: test-report-macos - path: testing/output/lovetest_runAllTests.md - - name: Zip Test Output - run: | - 7z a -tzip test-output-macos-opengl.zip testing/output/ - - name: Artifact Test Output - uses: actions/upload-artifact@v3 - with: - name: test-output-macos-opengl - path: test-output-macos-opengl.zip - iOS-Simulator: - runs-on: macos-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Clone Dependencies - uses: actions/checkout@v3 - with: - path: apple-dependencies - repository: love2d/love-apple-dependencies - ref: 12.x - - name: Move Dependencies - run: | - mv apple-dependencies/iOS/libraries platform/xcode/ios - - name: Build - run: - xcodebuild -project platform/xcode/love.xcodeproj -scheme love-ios -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11' + workflow: ${{ github.event.workflow_run.workflow_id }} + workflow_conclusion: success From 58fa1c8ccddeb09bceaefedebb80782b52ae005f Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:34:53 +0000 Subject: [PATCH 076/409] test the test workflow --- .github/workflows/testsuite.yml | 264 +++++++++++++++++++++++++++++++- 1 file changed, 261 insertions(+), 3 deletions(-) diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml index 4590ad5b2..d0f3fe77f 100644 --- a/.github/workflows/testsuite.yml +++ b/.github/workflows/testsuite.yml @@ -1,5 +1,4 @@ name: testsuite - on: workflow_run: workflows: ["continuous-integration"] @@ -10,8 +9,267 @@ jobs: macos-latest: runs-on: macos-latest steps: - - name: Download artifact + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Download Artifacts From CI uses: dawidd6/action-download-artifact@v2 with: - workflow: ${{ github.event.workflow_run.workflow_id }} + workflow: main.yaml workflow_conclusion: success + name: love-macos + - name: Unzip Love + run: + echo 'check downloaded' + ls +# - name: Run Test Suite +# run: CHECK_PATH/love.app/Contents/MacOS/love ./testing/main.lua +# - name: Love Test Report +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite MacOS +# title: test-report-macos +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output +# run: | +# 7z a -tzip test-output-macos-opengl.zip output/ +# - name: Artifact Test Output +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-macos-opengl +# path: test-output-macos-opengl.zip + windows-latest: + runs-on: windows-latest + env: + ALSOFT_CONF: resources/alsoft.conf + VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json + VULKAN_SDK: C:/VulkanSDK/1.3.231.1 + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Download Artifacts From CI + uses: dawidd6/action-download-artifact@v2 + with: + workflow: main.yaml + workflow_conclusion: success + name: love-windows-x64 + - name: Unzip Love + run: + echo 'check downloaded' + ls +# - name: Install Mesa +# run: | +# curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z +# 7z x mesa.7z -o* +# powershell.exe mesa\systemwidedeploy.cmd 1 +# - name: Run Tests (opengl) +# run: powershell.exe ./CHECK_PATH/lovec.exe ./testing/main.lua +# - name: Love Test Report (opengl) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Windows (opengl) +# title: test-report-windows-opengl +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output (opengl) +# run: | +# 7z a -tzip test-output-windows-opengl.zip output\ +# - name: Artifact Test Output (opengl) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-windows-opengl +# path: test-output-windows-opengl.zip +# - name: Run Tests (opengles) +# run: | +# $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 +# powershell.exe ./CHECK_PATH/lovec.exe ./testing/main.lua +# - name: Love Test Report (opengles) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Windows (opengles) +# title: test-report-windows-opengles +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output (opengles) +# run: | +# 7z a -tzip test-output-windows-opengles.zip output\ +# - name: Artifact Test Output (opengles) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-windows-opengles +# path: test-output-windows-opengles.zip +# - name: Install Vulkan +# run: | +# curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe +# ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma +# curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip +# 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 +# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" +# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" +# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" +# reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 +# powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary +# - name: Run Tests (vulkan) +# run: | +# $ENV:LOVE_GRAPHICS_DEBUG=1 +# powershell.exe ./CHECK_PATH/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan +# - name: Love Test Report (vulkan) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Windows (vulkan) +# title: test-report-windows-vulkan +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output (vulkan) +# run: | +# 7z a -tzip test-output-windows-vulkan.zip output/ +# - name: Artifact Test Output (vulkan) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-windows-vulkan +# path: test-output-windows-vulkan.zip + linux-ubuntu: + runs-on: ubuntu-20.04 + env: + ALSOFT_CONF: resources/alsoft.conf + DISPLAY: :99 + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Download Artifacts From CI + uses: dawidd6/action-download-artifact@v2 + with: + workflow: main.yaml + workflow_conclusion: success + name: love-linux-x86_64.AppImage + - name: Unzip Love + run: + echo 'check downloaded' + ls + echo 'chmod a+x here' +# - name: Update APT +# run: sudo apt-get update +# - name: Install Dependencies +# run: | +# sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \ +# libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \ +# libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \ +# libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ +# libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ +# libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ +# libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ +# libfuse2 wmctrl openbox +# - name: Start xvfb and openbox +# run: | +# echo "Starting XVFB on $DISPLAY" +# Xvfb $DISPLAY -screen 0, 360x240x24 & +# echo "XVFBPID=$!" >> $GITHUB_ENV +# # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) +# sleep 3 +# openbox & +# echo "OPENBOXPID=$!" >> $GITHUB_ENV +# # linux opengl tests +# - name: Run Test Suite (opengl) +# run: | +# CHECK_PATH/love12.AppImage ./testing/main.lua +# - name: Love Test Report (opengl) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Linux +# title: test-report-linux-opengl +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output (opengl) +# run: | +# 7z a -tzip test-output-linux-opengl.zip output/ +# - name: Artifact Test Output (opengl) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-linux-opengl +# path: test-output-linux-opengl.zip +# # linux opengles tests +# - name: Run Test Suite (opengles) +# run: | +# export LOVE_GRAPHICS_USE_OPENGLES=1 +# CHECK_PATH/love12.AppImage ./testing/main.lua +# - name: Love Test Report (opengles) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Linux +# title: test-report-linux-opengles +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output (opengles) +# run: | +# 7z a -tzip test-output-linux-opengles.zip output\ +# - name: Artifact Test Output (opengles) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-linux-opengles +# path: test-output-linux-opengles.zip +# - name: Stop xvfb and openbox +# # should always stop xvfb and openbox even if other steps failed +# if: always() +# run: | +# kill $XVFBPID +# kill $OPENBOXPID + linux-vulkan: + runs-on: ubuntu-22.04 + env: + ALSOFT_CONF: resources/alsoft.conf + DISPLAY: :99 + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Download Artifacts From CI + uses: dawidd6/action-download-artifact@v2 + with: + workflow: main.yaml + workflow_conclusion: success + name: love-linux-x86_64.AppImage + - name: Unzip Love + run: + echo 'check downloaded' + ls + echo 'chmod a+x here' +# - name: Update APT +# run: sudo apt-get update +# - name: Install Dependencies +# run: | +# sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \ +# libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \ +# libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \ +# libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ +# libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ +# libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ +# libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ +# libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ +# vulkan-validationlayers +# - name: Start xvfb and openbox +# run: | +# echo "Starting XVFB on $DISPLAY" +# Xvfb $DISPLAY -screen 0, 360x240x24 & +# echo "XVFBPID=$!" >> $GITHUB_ENV +# # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) +# sleep 3 +# openbox & +# echo "OPENBOXPID=$!" >> $GITHUB_ENV +# # linux vulkan tests +# - name: Run Test Suite (vulkan) +# run: | +# export LOVE_GRAPHICS_DEBUG=1 +# CHECK_PATH/love12.AppImage ./testing/main.lua --runAllTests --renderers vulkan +# - name: Love Test Report (vulkan) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Linux +# title: test-report-linux-vulkan +# path: output/lovetest_runAllTests.md +# - name: Zip Test Output (vulkan) +# run: | +# 7z a -tzip test-output-linux-vulkan.zip output/ +# - name: Artifact Test Output (vulkan) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-linux-vulkan +# path: test-output-linux-vulkan.zip +# - name: Stop xvfb and openbox +# # should always stop xvfb and openbox even if other steps failed +# if: always() +# run: | +# kill $XVFBPID +# kill $OPENBOXPID From 0d338b0c0d3ba3e1cfea46089b4839b1028db924 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:04:49 +0000 Subject: [PATCH 077/409] workflow changes #1 --- .github/workflows/main.yml | 94 ++++++++++- .github/workflows/testsuite.yml | 275 -------------------------------- 2 files changed, 93 insertions(+), 276 deletions(-) delete mode 100644 .github/workflows/testsuite.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f3922d769..d5c967d4f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,9 @@ on: [push, pull_request] jobs: linux-os: runs-on: ubuntu-20.04 + env: + ALSOFT_CONF: resources/alsoft.conf + DISPLAY: :99 steps: - name: Update APT run: sudo apt-get update @@ -16,7 +19,7 @@ jobs: libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ - libcurl4-openssl-dev + libcurl4-openssl-dev libfuse2 wmctrl openbox - name: Checkout love-appimage-source uses: actions/checkout@v3 with: @@ -40,6 +43,42 @@ jobs: run: make LOVE_BRANCH=${{ github.sha }} - name: Print LuaJIT branch run: git -C LuaJIT-v2.1 branch -v + - name: Start xvfb and openbox + run: | + echo "Starting XVFB on $DISPLAY" + Xvfb $DISPLAY -screen 0, 360x240x24 & + echo "XVFBPID=$!" >> $GITHUB_ENV + # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) + sleep 3 + openbox & + echo "OPENBOXPID=$!" >> $GITHUB_ENV + # linux opengl tests + - name: Run Test Suite (opengl) + run: | + echo 'run opengl tests' + ls + ls love2d-${{ github.sha }} + chmod a+x love-${{ github.sha }}.AppImage + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua + - name: Love Test Report (opengl) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-opengl + path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengl) + run: | + 7z a -tzip test-output-linux-opengl.zip output/ + - name: Artifact Test Output (opengl) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-opengl + - name: Stop xvfb and openbox + # should always stop xvfb and openbox even if other steps failed + if: always() + run: | + kill $XVFBPID + kill $OPENBOXPID - name: Artifact uses: actions/upload-artifact@v3 with: @@ -52,6 +91,10 @@ jobs: path: love-${{ github.sha }}.AppImage-debug.tar.gz windows-os: runs-on: windows-latest + env: + ALSOFT_CONF: resources/alsoft.conf + VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json + VULKAN_SDK: C:/VulkanSDK/1.3.231.1 strategy: matrix: platform: [Win32, x64, ARM64] @@ -206,6 +249,37 @@ jobs: with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb + - name: Install Mesa + run: | + curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z + 7z x mesa.7z -o* + powershell.exe mesa\systemwidedeploy.cmd 1 + - name: Build Test Exe + if: steps.vars.outputs.arch != 'ARM64' + run: cmake --build build --config Release --target install + - name: Run Tests (opengl) + if: steps.vars.outputs.arch != 'ARM64' + run: | + echo 'check dir' + ls + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua + - name: Love Test Report (opengl) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (opengl) + title: test-report-windows-opengl + path: megasource/libs/love/testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengl) + if: steps.vars.outputs.arch != 'ARM64' + run: | + 7z a -tzip test-output-windows-opengl.zip output\ + - name: Artifact Test Output (opengl) + if: steps.vars.outputs.arch != 'ARM64' + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-opengl + path: test-output-windows-opengl.zip macOS: runs-on: macos-latest steps: @@ -234,6 +308,24 @@ jobs: with: name: love-macos path: love-macos.zip + - name: Run Test Suite + run: | + ls + love-macos/love.app/Contents/MacOS/love ./testing/main.lua + - name: Love Test Report + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite MacOS + title: test-report-macos + path: testing/output/lovetest_runAllTests.md + - name: Zip Test Output + run: | + 7z a -tzip test-output-macos-opengl.zip output/ + - name: Artifact Test Output + uses: actions/upload-artifact@v3 + with: + name: test-output-macos-opengl + path: test-output-macos-opengl.zip iOS-Simulator: runs-on: macos-latest steps: diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml deleted file mode 100644 index d0f3fe77f..000000000 --- a/.github/workflows/testsuite.yml +++ /dev/null @@ -1,275 +0,0 @@ -name: testsuite -on: - workflow_run: - workflows: ["continuous-integration"] - types: - - completed - -jobs: - macos-latest: - runs-on: macos-latest - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - name: Download Artifacts From CI - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yaml - workflow_conclusion: success - name: love-macos - - name: Unzip Love - run: - echo 'check downloaded' - ls -# - name: Run Test Suite -# run: CHECK_PATH/love.app/Contents/MacOS/love ./testing/main.lua -# - name: Love Test Report -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite MacOS -# title: test-report-macos -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output -# run: | -# 7z a -tzip test-output-macos-opengl.zip output/ -# - name: Artifact Test Output -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-macos-opengl -# path: test-output-macos-opengl.zip - windows-latest: - runs-on: windows-latest - env: - ALSOFT_CONF: resources/alsoft.conf - VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json - VULKAN_SDK: C:/VulkanSDK/1.3.231.1 - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - name: Download Artifacts From CI - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yaml - workflow_conclusion: success - name: love-windows-x64 - - name: Unzip Love - run: - echo 'check downloaded' - ls -# - name: Install Mesa -# run: | -# curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z -# 7z x mesa.7z -o* -# powershell.exe mesa\systemwidedeploy.cmd 1 -# - name: Run Tests (opengl) -# run: powershell.exe ./CHECK_PATH/lovec.exe ./testing/main.lua -# - name: Love Test Report (opengl) -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite Windows (opengl) -# title: test-report-windows-opengl -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output (opengl) -# run: | -# 7z a -tzip test-output-windows-opengl.zip output\ -# - name: Artifact Test Output (opengl) -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-windows-opengl -# path: test-output-windows-opengl.zip -# - name: Run Tests (opengles) -# run: | -# $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 -# powershell.exe ./CHECK_PATH/lovec.exe ./testing/main.lua -# - name: Love Test Report (opengles) -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite Windows (opengles) -# title: test-report-windows-opengles -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output (opengles) -# run: | -# 7z a -tzip test-output-windows-opengles.zip output\ -# - name: Artifact Test Output (opengles) -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-windows-opengles -# path: test-output-windows-opengles.zip -# - name: Install Vulkan -# run: | -# curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe -# ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma -# curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip -# 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 -# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" -# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" -# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" -# reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 -# powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary -# - name: Run Tests (vulkan) -# run: | -# $ENV:LOVE_GRAPHICS_DEBUG=1 -# powershell.exe ./CHECK_PATH/lovec.exe ./testing/main.lua --runAllTests --renderers vulkan -# - name: Love Test Report (vulkan) -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite Windows (vulkan) -# title: test-report-windows-vulkan -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output (vulkan) -# run: | -# 7z a -tzip test-output-windows-vulkan.zip output/ -# - name: Artifact Test Output (vulkan) -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-windows-vulkan -# path: test-output-windows-vulkan.zip - linux-ubuntu: - runs-on: ubuntu-20.04 - env: - ALSOFT_CONF: resources/alsoft.conf - DISPLAY: :99 - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - name: Download Artifacts From CI - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yaml - workflow_conclusion: success - name: love-linux-x86_64.AppImage - - name: Unzip Love - run: - echo 'check downloaded' - ls - echo 'chmod a+x here' -# - name: Update APT -# run: sudo apt-get update -# - name: Install Dependencies -# run: | -# sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \ -# libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \ -# libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \ -# libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ -# libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ -# libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ -# libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ -# libfuse2 wmctrl openbox -# - name: Start xvfb and openbox -# run: | -# echo "Starting XVFB on $DISPLAY" -# Xvfb $DISPLAY -screen 0, 360x240x24 & -# echo "XVFBPID=$!" >> $GITHUB_ENV -# # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) -# sleep 3 -# openbox & -# echo "OPENBOXPID=$!" >> $GITHUB_ENV -# # linux opengl tests -# - name: Run Test Suite (opengl) -# run: | -# CHECK_PATH/love12.AppImage ./testing/main.lua -# - name: Love Test Report (opengl) -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite Linux -# title: test-report-linux-opengl -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output (opengl) -# run: | -# 7z a -tzip test-output-linux-opengl.zip output/ -# - name: Artifact Test Output (opengl) -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-linux-opengl -# path: test-output-linux-opengl.zip -# # linux opengles tests -# - name: Run Test Suite (opengles) -# run: | -# export LOVE_GRAPHICS_USE_OPENGLES=1 -# CHECK_PATH/love12.AppImage ./testing/main.lua -# - name: Love Test Report (opengles) -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite Linux -# title: test-report-linux-opengles -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output (opengles) -# run: | -# 7z a -tzip test-output-linux-opengles.zip output\ -# - name: Artifact Test Output (opengles) -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-linux-opengles -# path: test-output-linux-opengles.zip -# - name: Stop xvfb and openbox -# # should always stop xvfb and openbox even if other steps failed -# if: always() -# run: | -# kill $XVFBPID -# kill $OPENBOXPID - linux-vulkan: - runs-on: ubuntu-22.04 - env: - ALSOFT_CONF: resources/alsoft.conf - DISPLAY: :99 - steps: - - name: Checkout Repo - uses: actions/checkout@v4 - - name: Download Artifacts From CI - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yaml - workflow_conclusion: success - name: love-linux-x86_64.AppImage - - name: Unzip Love - run: - echo 'check downloaded' - ls - echo 'chmod a+x here' -# - name: Update APT -# run: sudo apt-get update -# - name: Install Dependencies -# run: | -# sudo apt-get install --assume-yes build-essential git make cmake autoconf automake \ -# libtool pkg-config libasound2-dev libpulse-dev libaudio-dev \ -# libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \ -# libxfixes-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev \ -# libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ -# libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ -# libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ -# libfuse2 wmctrl openbox mesa-vulkan-drivers libvulkan1 vulkan-tools \ -# vulkan-validationlayers -# - name: Start xvfb and openbox -# run: | -# echo "Starting XVFB on $DISPLAY" -# Xvfb $DISPLAY -screen 0, 360x240x24 & -# echo "XVFBPID=$!" >> $GITHUB_ENV -# # wait for xvfb to startup (3s is the same amount xvfb-run waits by default) -# sleep 3 -# openbox & -# echo "OPENBOXPID=$!" >> $GITHUB_ENV -# # linux vulkan tests -# - name: Run Test Suite (vulkan) -# run: | -# export LOVE_GRAPHICS_DEBUG=1 -# CHECK_PATH/love12.AppImage ./testing/main.lua --runAllTests --renderers vulkan -# - name: Love Test Report (vulkan) -# uses: ellraiser/love-test-report@main -# with: -# name: Love Testsuite Linux -# title: test-report-linux-vulkan -# path: output/lovetest_runAllTests.md -# - name: Zip Test Output (vulkan) -# run: | -# 7z a -tzip test-output-linux-vulkan.zip output/ -# - name: Artifact Test Output (vulkan) -# uses: actions/upload-artifact@v3 -# with: -# name: test-output-linux-vulkan -# path: test-output-linux-vulkan.zip -# - name: Stop xvfb and openbox -# # should always stop xvfb and openbox even if other steps failed -# if: always() -# run: | -# kill $XVFBPID -# kill $OPENBOXPID From 5155a96540bed29229ccdbc9ba90d11436ef3caa Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:18:43 +0000 Subject: [PATCH 078/409] fix upload paths --- .github/workflows/main.yml | 55 +++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d5c967d4f..1e6285c0e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,6 +43,7 @@ jobs: run: make LOVE_BRANCH=${{ github.sha }} - name: Print LuaJIT branch run: git -C LuaJIT-v2.1 branch -v + # start xvfb for test running - name: Start xvfb and openbox run: | echo "Starting XVFB on $DISPLAY" @@ -55,9 +56,6 @@ jobs: # linux opengl tests - name: Run Test Suite (opengl) run: | - echo 'run opengl tests' - ls - ls love2d-${{ github.sha }} chmod a+x love-${{ github.sha }}.AppImage ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua - name: Love Test Report (opengl) @@ -68,11 +66,29 @@ jobs: path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md - name: Zip Test Output (opengl) run: | - 7z a -tzip test-output-linux-opengl.zip output/ + 7z a -tzip test-output-linux-opengl.zip love2d-${{ github.sha }}/testing/output/ - name: Artifact Test Output (opengl) uses: actions/upload-artifact@v3 with: name: test-output-linux-opengl + # linux opengles tests + - name: Run Test Suite (opengles) + run: | + export LOVE_GRAPHICS_USE_OPENGLES=1 + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua + - name: Love Test Report (opengles) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-opengles + path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengles) + run: | + 7z a -tzip test-output-linux-opengles.zip love2d-${{ github.sha }}/testing/output/ + - name: Artifact Test Output (opengles) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-opengles - name: Stop xvfb and openbox # should always stop xvfb and openbox even if other steps failed if: always() @@ -249,14 +265,17 @@ jobs: with: name: love-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-dbg path: pdb/Release/*.pdb + # install mesa for graphic tests - name: Install Mesa run: | curl -L --output mesa.7z --url https://github.com/pal1000/mesa-dist-win/releases/download/23.2.1/mesa3d-23.2.1-release-msvc.7z 7z x mesa.7z -o* powershell.exe mesa\systemwidedeploy.cmd 1 + # build love to use for the tests - name: Build Test Exe if: steps.vars.outputs.arch != 'ARM64' run: cmake --build build --config Release --target install + # windows opengl tests - name: Run Tests (opengl) if: steps.vars.outputs.arch != 'ARM64' run: | @@ -273,13 +292,36 @@ jobs: - name: Zip Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' run: | - 7z a -tzip test-output-windows-opengl.zip output\ + 7z a -tzip test-output-windows-opengl.zip megasource/libs/love/testing/output/ - name: Artifact Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 with: name: test-output-windows-opengl path: test-output-windows-opengl.zip + # windows opengles tests + - name: Run Tests (opengles) + if: steps.vars.outputs.arch != 'ARM64' + run: | + $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua + - name: Love Test Report (opengles) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows (opengles) + title: test-report-windows-opengles + path: megasource/libs/love/testing/output/lovetest_runAllTests.md + - name: Zip Test Output (opengles) + if: steps.vars.outputs.arch != 'ARM64' + run: | + 7z a -tzip test-output-windows-opengles.zip megasource/libs/love/testing/output/ + - name: Artifact Test Output (opengles) + if: steps.vars.outputs.arch != 'ARM64' + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-opengles + path: test-output-windows-opengles.zip macOS: runs-on: macos-latest steps: @@ -308,6 +350,7 @@ jobs: with: name: love-macos path: love-macos.zip + # macos opengl tests (metal not supported on runners) - name: Run Test Suite run: | ls @@ -320,7 +363,7 @@ jobs: path: testing/output/lovetest_runAllTests.md - name: Zip Test Output run: | - 7z a -tzip test-output-macos-opengl.zip output/ + 7z a -tzip test-output-macos-opengl.zip ./testing/output/ - name: Artifact Test Output uses: actions/upload-artifact@v3 with: From 38ef55ee32430c2ed4af41458d28b1dfc9aa1cf3 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:38:35 +0000 Subject: [PATCH 079/409] add arch+compat to win test output --- .github/workflows/main.yml | 78 +++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1e6285c0e..e3e65f063 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ on: [push, pull_request] jobs: linux-os: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: ALSOFT_CONF: resources/alsoft.conf DISPLAY: :99 @@ -19,7 +19,8 @@ jobs: libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ - libcurl4-openssl-dev libfuse2 wmctrl openbox + libcurl4-openssl-dev libfuse2 wmctrl openbox mesa-vulkan-drivers \ + libvulkan1 vulkan-tools vulkan-validationlayers - name: Checkout love-appimage-source uses: actions/checkout@v3 with: @@ -71,6 +72,7 @@ jobs: uses: actions/upload-artifact@v3 with: name: test-output-linux-opengl + path: test-output-linux-opengl.zip # linux opengles tests - name: Run Test Suite (opengles) run: | @@ -89,6 +91,26 @@ jobs: uses: actions/upload-artifact@v3 with: name: test-output-linux-opengles + path: test-output-linux-opengles.zip + # linux vulkan tests + - name: Run Test Suite (vulkan) + run: | + export LOVE_GRAPHICS_DEBUG=1 + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --renderers vulkan + - name: Love Test Report (vulkan) + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Linux + title: test-report-linux-vulkan + path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md + - name: Zip Test Output (vulkan) + run: | + 7z a -tzip test-output-linux-vulkan.zip love2d-${{ github.sha }}/testing/output/ + - name: Artifact Test Output (vulkan) + uses: actions/upload-artifact@v3 + with: + name: test-output-linux-vulkan + path: test-output-linux-vulkan.zip - name: Stop xvfb and openbox # should always stop xvfb and openbox even if other steps failed if: always() @@ -286,8 +308,8 @@ jobs: if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: - name: Love Testsuite Windows (opengl) - title: test-report-windows-opengl + name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (opengl) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl path: megasource/libs/love/testing/output/lovetest_runAllTests.md - name: Zip Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' @@ -297,8 +319,8 @@ jobs: if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 with: - name: test-output-windows-opengl - path: test-output-windows-opengl.zip + name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl + path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl.zip # windows opengles tests - name: Run Tests (opengles) if: steps.vars.outputs.arch != 'ARM64' @@ -309,8 +331,8 @@ jobs: if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main with: - name: Love Testsuite Windows (opengles) - title: test-report-windows-opengles + name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (opengles) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles path: megasource/libs/love/testing/output/lovetest_runAllTests.md - name: Zip Test Output (opengles) if: steps.vars.outputs.arch != 'ARM64' @@ -320,8 +342,44 @@ jobs: if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 with: - name: test-output-windows-opengles - path: test-output-windows-opengles.zip + name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles + path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles.zip + # install vulkan + - name: Install Vulkan + if: steps.vars.outputs.arch != 'ARM64' + run: | + curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe + ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma + curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip + 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" + copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" + reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 + powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary + # windows vulkan tests + - name: Run Tests (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + run: | + $ENV:LOVE_GRAPHICS_DEBUG=1 + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --renderers vulkan + - name: Love Test Report (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + uses: ellraiser/love-test-report@main + with: + name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (vulkan) + title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan + path: megasource/libs/love/testing/output/lovetest_runAllTests.md + - name: Zip Test Output (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + run: | + 7z a -tzip test-output-windows-vulkan.zip megasource/libs/love/testing/output/ + - name: Artifact Test Output (vulkan) + if: steps.vars.outputs.arch != 'ARM64' + uses: actions/upload-artifact@v3 + with: + name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan + path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan.zip macOS: runs-on: macos-latest steps: From 46d45678af64f53044918ca32ae1128f6c71055b Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:42:04 +0000 Subject: [PATCH 080/409] invalid lib linux --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e3e65f063..66b25cf3f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev \ libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev \ libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev \ - libcurl4-openssl-dev libfuse2 wmctrl openbox mesa-vulkan-drivers \ + libcurl4-openssl-dev libfuse2 wmctrl openbox mesa-vulkan-drivers \ libvulkan1 vulkan-tools vulkan-validationlayers - name: Checkout love-appimage-source uses: actions/checkout@v3 From b1fe623358ead2056e8baa09bd2c1b02793ae10d Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 20:53:42 +0000 Subject: [PATCH 081/409] turn off vulkan tests for now --- .github/workflows/main.yml | 110 ++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 66b25cf3f..d73431727 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -92,25 +92,25 @@ jobs: with: name: test-output-linux-opengles path: test-output-linux-opengles.zip - # linux vulkan tests - - name: Run Test Suite (vulkan) - run: | - export LOVE_GRAPHICS_DEBUG=1 - ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --renderers vulkan - - name: Love Test Report (vulkan) - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Linux - title: test-report-linux-vulkan - path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md - - name: Zip Test Output (vulkan) - run: | - 7z a -tzip test-output-linux-vulkan.zip love2d-${{ github.sha }}/testing/output/ - - name: Artifact Test Output (vulkan) - uses: actions/upload-artifact@v3 - with: - name: test-output-linux-vulkan - path: test-output-linux-vulkan.zip +# # linux vulkan tests +# - name: Run Test Suite (vulkan) +# run: | +# export LOVE_GRAPHICS_DEBUG=1 +# ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --renderers vulkan +# - name: Love Test Report (vulkan) +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Linux +# title: test-report-linux-vulkan +# path: love2d-${{ github.sha }}/testing/output/lovetest_runAllTests.md +# - name: Zip Test Output (vulkan) +# run: | +# 7z a -tzip test-output-linux-vulkan.zip love2d-${{ github.sha }}/testing/output/ +# - name: Artifact Test Output (vulkan) +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-linux-vulkan +# path: test-output-linux-vulkan.zip - name: Stop xvfb and openbox # should always stop xvfb and openbox even if other steps failed if: always() @@ -344,42 +344,42 @@ jobs: with: name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles.zip - # install vulkan - - name: Install Vulkan - if: steps.vars.outputs.arch != 'ARM64' - run: | - curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe - ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma - curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip - 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" - copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" - reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 - powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary - # windows vulkan tests - - name: Run Tests (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: | - $ENV:LOVE_GRAPHICS_DEBUG=1 - powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --renderers vulkan - - name: Love Test Report (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: ellraiser/love-test-report@main - with: - name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (vulkan) - title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan - path: megasource/libs/love/testing/output/lovetest_runAllTests.md - - name: Zip Test Output (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - run: | - 7z a -tzip test-output-windows-vulkan.zip megasource/libs/love/testing/output/ - - name: Artifact Test Output (vulkan) - if: steps.vars.outputs.arch != 'ARM64' - uses: actions/upload-artifact@v3 - with: - name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan - path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan.zip +# # install vulkan +# - name: Install Vulkan +# if: steps.vars.outputs.arch != 'ARM64' +# run: | +# curl -L --show-error --output VulkanSDK.exe https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/VulkanSDK-1.3.231.1-Installer.exe +# ./VulkanSDK.exe --root C:/VulkanSDK/1.3.231.1 --accept-licenses --default-answer --confirm-command install com.lunarg.vulkan.core com.lunarg.vulkan.vma +# curl -L --show-error --output vulkan-runtime.zip https://sdk.lunarg.com/sdk/download/1.3.231.1/windows/vulkan-runtime-components.zip +# 7z e vulkan-runtime.zip -o"C:/VulkanSDK/1.3.231.1/runtime/x64" */x64 +# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "mesa/x64" +# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "C:/Windows/System32" +# copy "C:/VulkanSDK/1.3.231.1/runtime/x64/vulkan-1.dll" "love-12.0-win64/love-12.0-win64" +# reg add HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers /v "${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json" /t REG_DWORD /d 0 +# powershell.exe C:/VulkanSDK/1.3.231.1/runtime/x64/vulkaninfo.exe --summary +# # windows vulkan tests +# - name: Run Tests (vulkan) +# if: steps.vars.outputs.arch != 'ARM64' +# run: | +# $ENV:LOVE_GRAPHICS_DEBUG=1 +# powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --renderers vulkan +# - name: Love Test Report (vulkan) +# if: steps.vars.outputs.arch != 'ARM64' +# uses: ellraiser/love-test-report@main +# with: +# name: Love Testsuite Windows ${{ steps.vars.outputs.arch }} ${{ steps.vars.outputs.compatname }} (vulkan) +# title: test-report-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan +# path: megasource/libs/love/testing/output/lovetest_runAllTests.md +# - name: Zip Test Output (vulkan) +# if: steps.vars.outputs.arch != 'ARM64' +# run: | +# 7z a -tzip test-output-windows-vulkan.zip megasource/libs/love/testing/output/ +# - name: Artifact Test Output (vulkan) +# if: steps.vars.outputs.arch != 'ARM64' +# uses: actions/upload-artifact@v3 +# with: +# name: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan +# path: test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan.zip macOS: runs-on: macos-latest steps: From 333169eb0f07e712c58c395e09d7711085785e47 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:22:10 +0000 Subject: [PATCH 082/409] fix alsoft path --- .github/workflows/main.yml | 10 +++++----- testing/tests/video.lua | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d73431727..2bd4ed7a4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: linux-os: runs-on: ubuntu-22.04 env: - ALSOFT_CONF: resources/alsoft.conf + ALSOFT_CONF: testing/resources/alsoft.conf DISPLAY: :99 steps: - name: Update APT @@ -130,7 +130,7 @@ jobs: windows-os: runs-on: windows-latest env: - ALSOFT_CONF: resources/alsoft.conf + ALSOFT_CONF: testing/resources/alsoft.conf VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json VULKAN_SDK: C:/VulkanSDK/1.3.231.1 strategy: @@ -314,7 +314,7 @@ jobs: - name: Zip Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' run: | - 7z a -tzip test-output-windows-opengl.zip megasource/libs/love/testing/output/ + 7z a -tzip test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengl.zip megasource/libs/love/testing/output/ - name: Artifact Test Output (opengl) if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 @@ -337,7 +337,7 @@ jobs: - name: Zip Test Output (opengles) if: steps.vars.outputs.arch != 'ARM64' run: | - 7z a -tzip test-output-windows-opengles.zip megasource/libs/love/testing/output/ + 7z a -tzip test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-opengles.zip megasource/libs/love/testing/output/ - name: Artifact Test Output (opengles) if: steps.vars.outputs.arch != 'ARM64' uses: actions/upload-artifact@v3 @@ -373,7 +373,7 @@ jobs: # - name: Zip Test Output (vulkan) # if: steps.vars.outputs.arch != 'ARM64' # run: | -# 7z a -tzip test-output-windows-vulkan.zip megasource/libs/love/testing/output/ +# 7z a -tzip test-output-windows-${{ steps.vars.outputs.arch }}${{ steps.vars.outputs.compatname }}-vulkan.zip megasource/libs/love/testing/output/ # - name: Artifact Test Output (vulkan) # if: steps.vars.outputs.arch != 'ARM64' # uses: actions/upload-artifact@v3 diff --git a/testing/tests/video.lua b/testing/tests/video.lua index 06b4eea7c..42879712d 100644 --- a/testing/tests/video.lua +++ b/testing/tests/video.lua @@ -20,7 +20,7 @@ love.test.video.VideoStream = function(test) video:play() test:assertEquals(true, video:isPlaying(), 'check now playing') video:seek(0.3) - test:assertEquals(0.3, video:tell(), 'check seek/tell') + test:assertEquals(3, math.floor(video:tell()*10), 'check seek/tell') video:rewind() test:assertEquals(0, video:tell(), 'check rewind') video:pause() From c89e7930ba30c8ad4213fd55108393f5a85b6eff Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:33:11 +0000 Subject: [PATCH 083/409] alsoft relative to checkout --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2bd4ed7a4..78891f95e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: linux-os: runs-on: ubuntu-22.04 env: - ALSOFT_CONF: testing/resources/alsoft.conf + ALSOFT_CONF: love2d-${{ github.sha }}/testing/resources/alsoft.conf DISPLAY: :99 steps: - name: Update APT @@ -130,7 +130,7 @@ jobs: windows-os: runs-on: windows-latest env: - ALSOFT_CONF: testing/resources/alsoft.conf + ALSOFT_CONF: megasource/libs/love/testing/resources/alsoft.conf VK_ICD_FILENAMES: ${{ github.workspace }}\mesa\x64\lvp_icd.x86_64.json VULKAN_SDK: C:/VulkanSDK/1.3.231.1 strategy: From 357b005e5332d7fca847a40eac5b1d263e6e7398 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Tue, 14 Nov 2023 23:21:28 +0000 Subject: [PATCH 084/409] fix test.audio.Source --- testing/tests/audio.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/tests/audio.lua b/testing/tests/audio.lua index 436d5b6e7..464562943 100644 --- a/testing/tests/audio.lua +++ b/testing/tests/audio.lua @@ -144,14 +144,14 @@ love.test.audio.Source = function(test) type = 'flanger', volume = 10 }) - local seteffect, err = effsource:setEffect('flanger', { + local seteffect, err = effsource:setEffect('testeffect', { type = 'highpass', volume = 0.3, lowgain = 0.1 }) -- both these fail on 12 using stereo or mono, no err test:assertEquals(true, seteffect, 'check effect was applied') - local filtersettings = effsource:getEffect('chorus', {}) + local filtersettings = effsource:getEffect('effectthatdoesntexist', {}) test:assertNotNil(filtersettings) end From ae465f8e4b598401ce0a1dd6aaf402a4bfcb6e11 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Wed, 15 Nov 2023 12:16:19 +0800 Subject: [PATCH 085/409] Insert Android-specific changelog. --- changes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changes.txt b/changes.txt index ffd39733a..02f285430 100644 --- a/changes.txt +++ b/changes.txt @@ -3,6 +3,7 @@ LOVE 11.5 [Mysterious Mysteries] Released: N/A +* Added "LÖVE Loader" launcher on Android for easier loading of .love files. * Fixed inconsistent and buggy behaviour of 'pairs' by updating LuaJIT. * Fixed "unexpected alignment" errors when running love on some 32 bit Linux systems. * Fixed running fused games on Windows when the executable has been code-signed. From 81393b9aede340d59e2e403b2ec737c7210ad659 Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Wed, 15 Nov 2023 12:19:06 +0800 Subject: [PATCH 086/409] Android: Fixed invalid JNIEnv* pointer when starting up love.filesystem for 2nd time. --- src/common/android.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/common/android.cpp b/src/common/android.cpp index a0a1f4444..c10ef99dc 100644 --- a/src/common/android.cpp +++ b/src/common/android.cpp @@ -806,10 +806,9 @@ const char *getCRequirePath() const char *getArg0() { - static PHYSFS_AndroidInit androidInit = { - SDL_AndroidGetJNIEnv(), - SDL_AndroidGetActivity() - }; + static PHYSFS_AndroidInit androidInit = {nullptr, nullptr}; + androidInit.jnienv = SDL_AndroidGetJNIEnv(); + androidInit.context = SDL_AndroidGetActivity(); return (const char *) &androidInit; } From af4c50a4ceeea5b3cff0f371853e3bc4e8992ad0 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Wed, 15 Nov 2023 09:06:16 +0000 Subject: [PATCH 087/409] skip test.audio.RecordingDevice on CI --- .github/workflows/main.yml | 14 +++++++------- testing/tests/audio.lua | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 78891f95e..098ef32e7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -58,7 +58,7 @@ jobs: - name: Run Test Suite (opengl) run: | chmod a+x love-${{ github.sha }}.AppImage - ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --isRunner - name: Love Test Report (opengl) uses: ellraiser/love-test-report@main with: @@ -77,7 +77,7 @@ jobs: - name: Run Test Suite (opengles) run: | export LOVE_GRAPHICS_USE_OPENGLES=1 - ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua + ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --isRunner - name: Love Test Report (opengles) uses: ellraiser/love-test-report@main with: @@ -96,7 +96,7 @@ jobs: # - name: Run Test Suite (vulkan) # run: | # export LOVE_GRAPHICS_DEBUG=1 -# ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --renderers vulkan +# ./love-${{ github.sha }}.AppImage love2d-${{ github.sha }}/testing/main.lua --runAllTests --isRunner --renderers vulkan # - name: Love Test Report (vulkan) # uses: ellraiser/love-test-report@main # with: @@ -303,7 +303,7 @@ jobs: run: | echo 'check dir' ls - powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --isRunner - name: Love Test Report (opengl) if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main @@ -326,7 +326,7 @@ jobs: if: steps.vars.outputs.arch != 'ARM64' run: | $ENV:LOVE_GRAPHICS_USE_OPENGLES=1 - powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua + powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --isRunner - name: Love Test Report (opengles) if: steps.vars.outputs.arch != 'ARM64' uses: ellraiser/love-test-report@main @@ -362,7 +362,7 @@ jobs: # if: steps.vars.outputs.arch != 'ARM64' # run: | # $ENV:LOVE_GRAPHICS_DEBUG=1 -# powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --renderers vulkan +# powershell.exe ./install/lovec.exe ./megasource/libs/love/testing/main.lua --runAllTests --isRunner --renderers vulkan # - name: Love Test Report (vulkan) # if: steps.vars.outputs.arch != 'ARM64' # uses: ellraiser/love-test-report@main @@ -412,7 +412,7 @@ jobs: - name: Run Test Suite run: | ls - love-macos/love.app/Contents/MacOS/love ./testing/main.lua + love-macos/love.app/Contents/MacOS/love ./testing/main.lua --runAllTests --isRunner - name: Love Test Report uses: ellraiser/love-test-report@main with: diff --git a/testing/tests/audio.lua b/testing/tests/audio.lua index 464562943..bf36b1187 100644 --- a/testing/tests/audio.lua +++ b/testing/tests/audio.lua @@ -10,6 +10,9 @@ -- RecordingDevice (love.audio.getRecordingDevices) love.test.audio.RecordingDevice = function(test) + if GITHUB_RUNNER == true then + return test:skipTest('cant emulate recording devices in CI') + end -- check devices first local devices = love.audio.getRecordingDevices() if #devices == 0 then From ad44eb4fd7a654a043ea6acfb98b2333d1a7a000 Mon Sep 17 00:00:00 2001 From: ell <77150506+ellraiser@users.noreply.github.com> Date: Wed, 15 Nov 2023 19:32:39 +0000 Subject: [PATCH 088/409] more graphics class tests - added graphics.Canvas, graphics.Font, graphics.Image, graphics.Quad, graphics.Shader and graphics.Text - removed rogue resource img - removed event wait test placeholder - updated todo list --- testing/examples/lovetest_runAllTests.html | 2 +- testing/examples/lovetest_runAllTests.md | 40 +- testing/examples/lovetest_runAllTests.xml | 578 +++++++++--------- .../expected/love.test.graphics.Font-1.png | Bin 0 -> 102 bytes .../expected/love.test.graphics.Font-2.png | Bin 0 -> 104 bytes .../expected/love.test.graphics.Image-1.png | Bin 0 -> 375 bytes .../expected/love.test.graphics.Quad-1.png | Bin 0 -> 265 bytes .../expected/love.test.graphics.Shader-1.png | Bin 0 -> 114 bytes .../expected/love.test.graphics.Text-1.png | Bin 0 -> 449 bytes .../love.test.graphics.setColorMask-1.png | Bin 99 -> 84 bytes testing/readme.md | 30 +- testing/resources/font-letters-ab.png | Bin 0 -> 146 bytes testing/resources/font-letters-cd.png | Bin 0 -> 146 bytes .../love_test_graphics_rectangle_expected.png | Bin 135 -> 0 bytes testing/tests/event.lua | 2 +- testing/tests/graphics.lua | 359 ++++++++++- 16 files changed, 649 insertions(+), 362 deletions(-) create mode 100644 testing/output/expected/love.test.graphics.Font-1.png create mode 100644 testing/output/expected/love.test.graphics.Font-2.png create mode 100644 testing/output/expected/love.test.graphics.Image-1.png create mode 100644 testing/output/expected/love.test.graphics.Quad-1.png create mode 100644 testing/output/expected/love.test.graphics.Shader-1.png create mode 100644 testing/output/expected/love.test.graphics.Text-1.png create mode 100644 testing/resources/font-letters-ab.png create mode 100644 testing/resources/font-letters-cd.png delete mode 100644 testing/resources/love_test_graphics_rectangle_expected.png diff --git a/testing/examples/lovetest_runAllTests.html b/testing/examples/lovetest_runAllTests.html index 5a0be8304..41462203f 100644 --- a/testing/examples/lovetest_runAllTests.html +++ b/testing/examples/lovetest_runAllTests.html @@ -1 +1 @@ -

🔴 love.test

  • 🟢 275 Tests
  • 🔴 2 Failures
  • 🟡 28 Skipped
  • 16.781s


🔴 love.audio

  • 🟢 27 Tests
  • 🔴 1 Failures
  • 🟡 0 Skipped
  • 4.898s


    • MethodTimeDetails
      🟢RecordingDevice4.419s
      🔴Source0.019sassert 53 [check effect was applied] expected 'true' got 'false'
      🟢getActiveEffects0.013s
      🟢getActiveSourceCount0.018s
      🟢getDistanceModel0.018s
      🟢getDopplerScale0.019s
      🟢getEffect0.018s
      🟢getMaxSceneEffects0.017s
      🟢getMaxSourceEffects0.016s
      🟢getOrientation0.018s
      🟢getPosition0.017s
      🟢getRecordingDevices0.017s
      🟢getVelocity0.018s
      🟢getVolume0.018s
      🟢isEffectsSupported0.017s
      🟢newQueueableSource0.016s
      🟢newSource0.019s
      🟢pause0.019s
      🟢play0.019s
      🟢setDistanceModel0.019s
      🟢setDopplerScale0.018s
      🟢setEffect0.017s
      🟢setMixWithSystem0.017s
      🟢setOrientation0.019s
      🟢setPosition0.019s
      🟢setVelocity0.018s
      🟢setVolume0.017s
      🟢stop0.019s

      🟢 love.data

      • 🟢 12 Tests
      • 🔴 0 Failures
      • 🟡 0 Skipped
      • 0.213s


        • MethodTimeDetails
          🟢ByteData0.017s
          🟢CompressedData0.017s
          🟢compress0.018s
          🟢decode0.018s
          🟢decompress0.018s
          🟢encode0.018s
          🟢getPackedSize0.018s
          🟢hash0.019s
          🟢newByteData0.017s
          🟢newDataView0.017s
          🟢pack0.017s
          🟢unpack0.018s

          🟢 love.event

          • 🟢 4 Tests
          • 🔴 0 Failures
          • 🟡 2 Skipped
          • 0.103s


            • MethodTimeDetails
              🟢clear0.015s
              🟢poll0.017s
              🟡pump0.018sused internally
              🟢push0.018s
              🟢quit0.018s
              🟡wait0.017stest class needs writing

              🟢 love.filesystem

              • 🟢 29 Tests
              • 🔴 0 Failures
              • 🟡 2 Skipped
              • 0.561s


                • MethodTimeDetails
                  🟢File0.018s
                  🟢FileData0.019s
                  🟢append0.020s
                  🟢areSymlinksEnabled0.017s
                  🟢createDirectory0.019s
                  🟢getAppdataDirectory0.018s
                  🟢getCRequirePath0.017s
                  🟢getDirectoryItems0.018s
                  🟢getIdentity0.018s
                  🟢getInfo0.019s
                  🟢getRealDirectory0.018s
                  🟢getRequirePath0.017s
                  🟢getSaveDirectory0.017s
                  🟡getSource0.016sused internally
                  🟢getSourceBaseDirectory0.018s
                  🟢getUserDirectory0.017s
                  🟢getWorkingDirectory0.018s
                  🟢isFused0.018s
                  🟢lines0.022s
                  🟢load0.017s
                  🟢mount0.018s
                  🟢newFileData0.018s
                  🟢openFile0.018s
                  🟢read0.018s
                  🟢remove0.018s
                  🟢setCRequirePath0.018s
                  🟢setIdentity0.019s
                  🟢setRequirePath0.019s
                  🟡setSource0.017sused internally
                  🟢unmount0.018s
                  🟢write0.019s

                  🔴 love.font

                  • 🟢 6 Tests
                  • 🔴 1 Failures
                  • 🟡 0 Skipped
                  • 0.123s


                    • MethodTimeDetails
                      🔴GlyphData0.017sassert 8 [check glyph number] expected '97' got '0'
                      🟢Rasterizer0.018s
                      🟢newBMFontRasterizer0.018s
                      🟢newGlyphData0.018s
                      🟢newImageRasterizer0.018s
                      🟢newRasterizer0.017s
                      🟢newTrueTypeRasterizer0.019s

                      🟢 love.graphics

                      • 🟢 93 Tests
                      • 🔴 0 Failures
                      • 🟡 14 Skipped
                      • 2.106s


                        • MethodTimeDetails
                          🟡Canvas0.017stest class needs writing
                          🟡Font0.018stest class needs writing
                          🟡Image0.017stest class needs writing
                          🟡Mesh0.017stest class needs writing
                          🟡ParticleSystem0.017stest class needs writing
                          🟡Quad0.017stest class needs writing
                          🟡Shader0.018stest class needs writing
                          🟡SpriteBatch0.018stest class needs writing
                          🟡Text0.018stest class needs writing
                          🟡Texture0.018stest class needs writing
                          🟡Video0.007stest class needs writing
                          🟢applyTransform0.019s

                          Expected

                          Actual

                          🟢arc0.024s

                          Expected

                          Actual

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢captureScreenshot0.184s
                          🟢circle0.021s

                          Expected

                          Actual

                          🟢clear0.018s

                          Expected

                          Actual

                          🟡discard0.016scant test this worked
                          🟢draw0.018s

                          Expected

                          Actual

                          🟡drawInstanced0.018stest class needs writing
                          🟢drawLayer0.020s

                          Expected

                          Actual

                          🟢ellipse0.018s

                          Expected

                          Actual

                          🟢flushBatch0.017s
                          🟢getBackgroundColor0.018s
                          🟢getBlendMode0.018s
                          🟢getCanvas0.019s
                          🟢getColor0.017s
                          🟢getColorMask0.018s
                          🟢getDPIScale0.017s
                          🟢getDefaultFilter0.018s
                          🟢getDepthMode0.017s
                          🟢getDimensions0.018s
                          🟢getFont0.019s
                          🟢getFrontFaceWinding0.017s
                          🟢getHeight0.017s
                          🟢getLineJoin0.017s
                          🟢getLineStyle0.020s
                          🟢getLineWidth0.016s
                          🟢getMeshCullMode0.016s
                          🟢getPixelDimensions0.018s
                          🟢getPixelHeight0.018s
                          🟢getPixelWidth0.018s
                          🟢getPointSize0.016s
                          🟢getRendererInfo0.019s
                          🟢getScissor0.017s
                          🟢getShader0.019s
                          🟢getStackDepth0.018s
                          🟢getStats0.018s
                          🟢getStencilMode0.017s
                          🟢getSupported0.018s
                          🟢getSystemLimits0.018s
                          🟢getTextureFormats0.019s
                          🟢getTextureTypes0.018s
                          🟢getWidth0.017s
                          🟢intersectScissor0.019s

                          Expected

                          Actual

                          🟢inverseTransformPoint0.017s
                          🟢isActive0.017s
                          🟢isGammaCorrect0.018s
                          🟢isWireframe0.018s
                          🟢line0.019s

                          Expected

                          Actual

                          🟢newArrayImage0.019s
                          🟢newCanvas0.015s
                          🟢newCubeImage0.020s
                          🟢newFont0.018s
                          🟢newImage0.017s
                          🟢newImageFont0.019s
                          🟢newMesh0.018s
                          🟢newParticleSystem0.018s
                          🟢newQuad0.017s
                          🟢newShader0.022s
                          🟢newSpriteBatch0.019s
                          🟢newTextBatch0.016s
                          🟢newVideo0.021s
                          🟢newVolumeImage0.019s
                          🟢origin0.018s

                          Expected

                          Actual

                          🟢points0.019s

                          Expected

                          Actual

                          🟢polygon0.016s

                          Expected

                          Actual

                          🟢pop0.019s

                          Expected

                          Actual

                          🟡present0.018stest class needs writing
                          🟢print0.019s

                          Expected

                          Actual

                          🟢printf0.019s

                          Expected

                          Actual

                          🟢push0.021s

                          Expected

                          Actual

                          🟢rectangle0.018s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢replaceTransform0.017s

                          Expected

                          Actual

                          🟢reset0.017s
                          🟢rotate0.020s

                          Expected

                          Actual

                          🟢scale0.020s
                          🟢setBackgroundColor0.017s
                          🟢setBlendMode0.020s

                          Expected

                          Actual

                          🟢setCanvas0.019s

                          Expected

                          Actual

                          🟢setColor0.018s

                          Expected

                          Actual

                          🟢setColorMask0.019s

                          Expected

                          Actual

                          🟢setDefaultFilter0.018s
                          🟢setDepthMode0.018s
                          🟢setFont0.018s

                          Expected

                          Actual

                          🟢setFrontFaceWinding0.018s
                          🟢setLineJoin0.020s

                          Expected

                          Actual

                          🟢setLineStyle0.017s

                          Expected

                          Actual

                          🟢setLineWidth0.018s

                          Expected

                          Actual

                          🟢setMeshCullMode0.018s
                          🟢setScissor0.018s

                          Expected

                          Actual

                          🟢setShader0.024s

                          Expected

                          Actual

                          🟢setStencilTest0.018s

                          Expected

                          Actual

                          🟢setWireframe0.019s

                          Expected

                          Actual

                          🟢shear0.021s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢transformPoint0.016s
                          🟢translate0.020s

                          Expected

                          Actual

                          🟢validateShader0.021s

                          🟢 love.image

                          • 🟢 5 Tests
                          • 🔴 0 Failures
                          • 🟡 0 Skipped
                          • 0.088s


                            • MethodTimeDetails
                              🟢CompressedImageData0.018s
                              🟢ImageData0.018s
                              🟢isCompressed0.017s
                              🟢newCompressedData0.018s
                              🟢newImageData0.018s

                              🟢 love.math

                              • 🟢 20 Tests
                              • 🔴 0 Failures
                              • 🟡 0 Skipped
                              • 0.284s


                                • MethodTimeDetails
                                  🟢BezierCurve0.016s
                                  🟢RandomGenerator0.017s
                                  🟢Transform0.017s
                                  🟢colorFromBytes0.018s
                                  🟢colorToBytes0.018s
                                  🟢gammaToLinear0.017s
                                  🟢getRandomSeed0.017s
                                  🟢getRandomState0.018s
                                  🟢isConvex0.018s
                                  🟢linearToGamma0.018s
                                  🟢newBezierCurve0.018s
                                  🟢newRandomGenerator0.018s
                                  🟢newTransform0.017s
                                  🟢perlinNoise0.019s
                                  🟢random0.012s
                                  🟢randomNormal0.017s
                                  🟢setRandomSeed0.002s
                                  🟢setRandomState0.002s
                                  🟢simplexNoise0.002s
                                  🟢triangulate0.003s

                                  🟢 love.physics

                                  • 🟢 22 Tests
                                  • 🔴 0 Failures
                                  • 🟡 6 Skipped
                                  • 0.059s


                                    • MethodTimeDetails
                                      🟡Body0.002stest class needs writing
                                      🟡Contact0.002stest class needs writing
                                      🟡Fixture0.002stest class needs writing
                                      🟡Joint0.002stest class needs writing
                                      🟡Shape0.002stest class needs writing
                                      🟡World0.002stest class needs writing
                                      🟢getDistance0.002s
                                      🟢getMeter0.002s
                                      🟢newBody0.002s
                                      🟢newChainShape0.002s
                                      🟢newCircleShape0.005s
                                      🟢newDistanceJoint0.002s
                                      🟢newEdgeShape0.002s
                                      🟢newFixture0.002s
                                      🟢newFrictionJoint0.002s
                                      🟢newGearJoint0.002s
                                      🟢newMotorJoint0.002s
                                      🟢newMouseJoint0.002s
                                      🟢newPolygonShape0.002s
                                      🟢newPrismaticJoint0.002s
                                      🟢newPulleyJoint0.002s
                                      🟢newRectangleShape0.002s
                                      🟢newRevoluteJoint0.002s
                                      🟢newRopeJoint0.002s
                                      🟢newWeldJoint0.002s
                                      🟢newWheelJoint0.002s
                                      🟢newWorld0.002s
                                      🟢setMeter0.002s

                                      🟢 love.sound

                                      • 🟢 4 Tests
                                      • 🔴 0 Failures
                                      • 🟡 0 Skipped
                                      • 0.015s


                                        • MethodTimeDetails
                                          🟢Decoder0.007s
                                          🟢SoundData0.003s
                                          🟢newDecoder0.002s
                                          🟢newSoundData0.003s

                                          🟢 love.system

                                          • 🟢 6 Tests
                                          • 🔴 0 Failures
                                          • 🟡 2 Skipped
                                          • 0.023s


                                            • MethodTimeDetails
                                              🟢getClipboardText0.004s
                                              🟢getOS0.007s
                                              🟢getPowerInfo0.002s
                                              🟢getProcessorCount0.002s
                                              🟢hasBackgroundMusic0.002s
                                              🟡openURL0.002scant test this worked
                                              🟢setClipboardText0.003s
                                              🟡vibrate0.002scant test this worked

                                              🟢 love.thread

                                              • 🟢 5 Tests
                                              • 🔴 0 Failures
                                              • 🟡 0 Skipped
                                              • 0.318s


                                                • MethodTimeDetails
                                                  🟢Channel0.220s
                                                  🟢Thread0.092s
                                                  🟢getChannel0.002s
                                                  🟢newChannel0.002s
                                                  🟢newThread0.002s

                                                  🟢 love.timer

                                                  • 🟢 6 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 0 Skipped
                                                  • 2.020s


                                                    • MethodTimeDetails
                                                      🟢getAverageDelta0.002s
                                                      🟢getDelta0.002s
                                                      🟢getFPS0.002s
                                                      🟢getTime1.003s
                                                      🟢sleep1.006s
                                                      🟢step0.004s

                                                      🟢 love.video

                                                      • 🟢 2 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 0 Skipped
                                                      • 0.016s


                                                        • MethodTimeDetails
                                                          🟢VideoStream0.009s
                                                          🟢newVideoStream0.007s

                                                          🟢 love.window

                                                          • 🟢 34 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 2 Skipped
                                                          • 5.954s


                                                            • MethodTimeDetails
                                                              🟢close0.054s
                                                              🟢fromPixels0.002s
                                                              🟢getDPIScale0.002s
                                                              🟢getDesktopDimensions0.002s
                                                              🟢getDisplayCount0.002s
                                                              🟢getDisplayName0.015s
                                                              🟢getDisplayOrientation0.017s
                                                              🟢getFullscreen1.340s
                                                              🟢getFullscreenModes0.009s
                                                              🟢getIcon0.019s
                                                              🟢getMode0.014s
                                                              🟢getPosition0.017s
                                                              🟢getSafeArea0.017s
                                                              🟢getTitle0.018s
                                                              🟢getVSync0.017s
                                                              🟢hasFocus0.018s
                                                              🟢hasMouseFocus0.018s
                                                              🟢isDisplaySleepEnabled0.017s
                                                              🟢isMaximized0.186s
                                                              🟢isMinimized0.744s
                                                              🟢isOpen0.054s
                                                              🟢isVisible0.031s
                                                              🟢maximize0.173s
                                                              🟢minimize0.740s
                                                              🟡requestAttention0.003scant test this worked
                                                              🟢restore0.840s
                                                              🟢setDisplaySleepEnabled0.016s
                                                              🟢setFullscreen1.335s
                                                              🟢setIcon0.013s
                                                              🟢setMode0.021s
                                                              🟢setPosition0.178s
                                                              🟢setTitle0.003s
                                                              🟢setVSync0.002s
                                                              🟡showMessageBox0.002scant test this worked
                                                              🟢toPixels0.002s
                                                              🟢updateMode0.014s
\ No newline at end of file +

🔴 love.test

  • 🟢 281 Tests
  • 🔴 2 Failures
  • 🟡 20 Skipped
  • 13.278s


🟢 love.audio

  • 🟢 28 Tests
  • 🔴 0 Failures
  • 🟡 0 Skipped
  • 0.851s


    • MethodTimeDetails
      🟢RecordingDevice0.397s
      🟢Source0.021s
      🟢getActiveEffects0.017s
      🟢getActiveSourceCount0.018s
      🟢getDistanceModel0.017s
      🟢getDopplerScale0.017s
      🟢getEffect0.017s
      🟢getMaxSceneEffects0.017s
      🟢getMaxSourceEffects0.017s
      🟢getOrientation0.017s
      🟢getPosition0.016s
      🟢getRecordingDevices0.017s
      🟢getVelocity0.014s
      🟢getVolume0.017s
      🟢isEffectsSupported0.017s
      🟢newQueueableSource0.017s
      🟢newSource0.017s
      🟢pause0.017s
      🟢play0.017s
      🟢setDistanceModel0.018s
      🟢setDopplerScale0.016s
      🟢setEffect0.017s
      🟢setMixWithSystem0.017s
      🟢setOrientation0.016s
      🟢setPosition0.016s
      🟢setVelocity0.016s
      🟢setVolume0.016s
      🟢stop0.017s

      🟢 love.data

      • 🟢 12 Tests
      • 🔴 0 Failures
      • 🟡 0 Skipped
      • 0.197s


        • MethodTimeDetails
          🟢ByteData0.016s
          🟢CompressedData0.016s
          🟢compress0.016s
          🟢decode0.018s
          🟢decompress0.017s
          🟢encode0.017s
          🟢getPackedSize0.016s
          🟢hash0.015s
          🟢newByteData0.016s
          🟢newDataView0.015s
          🟢pack0.018s
          🟢unpack0.016s

          🟢 love.event

          • 🟢 4 Tests
          • 🔴 0 Failures
          • 🟡 2 Skipped
          • 0.096s


            • MethodTimeDetails
              🟢clear0.016s
              🟢poll0.016s
              🟡pump0.016sused internally
              🟢push0.016s
              🟢quit0.016s
              🟡wait0.016sused internally

              🟢 love.filesystem

              • 🟢 29 Tests
              • 🔴 0 Failures
              • 🟡 2 Skipped
              • 0.539s


                • MethodTimeDetails
                  🟢File0.020s
                  🟢FileData0.016s
                  🟢append0.022s
                  🟢areSymlinksEnabled0.017s
                  🟢createDirectory0.017s
                  🟢getAppdataDirectory0.016s
                  🟢getCRequirePath0.017s
                  🟢getDirectoryItems0.019s
                  🟢getIdentity0.017s
                  🟢getInfo0.018s
                  🟢getRealDirectory0.017s
                  🟢getRequirePath0.017s
                  🟢getSaveDirectory0.017s
                  🟡getSource0.017sused internally
                  🟢getSourceBaseDirectory0.017s
                  🟢getUserDirectory0.018s
                  🟢getWorkingDirectory0.021s
                  🟢isFused0.014s
                  🟢lines0.017s
                  🟢load0.018s
                  🟢mount0.018s
                  🟢newFileData0.018s
                  🟢openFile0.016s
                  🟢read0.016s
                  🟢remove0.017s
                  🟢setCRequirePath0.016s
                  🟢setIdentity0.016s
                  🟢setRequirePath0.015s
                  🟡setSource0.017sused internally
                  🟢unmount0.018s
                  🟢write0.019s

                  🔴 love.font

                  • 🟢 6 Tests
                  • 🔴 1 Failures
                  • 🟡 0 Skipped
                  • 0.121s


                    • MethodTimeDetails
                      🔴GlyphData0.016sassert 8 [check glyph number] expected '97' got '0'
                      🟢Rasterizer0.016s
                      🟢newBMFontRasterizer0.017s
                      🟢newGlyphData0.018s
                      🟢newImageRasterizer0.018s
                      🟢newRasterizer0.018s
                      🟢newTrueTypeRasterizer0.018s

                      🔴 love.graphics

                      • 🟢 98 Tests
                      • 🔴 1 Failures
                      • 🟡 6 Skipped
                      • 2.029s


                        • MethodTimeDetails
                          🔴Canvas0.018sassert 44 [check depth sample mode set] expected 'equal' got 'nil'
                          🟢Font0.023s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢Image0.020s

                          Expected

                          Actual

                          🟡Mesh0.018stest class needs writing
                          🟡ParticleSystem0.017stest class needs writing
                          🟢Quad0.020s

                          Expected

                          Actual

                          🟢Shader0.029s

                          Expected

                          Actual

                          🟡SpriteBatch0.016stest class needs writing
                          🟢Text0.014s

                          Expected

                          Actual

                          🟡Video0.015stest class needs writing
                          🟢applyTransform0.018s

                          Expected

                          Actual

                          🟢arc0.026s

                          Expected

                          Actual

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢captureScreenshot0.183s
                          🟢circle0.023s

                          Expected

                          Actual

                          🟢clear0.018s

                          Expected

                          Actual

                          🟡discard0.017scant test this worked
                          🟢draw0.034s

                          Expected

                          Actual

                          🟡drawInstanced0.014stest class needs writing
                          🟢drawLayer0.017s

                          Expected

                          Actual

                          🟢ellipse0.018s

                          Expected

                          Actual

                          🟢flushBatch0.016s
                          🟢getBackgroundColor0.016s
                          🟢getBlendMode0.016s
                          🟢getCanvas0.016s
                          🟢getColor0.016s
                          🟢getColorMask0.015s
                          🟢getDPIScale0.016s
                          🟢getDefaultFilter0.016s
                          🟢getDepthMode0.016s
                          🟢getDimensions0.016s
                          🟢getFont0.016s
                          🟢getFrontFaceWinding0.016s
                          🟢getHeight0.015s
                          🟢getLineJoin0.016s
                          🟢getLineStyle0.025s
                          🟢getLineWidth0.018s
                          🟢getMeshCullMode0.016s
                          🟢getPixelDimensions0.016s
                          🟢getPixelHeight0.024s
                          🟢getPixelWidth0.013s
                          🟢getPointSize0.016s
                          🟢getRendererInfo0.016s
                          🟢getScissor0.016s
                          🟢getShader0.017s
                          🟢getStackDepth0.016s
                          🟢getStats0.015s
                          🟢getStencilMode0.016s
                          🟢getSupported0.015s
                          🟢getSystemLimits0.015s
                          🟢getTextureFormats0.017s
                          🟢getTextureTypes0.016s
                          🟢getWidth0.015s
                          🟢intersectScissor0.017s

                          Expected

                          Actual

                          🟢inverseTransformPoint0.016s
                          🟢isActive0.016s
                          🟢isGammaCorrect0.015s
                          🟢isWireframe0.015s
                          🟢line0.017s

                          Expected

                          Actual

                          🟢newArrayImage0.016s
                          🟢newCanvas0.015s
                          🟢newCubeImage0.017s
                          🟢newFont0.017s
                          🟢newImage0.017s
                          🟢newImageFont0.016s
                          🟢newMesh0.016s
                          🟢newParticleSystem0.017s
                          🟢newQuad0.016s
                          🟢newShader0.022s
                          🟢newSpriteBatch0.017s
                          🟢newTextBatch0.011s
                          🟢newVideo0.019s
                          🟢newVolumeImage0.018s
                          🟢origin0.018s

                          Expected

                          Actual

                          🟢points0.020s

                          Expected

                          Actual

                          🟢polygon0.021s

                          Expected

                          Actual

                          🟢pop0.018s

                          Expected

                          Actual

                          🟢print0.020s

                          Expected

                          Actual

                          🟢printf0.020s

                          Expected

                          Actual

                          🟢push0.018s

                          Expected

                          Actual

                          🟢rectangle0.020s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢replaceTransform0.018s

                          Expected

                          Actual

                          🟢reset0.018s
                          🟢rotate0.018s

                          Expected

                          Actual

                          🟢scale0.017s
                          🟢setBackgroundColor0.017s
                          🟢setBlendMode0.019s

                          Expected

                          Actual

                          🟢setCanvas0.018s

                          Expected

                          Actual

                          🟢setColor0.018s

                          Expected

                          Actual

                          🟢setColorMask0.019s

                          Expected

                          Actual

                          🟢setDefaultFilter0.017s
                          🟢setDepthMode0.017s
                          🟢setFont0.019s

                          Expected

                          Actual

                          🟢setFrontFaceWinding0.017s
                          🟢setLineJoin0.018s

                          Expected

                          Actual

                          🟢setLineStyle0.018s

                          Expected

                          Actual

                          🟢setLineWidth0.019s

                          Expected

                          Actual

                          🟢setMeshCullMode0.018s
                          🟢setScissor0.020s

                          Expected

                          Actual

                          🟢setShader0.023s

                          Expected

                          Actual

                          🟢setStencilTest0.019s

                          Expected

                          Actual

                          🟢setWireframe0.018s

                          Expected

                          Actual

                          🟢shear0.019s

                          Expected

                          Actual

                          Expected

                          Actual

                          🟢transformPoint0.018s
                          🟢translate0.025s

                          Expected

                          Actual

                          🟢validateShader0.016s

                          🟢 love.image

                          • 🟢 5 Tests
                          • 🔴 0 Failures
                          • 🟡 0 Skipped
                          • 0.087s


                            • MethodTimeDetails
                              🟢CompressedImageData0.018s
                              🟢ImageData0.017s
                              🟢isCompressed0.017s
                              🟢newCompressedData0.019s
                              🟢newImageData0.017s

                              🟢 love.math

                              • 🟢 20 Tests
                              • 🔴 0 Failures
                              • 🟡 0 Skipped
                              • 0.321s


                                • MethodTimeDetails
                                  🟢BezierCurve0.018s
                                  🟢RandomGenerator0.017s
                                  🟢Transform0.017s
                                  🟢colorFromBytes0.017s
                                  🟢colorToBytes0.016s
                                  🟢gammaToLinear0.016s
                                  🟢getRandomSeed0.016s
                                  🟢getRandomState0.016s
                                  🟢isConvex0.016s
                                  🟢linearToGamma0.017s
                                  🟢newBezierCurve0.016s
                                  🟢newRandomGenerator0.016s
                                  🟢newTransform0.016s
                                  🟢perlinNoise0.015s
                                  🟢random0.016s
                                  🟢randomNormal0.014s
                                  🟢setRandomSeed0.015s
                                  🟢setRandomState0.015s
                                  🟢simplexNoise0.016s
                                  🟢triangulate0.016s

                                  🟢 love.physics

                                  • 🟢 22 Tests
                                  • 🔴 0 Failures
                                  • 🟡 6 Skipped
                                  • 0.468s


                                    • MethodTimeDetails
                                      🟡Body0.018stest class needs writing
                                      🟡Contact0.017stest class needs writing
                                      🟡Fixture0.026stest class needs writing
                                      🟡Joint0.017stest class needs writing
                                      🟡Shape0.017stest class needs writing
                                      🟡World0.017stest class needs writing
                                      🟢getDistance0.017s
                                      🟢getMeter0.015s
                                      🟢newBody0.016s
                                      🟢newChainShape0.016s
                                      🟢newCircleShape0.017s
                                      🟢newDistanceJoint0.016s
                                      🟢newEdgeShape0.017s
                                      🟢newFixture0.016s
                                      🟢newFrictionJoint0.016s
                                      🟢newGearJoint0.016s
                                      🟢newMotorJoint0.016s
                                      🟢newMouseJoint0.018s
                                      🟢newPolygonShape0.016s
                                      🟢newPrismaticJoint0.017s
                                      🟢newPulleyJoint0.016s
                                      🟢newRectangleShape0.017s
                                      🟢newRevoluteJoint0.015s
                                      🟢newRopeJoint0.016s
                                      🟢newWeldJoint0.015s
                                      🟢newWheelJoint0.016s
                                      🟢newWorld0.014s
                                      🟢setMeter0.015s

                                      🟢 love.sound

                                      • 🟢 4 Tests
                                      • 🔴 0 Failures
                                      • 🟡 0 Skipped
                                      • 0.068s


                                        • MethodTimeDetails
                                          🟢Decoder0.018s
                                          🟢SoundData0.017s
                                          🟢newDecoder0.016s
                                          🟢newSoundData0.017s

                                          🟢 love.system

                                          • 🟢 6 Tests
                                          • 🔴 0 Failures
                                          • 🟡 2 Skipped
                                          • 0.148s


                                            • MethodTimeDetails
                                              🟢getClipboardText0.019s
                                              🟢getOS0.017s
                                              🟢getPowerInfo0.017s
                                              🟢getProcessorCount0.016s
                                              🟢hasBackgroundMusic0.029s
                                              🟡openURL0.016scant test this worked
                                              🟢setClipboardText0.017s
                                              🟡vibrate0.016scant test this worked

                                              🟢 love.thread

                                              • 🟢 5 Tests
                                              • 🔴 0 Failures
                                              • 🟡 0 Skipped
                                              • 0.376s


                                                • MethodTimeDetails
                                                  🟢Channel0.230s
                                                  🟢Thread0.093s
                                                  🟢getChannel0.018s
                                                  🟢newChannel0.017s
                                                  🟢newThread0.018s

                                                  🟢 love.timer

                                                  • 🟢 6 Tests
                                                  • 🔴 0 Failures
                                                  • 🟡 0 Skipped
                                                  • 2.082s


                                                    • MethodTimeDetails
                                                      🟢getAverageDelta0.017s
                                                      🟢getDelta0.016s
                                                      🟢getFPS0.016s
                                                      🟢getTime1.017s
                                                      🟢sleep1.009s
                                                      🟢step0.005s

                                                      🟢 love.video

                                                      • 🟢 2 Tests
                                                      • 🔴 0 Failures
                                                      • 🟡 0 Skipped
                                                      • 0.039s


                                                        • MethodTimeDetails
                                                          🟢VideoStream0.020s
                                                          🟢newVideoStream0.020s

                                                          🟢 love.window

                                                          • 🟢 34 Tests
                                                          • 🔴 0 Failures
                                                          • 🟡 2 Skipped
                                                          • 5.855s


                                                            • MethodTimeDetails
                                                              🟢close0.052s
                                                              🟢fromPixels0.002s
                                                              🟢getDPIScale0.017s
                                                              🟢getDesktopDimensions0.018s
                                                              🟢getDisplayCount0.017s
                                                              🟢getDisplayName0.018s
                                                              🟢getDisplayOrientation0.018s
                                                              🟢getFullscreen1.357s
                                                              🟢getFullscreenModes0.010s
                                                              🟢getIcon0.019s
                                                              🟢getMode0.015s
                                                              🟢getPosition0.017s
                                                              🟢getSafeArea0.016s
                                                              🟢getTitle0.017s
                                                              🟢getVSync0.016s
                                                              🟢hasFocus0.016s
                                                              🟢hasMouseFocus0.015s
                                                              🟢isDisplaySleepEnabled0.017s
                                                              🟢isMaximized0.185s
                                                              🟢isMinimized0.749s
                                                              🟢isOpen0.037s
                                                              🟢isVisible0.024s
                                                              🟢maximize0.156s
                                                              🟢minimize0.733s
                                                              🟡requestAttention0.003scant test this worked
                                                              🟢restore0.880s
                                                              🟢setDisplaySleepEnabled0.020s
                                                              🟢setFullscreen1.151s
                                                              🟢setIcon0.007s
                                                              🟢setMode0.023s
                                                              🟢setPosition0.181s
                                                              🟢setTitle0.018s
                                                              🟢setVSync0.015s
                                                              🟡showMessageBox0.003scant test this worked
                                                              🟢toPixels0.002s
                                                              🟢updateMode0.011s
\ No newline at end of file diff --git a/testing/examples/lovetest_runAllTests.md b/testing/examples/lovetest_runAllTests.md index c69865ba7..d309282ee 100644 --- a/testing/examples/lovetest_runAllTests.md +++ b/testing/examples/lovetest_runAllTests.md @@ -1,31 +1,31 @@ - + -**305** tests were completed in **16.781s** with **275** passed, **2** failed, and **28** skipped +**303** tests were completed in **13.278s** with **281** passed, **2** failed, and **20** skipped ### Report | Module | Pass | Fail | Skip | Time | | --------------------- | ------ | ------ | ------- | ------ | -| 🔴 audio | 27 | 1 | 0 | 4.898s | -| 🟢 data | 12 | 0 | 0 | 0.213s | -| 🟢 event | 4 | 0 | 2 | 0.103s | -| 🟢 filesystem | 29 | 0 | 2 | 0.561s | -| 🔴 font | 6 | 1 | 0 | 0.123s | -| 🟢 graphics | 93 | 0 | 14 | 2.106s | -| 🟢 image | 5 | 0 | 0 | 0.088s | -| 🟢 math | 20 | 0 | 0 | 0.284s | -| 🟢 physics | 22 | 0 | 6 | 0.059s | -| 🟢 sound | 4 | 0 | 0 | 0.015s | -| 🟢 system | 6 | 0 | 2 | 0.023s | -| 🟢 thread | 5 | 0 | 0 | 0.318s | -| 🟢 timer | 6 | 0 | 0 | 2.020s | -| 🟢 video | 2 | 0 | 0 | 0.016s | -| 🟢 window | 34 | 0 | 2 | 5.954s | +| 🟢 audio | 28 | 0 | 0 | 0.851s | +| 🟢 data | 12 | 0 | 0 | 0.197s | +| 🟢 event | 4 | 0 | 2 | 0.096s | +| 🟢 filesystem | 29 | 0 | 2 | 0.539s | +| 🔴 font | 6 | 1 | 0 | 0.121s | +| 🔴 graphics | 98 | 1 | 6 | 2.029s | +| 🟢 image | 5 | 0 | 0 | 0.087s | +| 🟢 math | 20 | 0 | 0 | 0.321s | +| 🟢 physics | 22 | 0 | 6 | 0.468s | +| 🟢 sound | 4 | 0 | 0 | 0.068s | +| 🟢 system | 6 | 0 | 2 | 0.148s | +| 🟢 thread | 5 | 0 | 0 | 0.376s | +| 🟢 timer | 6 | 0 | 0 | 2.082s | +| 🟢 video | 2 | 0 | 0 | 0.039s | +| 🟢 window | 34 | 0 | 2 | 5.855s | ### Failures -> 🔴 Source -> assert 53 [check effect was applied] expected 'true' got 'false' - > 🔴 GlyphData > assert 8 [check glyph number] expected '97' got '0' +> 🔴 Canvas +> assert 44 [check depth sample mode set] expected 'equal' got 'nil' + diff --git a/testing/examples/lovetest_runAllTests.xml b/testing/examples/lovetest_runAllTests.xml index deb2d4201..dc3bb5e04 100644 --- a/testing/examples/lovetest_runAllTests.xml +++ b/testing/examples/lovetest_runAllTests.xml @@ -1,162 +1,161 @@ - - - + + + - - assert 53 [check effect was applied] expected 'true' got 'false' + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -166,507 +165,496 @@ - - + + assert 8 [check glyph number] expected '97' got '0' - + - + - + - + - - - + + + assert 44 [check depth sample mode set] expected 'equal' got 'nil' - - + - - + - + - + + + + + - + + + - - + - - + - - + - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + \ No newline at end of file diff --git a/testing/output/expected/love.test.graphics.Font-1.png b/testing/output/expected/love.test.graphics.Font-1.png new file mode 100644 index 0000000000000000000000000000000000000000..cb2f21a1ed0ead98be5e0e43126476ea1846c3b6 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^0wBx?BpA#)4xIr~OeH~n!3+##lh0ZJdGekvjv*Cu xk`ox3nb_L+*xJr9^Vo|>SjiidGlFz xshE?TkdUxpWnw`Q(?Tl==9Vmp2SI!sEDT3ZaCjzihCK&q@pScbS?83{1OW6x7uf&+ literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.Image-1.png b/testing/output/expected/love.test.graphics.Image-1.png new file mode 100644 index 0000000000000000000000000000000000000000..5f45cf9e74d822c536be3082099ce09133192c72 GIT binary patch literal 375 zcmV--0f_#IP)RqEy~ItC z5mFp&z>Rw^VUMCxV1~#Pw?z6h2RKS3iW2EG!Kvd%{6aY~=F{WOhX9~w3vkj;0O)6W zfS&`Q5u1WUTnZBDQ;-ONMl6MfI0|P?NCZG5mcynA0Ivxc!hsmD5j(&N6K+h*@pp{( z2|W{Qyw7o8FfbA0zQ%}%g&1Q#H_S*T^7+Gz^fCk@Rtk@dSRJt)HFOkw4POU>kv0<&MCde85J3Ad;$JONIJ VNX|>^XKVlf002ovPDHLkV1i~FlZyZV literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.Quad-1.png b/testing/output/expected/love.test.graphics.Quad-1.png new file mode 100644 index 0000000000000000000000000000000000000000..22ab17e3e15b1eaeb545971e015ac2e9d0edadc9 GIT binary patch literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-u0Z-)*!2JZ{|B$QGso=x z1R$TWB*-tA!Qt7BG$3cSr;B4q#hl)A2YHzk1>7FaKRm@Dvtk3w?~N?{)^gigma1?m zIEE!N=@(w#c~-na;jguu#|`F#91|xnG$yoocr-W|IH{;OC`c#@2_^XJD1SL}^?mW9 zXZ@BB_xW^o?^ZT+QdzRs(!qk&y7hfY^|ouL6xYapQp}NMSt0D>TPt@`c}=jBPY0)= z;vc75{5_nx9xD_-vN38c6fkmZ@X~1U5m+F^r6|0i+q~{PxAOiC+!_*D&Om1~c)I$z JtaD0e0su2hE&W+PDtS3O;u>(;Emnd#lgf->?i8DIiOG!q}9{a&t;uc GLK6UQNgGoD literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.Text-1.png b/testing/output/expected/love.test.graphics.Text-1.png new file mode 100644 index 0000000000000000000000000000000000000000..4f15348cdffb4bef7adb7f461cb7aa263898fb36 GIT binary patch literal 449 zcmV;y0Y3hTP)g0{U)fQ71UQFBI6Q;wZG z0*wS!;pL=IpSs;{IOUo^RDpGDJ>WW&G!tEuuW*)dYu8e#o>y4220Gs@6BTxa2;CWE zsj0ddWU@b_5YP-d&zwbjj6?ltXt+sh2AYAINT_*OG%8gGIxl3sBz?BPqzsZEqbcMN rM=@@|tfwsc>4+=zl2Go(@jvSeY+*#a?9lLD00000NkvXXu0mjf!hyg) literal 0 HcmV?d00001 diff --git a/testing/output/expected/love.test.graphics.setColorMask-1.png b/testing/output/expected/love.test.graphics.setColorMask-1.png index 254f834f807f381374e51f249e36e74ffcdd595f..315c7a936f3dc201ea118e957e50a50e5f26b1f7 100644 GIT binary patch delta 65 zcmYcenIK`q$jrdNplX||1f-Y)d_r9R|7Ykr_Qe&*Eak-(VP6||NMvc%&ZNaLT4AV h^+*|H9Y`=@U`U$HEPMFm^IbrN44$rjF6*2UngH~68iN1; diff --git a/testing/readme.md b/testing/readme.md index 2f6f8bb42..9a56fe471 100644 --- a/testing/readme.md +++ b/testing/readme.md @@ -23,10 +23,10 @@ This is the status of all module tests currently. | ----------------- | ---- | ---- | ---- | | 🟢 audio | 28 | 0 | 0 | | 🟢 data | 12 | 0 | 0 | -| 🟡 event | 4 | 1 | 1 | -| 🟢 filesystem | 28 | 0 | 2 | +| 🟢 event | 4 | 0 | 2 | +| 🟢 filesystem | 29 | 0 | 2 | | 🟢 font | 7 | 0 | 0 | -| 🟡 graphics | 93 | 14 | 1 | +| 🟡 graphics | 99 | 5 | 1 | | 🟢 image | 5 | 0 | 0 | | 🟢 math | 20 | 0 | 0 | | 🟡 physics | 22 | 6 | 0 | @@ -113,24 +113,20 @@ For sanity-checking, if it's currently not covered or it's not possible to test Things still left to do: - [ ] physics.Body, physics.Contact, physics.Fixture, physics.Joint, physics.Shape, physics.World -- [ ] graphics.Canvas, graphics.Font, graphics.Image, graphics.Mesh, - graphics.ParticleSystem, graphics.Quad, graphics.Shader, - graphics.SpriteBatch, graphics.Text, graphics.Texture, graphics.Video -- [ ] event.wait -- [ ] graphics.present -- [ ] graphics.drawInstanced -- [ ] graphics.setDepthMode (needs actual graphical comparison if possible) -- [ ] graphics.setFrontFaceWinding (needs actual graphical comparison if possible) -- [ ] graphics.setMeshCullMode (needs actual graphical comparison if possible) -- [ ] @deprecated setStencilTest (use setStencilMode) - [ ] @deprecated physics methods (sasha changes) -- [ ] check 12.0 wiki page for new methods -- [ ] need a platform: format table somewhere for compressed formats (i.e. DXT not supported) -- [ ] ideally graphics.isCompressed should have an example of all compressed files love can take +- [ ] graphics.Mesh, graphics.ParticleSystem + graphics.SpriteBatch, graphics.Video +- [ ] graphics.drawInstanced +- [ ] @deprecated love.graphics.stencil (replaced by love.graphics.setStencilMode) +- [ ] @deprecated love.graphics.setStencilTest (replaced by love.graphics.setStencilMode) --- ## Future Goals -- [ ] Tests can compare visual results to a reference image (partially done) +- [ ] graphics.isCompressed should have an example of all compressed files love can take +- [ ] Tests can compare visual results to a reference image + This is partially done as we already save actual images for graphics tests to + use in the report output comparisons, so we just need to add a helper method + to the test class to let you just do assertMatching on the imgdata - [ ] Ability to test loading different combinations of modules - [ ] Performance tests diff --git a/testing/resources/font-letters-ab.png b/testing/resources/font-letters-ab.png new file mode 100644 index 0000000000000000000000000000000000000000..3ec8aeca38f5f5a67f9a3091b7cb5ab4a4fa8837 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&L!3HFEdh;y=QjEnx?oJHr&dIz4a(p~p978lF zZk^;P#9+X}y!i3|_-m`PF37zJ6u#`hW8m1!_`;;h(&nP<{kd-Zg2u<97Db-)-@kIP u;iMm@x>6s%%y2fYS~yp5_l~@;eZ24cd6o0SkG%q#%i!ti=d#Wzp$P!pIx=Vg literal 0 HcmV?d00001 diff --git a/testing/resources/font-letters-cd.png b/testing/resources/font-letters-cd.png new file mode 100644 index 0000000000000000000000000000000000000000..51190f648e5fbb176adecc71974896b33a6ad867 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&L!3HFEdh;y=QjEnx?oJHr&dIz4a(p~p978lF zUY%&j$DqK$-2L!>{IS3zVvk?+UQlMyX)yT0(hz-&Upe^gEq}@TPCjc)CrTy->zRIO tmiv(_@Ox51?b(hKeY!^Hx+X2NXKa1VE&otua|zH~22WQ%mvv4FO#r>iFv|b{ literal 0 HcmV?d00001 diff --git a/testing/resources/love_test_graphics_rectangle_expected.png b/testing/resources/love_test_graphics_rectangle_expected.png deleted file mode 100644 index bbbaf6edc47eb7d5a8fac65aa2688aff11068153..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|96eneLo9ml zPCm%TpupiIfA;_X)Lq;6q^$K_?;|kd(2PSY4W-+34zF0@%-wW?LHFs5+Drd+_ncPv iT=Tbyjb+uo&n(sUoQk=jADn=OF?hQAxvX Date: Wed, 15 Nov 2023 19:52:17 +0000 Subject: [PATCH 089/409] add renderer to report md --- testing/classes/TestSuite.lua | 6 +++++- testing/readme.md | 4 ++-- testing/tests/graphics.lua | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/testing/classes/TestSuite.lua b/testing/classes/TestSuite.lua index 39c76b472..c2c8c5dd1 100644 --- a/testing/classes/TestSuite.lua +++ b/testing/classes/TestSuite.lua @@ -136,6 +136,8 @@ TestSuite = { -- @return {nil} printResult = function(self) local finaltime = UtilTimeFormat(self.time) + + local name, version, vendor, device = love.graphics.getRendererInfo() local md = '\n\n' .. + ' || TIME ' .. finaltime .. ' -->\n\n### Info\n' .. '**' .. tostring(self.totals[1] + self.totals[2] + self.totals[3]) .. '** tests were completed in **' .. finaltime .. 's** with **' .. tostring(self.totals[1]) .. '** passed, **' .. @@ -152,7 +152,7 @@ TestSuite = { '### Report\n' .. '| Module | Pass | Fail | Skip | Time |\n' .. '| --------------------- | ------ | ------ | ------- | ------ |\n' .. - self.mdrows .. '\n\n### Failures\n' .. self.mdfailures + self.mdrows .. '\n### Failures\n' .. self.mdfailures local xml = '

🔴 love.test

  • 🟢 281 Tests
  • 🔴 2 Failures
  • 🟡 20 Skipped
  • 13.278s


🟢 love.audio