diff --git a/CMakeLists.txt b/CMakeLists.txt index c539145d0..50816c7f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,22 +229,33 @@ add_library(lua53 ) target_link_libraries(lua53 PRIVATE PkgConfig::lua51) -add_library(luahttps - libraries/luahttps/common/Connection.h - libraries/luahttps/common/ConnectionClient.h - libraries/luahttps/common/HTTPRequest.cpp - libraries/luahttps/common/HTTPRequest.h - libraries/luahttps/common/HTTPSClient.cpp - libraries/luahttps/common/HTTPSClient.h - libraries/luahttps/common/HTTPSCommon.cpp - libraries/luahttps/common/HTTPSCommon.h - libraries/luahttps/common/PlaintextConnection.cpp - libraries/luahttps/common/PlaintextConnection.h - libraries/luahttps/generic/CurlClient.cpp - libraries/luahttps/generic/CurlClient.h - libraries/luahttps/https.cpp +FetchContent_Declare(lua-https + GIT_REPOSITORY https://github.com/lovebrew/lua-https + GIT_TAG TurtleP/certs ) -target_link_libraries(luahttps PRIVATE PkgConfig::lua51) + +FetchContent_MakeAvailable(lua-https) + +add_library(lua-https STATIC + ${lua-https_SOURCE_DIR}/src/common/config.h + ${lua-https_SOURCE_DIR}/src/common/Connection.h + ${lua-https_SOURCE_DIR}/src/common/ConnectionClient.h + ${lua-https_SOURCE_DIR}/src/common/HTTPRequest.cpp + ${lua-https_SOURCE_DIR}/src/common/HTTPRequest.h + ${lua-https_SOURCE_DIR}/src/common/HTTPS.cpp + ${lua-https_SOURCE_DIR}/src/common/HTTPS.h + ${lua-https_SOURCE_DIR}/src/common/HTTPSClient.cpp + ${lua-https_SOURCE_DIR}/src/common/HTTPSClient.h + ${lua-https_SOURCE_DIR}/src/common/PlaintextConnection.cpp + ${lua-https_SOURCE_DIR}/src/common/PlaintextConnection.h + ${lua-https_SOURCE_DIR}/src/generic/CurlClient.cpp + ${lua-https_SOURCE_DIR}/src/generic/CurlClient.h + ${lua-https_SOURCE_DIR}/src/generic/OpenSSLConnection.cpp + ${lua-https_SOURCE_DIR}/src/generic/OpenSSLConnection.h + ${lua-https_SOURCE_DIR}/src/lua/luahttps.cpp +) + +target_compile_definitions(lua-https PRIVATE HTTPS_BACKEND_CURL HTTPS_BACKEND_CURL_LINKED) # luasocket add_library(luasocket @@ -311,7 +322,6 @@ add_library(wuff libraries/wuff/wuff_memory.c ) - target_compile_definitions(${PROJECT_NAME} PRIVATE __APP_VERSION__=\"${VERSION}\" __LOVE_VERSION__=\"${LOVE_VERSION}\" __EMULATION__ @@ -326,12 +336,12 @@ target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::lua51) # link curl pkg_check_modules(libcurl REQUIRED IMPORTED_TARGET libcurl) -target_link_libraries(luahttps PRIVATE PkgConfig::libcurl) +target_link_libraries(lua-https PRIVATE PkgConfig::lua51 PkgConfig::libcurl) # link everything else target_link_libraries(${PROJECT_NAME} PRIVATE ${APP_LIBS} physfs box2d z turbojpeg png vorbisidec ogg - modplug luabit lua53 wuff ddsparse luahttps luasocket noise1234 + modplug luabit lua53 wuff ddsparse lua-https luasocket noise1234 ) # Include directories @@ -340,7 +350,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE libraries/ddsparse libraries/dr libraries/lua53 - libraries/luahttps libraries/luasocket libraries/noise1234 libraries/utf8 diff --git a/include/common/drawable.hpp b/include/common/drawable.hpp index 963217ec1..aa4828f03 100644 --- a/include/common/drawable.hpp +++ b/include/common/drawable.hpp @@ -17,6 +17,6 @@ namespace love {} virtual void Draw(Graphics& graphics, - const Matrix4& matrix) = 0; + const Matrix4& matrix) = 0; }; } // namespace love diff --git a/include/common/matrix.tcc b/include/common/matrix.tcc index c6d5ed717..8a9548c56 100644 --- a/include/common/matrix.tcc +++ b/include/common/matrix.tcc @@ -2,16 +2,516 @@ #include "console.hpp" #include "math.hpp" +#include "utilities/driver/renderer/vertex.hpp" +#include "vector.hpp" #include +#include +#include + +using Elements = float[0x10]; + +#if defined(__SWITCH__) + #include +#endif + +#include namespace love { - template + template + concept ValidTransformRange = + std::ranges::random_access_range && + (std::is_same_v>, + std::remove_cvref_t> || + (std::is_same_v, Vector3> && + std::is_same_v>, vertex::Vertex>)); + + template + concept Vector3TransformRange = ValidTransformRange; + template + concept Vector2TransformRange = ValidTransformRange; + template + concept VectorAtLeast2TransformRange = + ValidTransformRange || ValidTransformRange; + class Matrix4 { + protected: + template + static auto DeVertexize(R&& r) -> decltype(auto) + { + if constexpr (std::is_same_v>, + vertex::Vertex>) + { + return r | std::views::transform([](auto&& e) -> auto& { return e.position; }); + } + else + { + return std::forward(r); + } + } + static void Multiply(const Matrix4& a, const Matrix4& b, Elements t) + { +#if defined(__SWITCH__) + float32x4_t cola1 = vld1q_f32(&a.matrix[0]); + float32x4_t cola2 = vld1q_f32(&a.matrix[4]); + float32x4_t cola3 = vld1q_f32(&a.matrix[8]); + float32x4_t cola4 = vld1q_f32(&a.matrix[12]); + + float32x4_t col1 = vmulq_n_f32(cola1, b.matrix[0]); + col1 = vmlaq_n_f32(col1, cola2, b.matrix[1]); + col1 = vmlaq_n_f32(col1, cola3, b.matrix[2]); + col1 = vmlaq_n_f32(col1, cola4, b.matrix[3]); + + float32x4_t col2 = vmulq_n_f32(cola1, b.matrix[4]); + col2 = vmlaq_n_f32(col2, cola2, b.matrix[5]); + col2 = vmlaq_n_f32(col2, cola3, b.matrix[6]); + col2 = vmlaq_n_f32(col2, cola4, b.matrix[7]); + + float32x4_t col3 = vmulq_n_f32(cola1, b.matrix[8]); + col3 = vmlaq_n_f32(col3, cola2, b.matrix[9]); + col3 = vmlaq_n_f32(col3, cola3, b.matrix[10]); + col3 = vmlaq_n_f32(col3, cola4, b.matrix[11]); + + float32x4_t col4 = vmulq_n_f32(cola1, b.matrix[12]); + col4 = vmlaq_n_f32(col4, cola2, b.matrix[13]); + col4 = vmlaq_n_f32(col4, cola3, b.matrix[14]); + col4 = vmlaq_n_f32(col4, cola4, b.matrix[15]); + + vst1q_f32(&t[0], col1); + vst1q_f32(&t[4], col2); + vst1q_f32(&t[8], col3); + vst1q_f32(&t[12], col4); +#else + t[0] = (a.matrix[0] * b.matrix[0]) + (a.matrix[4] * b.matrix[1]) + + (a.matrix[8] * b.matrix[2]) + (a.matrix[12] * b.matrix[3]); + t[4] = (a.matrix[0] * b.matrix[4]) + (a.matrix[4] * b.matrix[5]) + + (a.matrix[8] * b.matrix[6]) + (a.matrix[12] * b.matrix[7]); + t[8] = (a.matrix[0] * b.matrix[8]) + (a.matrix[4] * b.matrix[9]) + + (a.matrix[8] * b.matrix[10]) + (a.matrix[12] * b.matrix[11]); + t[12] = (a.matrix[0] * b.matrix[12]) + (a.matrix[4] * b.matrix[13]) + + (a.matrix[8] * b.matrix[14]) + (a.matrix[12] * b.matrix[15]); + + t[1] = (a.matrix[1] * b.matrix[0]) + (a.matrix[5] * b.matrix[1]) + + (a.matrix[9] * b.matrix[2]) + (a.matrix[13] * b.matrix[3]); + t[5] = (a.matrix[1] * b.matrix[4]) + (a.matrix[5] * b.matrix[5]) + + (a.matrix[9] * b.matrix[6]) + (a.matrix[13] * b.matrix[7]); + t[9] = (a.matrix[1] * b.matrix[8]) + (a.matrix[5] * b.matrix[9]) + + (a.matrix[9] * b.matrix[10]) + (a.matrix[13] * b.matrix[11]); + t[13] = (a.matrix[1] * b.matrix[12]) + (a.matrix[5] * b.matrix[13]) + + (a.matrix[9] * b.matrix[14]) + (a.matrix[13] * b.matrix[15]); + + t[2] = (a.matrix[2] * b.matrix[0]) + (a.matrix[6] * b.matrix[1]) + + (a.matrix[10] * b.matrix[2]) + (a.matrix[14] * b.matrix[3]); + t[6] = (a.matrix[2] * b.matrix[4]) + (a.matrix[6] * b.matrix[5]) + + (a.matrix[10] * b.matrix[6]) + (a.matrix[14] * b.matrix[7]); + t[10] = (a.matrix[2] * b.matrix[8]) + (a.matrix[6] * b.matrix[9]) + + (a.matrix[10] * b.matrix[10]) + (a.matrix[14] * b.matrix[11]); + t[14] = (a.matrix[2] * b.matrix[12]) + (a.matrix[6] * b.matrix[13]) + + (a.matrix[10] * b.matrix[14]) + (a.matrix[14] * b.matrix[15]); + + t[3] = (a.matrix[3] * b.matrix[0]) + (a.matrix[7] * b.matrix[1]) + + (a.matrix[11] * b.matrix[2]) + (a.matrix[15] * b.matrix[3]); + t[7] = (a.matrix[3] * b.matrix[4]) + (a.matrix[7] * b.matrix[5]) + + (a.matrix[11] * b.matrix[6]) + (a.matrix[15] * b.matrix[7]); + t[11] = (a.matrix[3] * b.matrix[8]) + (a.matrix[7] * b.matrix[9]) + + (a.matrix[11] * b.matrix[10]) + (a.matrix[15] * b.matrix[11]); + t[15] = (a.matrix[3] * b.matrix[12]) + (a.matrix[7] * b.matrix[13]) + + (a.matrix[11] * b.matrix[14]) + (a.matrix[15] * b.matrix[15]); +#endif + } + public: - void Transpose() - {} + static void Multiply(const Matrix4& a, const Matrix4& b, Matrix4& result) + { + Multiply(a, b, result.matrix); + } + + Matrix4() + { + this->SetIdentity(); + } + + Matrix4(float t00, float t10, float t01, float t11, float x, float y) + { + this->SetRawTransformation(t00, t10, t01, t11, x, y); + } + + Matrix4(const Elements elements) + { + std::copy_n(elements, 16, this->matrix); + } + + Matrix4(const Matrix4& a, const Matrix4& b) + { + this->Multiply(a, b, this->matrix); + } + + Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, + float ky) + { + this->SetTransformation(x, y, angle, sx, sy, ox, oy, kx, ky); + } + + Matrix4 operator*(const Matrix4& other) const + { + return Matrix4(*this, other); + } + + void operator*=(const Matrix4& other) + { + Elements elements; + this->Multiply(*this, other, elements); + std::copy_n(elements, 16, this->matrix); + } + + const Elements& GetElements() const + { + return this->matrix; + } + + void SetRow(int row, const Vector4& vector) + { + this->matrix[0 * 4 + row] = vector.x; + this->matrix[1 * 4 + row] = vector.y; + this->matrix[2 * 4 + row] = vector.z; + this->matrix[3 * 4 + row] = vector.w; + } + + Vector4 GetRow(int row) + { + return Vector4(this->matrix[0 * 4 + row], this->matrix[1 * 4 + row], + this->matrix[2 * 4 + row], this->matrix[3 * 4 + row]); + } + + void SetColumn(int column, const Vector4& vector) + { + this->matrix[column * 4 + 0] = vector.x; + this->matrix[column * 4 + 1] = vector.y; + this->matrix[column * 4 + 2] = vector.z; + this->matrix[column * 4 + 3] = vector.w; + } + + Vector4 GetColumn(int column) + { + return Vector4(this->matrix[column * 4 + 0], this->matrix[column * 4 + 1], + this->matrix[column * 4 + 2], this->matrix[column * 4 + 3]); + } + + void SetIdentity() + { + std::fill_n(this->matrix, 16, 0.0f); + this->matrix[15] = this->matrix[10] = this->matrix[5] = this->matrix[0] = 1; + } + + void SetTranslation(float x, float y) + { + this->SetIdentity(); + this->matrix[12] = x; + this->matrix[13] = y; + } + + void SetRotation(float rotation) + { + this->SetIdentity(); + + float cos = std::cos(rotation); + float sin = std::sin(rotation); + + this->matrix[0] = cos; + this->matrix[4] = -sin; + this->matrix[1] = sin; + this->matrix[5] = cos; + } + + void SetScale(float sx, float sy) + { + this->SetIdentity(); + + this->matrix[0] = sx; + this->matrix[5] = sy; + } + + void SetShear(float kx, float ky) + { + this->SetIdentity(); + + this->matrix[1] = ky; + this->matrix[4] = kx; + } + + void GetApproximateScale(float& sx, float& sy) const + { + sx = std::sqrt(this->matrix[0] * this->matrix[0] + this->matrix[4] * this->matrix[4]); + sy = std::sqrt(this->matrix[1] * this->matrix[1] + this->matrix[5] * this->matrix[5]); + } + + void SetRawTransformation(float t00, float t10, float t01, float t11, float x, float y) + { + std::fill_n(this->matrix, 16, 0.0f); + + this->matrix[10] = this->matrix[15] = 1.0f; + this->matrix[0] = t00; + this->matrix[1] = t10; + this->matrix[4] = t01; + this->matrix[5] = t11; + this->matrix[12] = x; + this->matrix[13] = y; + } + + void SetTransformation(float x, float y, float angle, float sx, float sy, float ox, + float oy, float kx, float ky) + { + std::fill_n(this->matrix, 16, 0.0f); + + float cos = std::cos(angle); + float sin = std::sin(angle); + + this->matrix[10] = this->matrix[15] = 1.0f; + this->matrix[0] = cos * sx - ky * sin * sy; // = a + this->matrix[1] = sin * sx + ky * cos * sy; // = b + this->matrix[4] = kx * cos * sx - sin * sy; // = c + this->matrix[5] = kx * sin * sx + cos * sy; // = d + this->matrix[12] = x - ox * this->matrix[0] - oy * this->matrix[4]; + this->matrix[13] = y - ox * this->matrix[1] - oy * this->matrix[5]; + } + + void Translate(float x, float y) + { + Matrix4 t {}; + t.SetTranslation(x, y); + this->operator*=(t); + } + + void Rotate(float rotation) + { + Matrix4 t {}; + t.SetRotation(rotation); + this->operator*=(t); + } + + void Scale(float sx, float sy) + { + Matrix4 t {}; + t.SetScale(sx, sy); + this->operator*=(t); + } + + void Shear(float kx, float ky) + { + Matrix4 t {}; + t.SetShear(kx, ky); + this->operator*=(t); + } + + bool IsAffine2DTransform() const + { + return fabsf(this->matrix[2] + this->matrix[3] + this->matrix[6] + this->matrix[7] + + this->matrix[8] + this->matrix[9] + this->matrix[11] + this->matrix[14]) < + 0.00001f && + fabsf(this->matrix[10] + this->matrix[15] - 2.0f) < 0.00001f; + } + + bool IsAffine3DTransform() const; + + template + void TransformXY0(Vdst&&, const Vsrc&&, int size) const; + + template + /* transform Vector2 src into Vector2 dst */ + void TransformXY(Vdst&& dst, Vsrc&& src) const + { + if constexpr (std::is_same_v>, + vertex::Vertex> || + std::is_same_v>, + vertex::Vertex>) + { + TransformXY(DeVertexize(dst), DeVertexize(src)); + return; + } + else + { + // This might need to be an assert; jury's out + // static_assert(std::ranges::size(dst) == std::ranges::size(src)); + + for (size_t i = 0; i < std::ranges::size(dst); i++) + { + float x = (this->matrix[0] * src[i].x) + (this->matrix[4] * src[i].y) + (0) + + (this->matrix[12]); + + float y = (this->matrix[1] * src[i].x) + (this->matrix[5] * src[i].y) + (0) + + (this->matrix[13]); + + dst[i].x = x; + dst[i].y = y; + } + } + } + + template + /* transform Vector3 src into Vector3 dst */ + void TransformXYZ(Vdst&& dst, Vsrc&& src) const + { + if constexpr (std::is_same_v>, + vertex::Vertex> || + std::is_same_v>, + vertex::Vertex>) + { + TransformXYZ(DeVertexize(dst), DeVertexize(src)); + return; + } + else + { + // static_assert(std::ranges::size(dst) == std::ranges::size(src)); + + for (size_t i = 0; i < std::ranges::size(dst); i++) + { + float x = (this->matrix[0] * src[i].x) + (this->matrix[4] * src[i].y) + + (this->matrix[8] * src[i].z) + (this->matrix[12]); + + float y = (this->matrix[1] * src[i].x) + (this->matrix[5] * src[i].y) + + (this->matrix[9] * src[i].z) + (this->matrix[13]); + + float z = (this->matrix[2] * src[i].x) + (this->matrix[6] * src[i].y) + + (this->matrix[10] * src[i].z) + (this->matrix[14]); + + dst[i].x = x; + dst[i].y = y; + dst[i].z = z; + } + } + } + + Matrix4 Inverse() const + { + Matrix4 inv; + + inv.matrix[0] = + matrix[5] * matrix[10] * matrix[15] - matrix[5] * matrix[11] * matrix[14] - + matrix[9] * matrix[6] * matrix[15] + matrix[9] * matrix[7] * matrix[14] + + matrix[13] * matrix[6] * matrix[11] - matrix[13] * matrix[7] * matrix[10]; + + inv.matrix[4] = + -matrix[4] * matrix[10] * matrix[15] + matrix[4] * matrix[11] * matrix[14] + + matrix[8] * matrix[6] * matrix[15] - matrix[8] * matrix[7] * matrix[14] - + matrix[12] * matrix[6] * matrix[11] + matrix[12] * matrix[7] * matrix[10]; + + inv.matrix[8] = + matrix[4] * matrix[9] * matrix[15] - matrix[4] * matrix[11] * matrix[13] - + matrix[8] * matrix[5] * matrix[15] + matrix[8] * matrix[7] * matrix[13] + + matrix[12] * matrix[5] * matrix[11] - matrix[12] * matrix[7] * matrix[9]; + + inv.matrix[12] = + -matrix[4] * matrix[9] * matrix[14] + matrix[4] * matrix[10] * matrix[13] + + matrix[8] * matrix[5] * matrix[14] - matrix[8] * matrix[6] * matrix[13] - + matrix[12] * matrix[5] * matrix[10] + matrix[12] * matrix[6] * matrix[9]; + + inv.matrix[1] = + -matrix[1] * matrix[10] * matrix[15] + matrix[1] * matrix[11] * matrix[14] + + matrix[9] * matrix[2] * matrix[15] - matrix[9] * matrix[3] * matrix[14] - + matrix[13] * matrix[2] * matrix[11] + matrix[13] * matrix[3] * matrix[10]; + + inv.matrix[5] = + matrix[0] * matrix[10] * matrix[15] - matrix[0] * matrix[11] * matrix[14] - + matrix[8] * matrix[2] * matrix[15] + matrix[8] * matrix[3] * matrix[14] + + matrix[12] * matrix[2] * matrix[11] - matrix[12] * matrix[3] * matrix[10]; + + inv.matrix[9] = + -matrix[0] * matrix[9] * matrix[15] + matrix[0] * matrix[11] * matrix[13] + + matrix[8] * matrix[1] * matrix[15] - matrix[8] * matrix[3] * matrix[13] - + matrix[12] * matrix[1] * matrix[11] + matrix[12] * matrix[3] * matrix[9]; + + inv.matrix[13] = + matrix[0] * matrix[9] * matrix[14] - matrix[0] * matrix[10] * matrix[13] - + matrix[8] * matrix[1] * matrix[14] + matrix[8] * matrix[2] * matrix[13] + + matrix[12] * matrix[1] * matrix[10] - matrix[12] * matrix[2] * matrix[9]; + + inv.matrix[2] = + matrix[1] * matrix[6] * matrix[15] - matrix[1] * matrix[7] * matrix[14] - + matrix[5] * matrix[2] * matrix[15] + matrix[5] * matrix[3] * matrix[14] + + matrix[13] * matrix[2] * matrix[7] - matrix[13] * matrix[3] * matrix[6]; + + inv.matrix[6] = + -matrix[0] * matrix[6] * matrix[15] + matrix[0] * matrix[7] * matrix[14] + + matrix[4] * matrix[2] * matrix[15] - matrix[4] * matrix[3] * matrix[14] - + matrix[12] * matrix[2] * matrix[7] + matrix[12] * matrix[3] * matrix[6]; + + inv.matrix[10] = + matrix[0] * matrix[5] * matrix[15] - matrix[0] * matrix[7] * matrix[13] - + matrix[4] * matrix[1] * matrix[15] + matrix[4] * matrix[3] * matrix[13] + + matrix[12] * matrix[1] * matrix[7] - matrix[12] * matrix[3] * matrix[5]; + + inv.matrix[14] = + -matrix[0] * matrix[5] * matrix[14] + matrix[0] * matrix[6] * matrix[13] + + matrix[4] * matrix[1] * matrix[14] - matrix[4] * matrix[2] * matrix[13] - + matrix[12] * matrix[1] * matrix[6] + matrix[12] * matrix[2] * matrix[5]; + + inv.matrix[3] = + -matrix[1] * matrix[6] * matrix[11] + matrix[1] * matrix[7] * matrix[10] + + matrix[5] * matrix[2] * matrix[11] - matrix[5] * matrix[3] * matrix[10] - + matrix[9] * matrix[2] * matrix[7] + matrix[9] * matrix[3] * matrix[6]; + + inv.matrix[7] = + matrix[0] * matrix[6] * matrix[11] - matrix[0] * matrix[7] * matrix[10] - + matrix[4] * matrix[2] * matrix[11] + matrix[4] * matrix[3] * matrix[10] + + matrix[8] * matrix[2] * matrix[7] - matrix[8] * matrix[3] * matrix[6]; + + inv.matrix[11] = + -matrix[0] * matrix[5] * matrix[11] + matrix[0] * matrix[7] * matrix[9] + + matrix[4] * matrix[1] * matrix[11] - matrix[4] * matrix[3] * matrix[9] - + matrix[8] * matrix[1] * matrix[7] + matrix[8] * matrix[3] * matrix[5]; + + inv.matrix[15] = + matrix[0] * matrix[5] * matrix[10] - matrix[0] * matrix[6] * matrix[9] - + matrix[4] * matrix[1] * matrix[10] + matrix[4] * matrix[2] * matrix[9] + + matrix[8] * matrix[1] * matrix[6] - matrix[8] * matrix[2] * matrix[5]; + + float det = matrix[0] * inv.matrix[0] + matrix[1] * inv.matrix[4] + + matrix[2] * inv.matrix[8] + matrix[3] * inv.matrix[12]; + + float invdet = 1.0f / det; + + for (int i = 0; i < 16; i++) + inv.matrix[i] *= invdet; + + return inv; + } + + static Matrix4 Ortho(float left, float right, float bottom, float top, float near, + float far) + { + Matrix4 t {}; + + t.matrix[0] = 2.0f / (right - left); + t.matrix[5] = 2.0f / (top - bottom); + t.matrix[10] = -2.0f / (far - near); + + t.matrix[12] = -(right + left) / (right - left); + t.matrix[13] = -(top + bottom) / (top - bottom); + t.matrix[14] = -(far + near) / (far - near); + + return t; + } + + static Matrix4 Perspective(float verticalfov, float aspect, float near, float far) + { + Matrix4 t {}; + + float cotangent = 1.0f / tanf(verticalfov * 0.5f); + + t.matrix[0] = cotangent / aspect; + t.matrix[5] = cotangent; + t.matrix[10] = (far + near) / (near - far); + t.matrix[11] = -1.0f; + + t.matrix[14] = 2.0f * near * far / (near - far); + t.matrix[15] = 0.0f; + + return t; + } + + protected: + Elements matrix; }; } // namespace love diff --git a/include/common/optional.hpp b/include/common/optional.hpp new file mode 100644 index 000000000..a28053099 --- /dev/null +++ b/include/common/optional.hpp @@ -0,0 +1,60 @@ +/** + * 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. + **/ + +#pragma once + +namespace love +{ + // Currently only meant for simple and small types. + template + struct Optional + { + T value; + bool hasValue; + + Optional() : value(T()), hasValue(false) + {} + + Optional(T val) : value(val), hasValue(true) + {} + + void set(T val) + { + value = val; + hasValue = true; + } + + T get(T defaultVal) const + { + return hasValue ? value : defaultVal; + } + + void clear() + { + hasValue = false; + } + }; + + typedef Optional OptionalBool; + typedef Optional OptionalFloat; + typedef Optional OptionalDouble; + typedef Optional OptionalInt; + +} // namespace love diff --git a/include/common/vector.hpp b/include/common/vector.hpp index 621f9c1de..81d3860fa 100644 --- a/include/common/vector.hpp +++ b/include/common/vector.hpp @@ -23,6 +23,7 @@ // STD #include +#include namespace love { @@ -41,6 +42,24 @@ namespace love Vector2(const Vector2& v) : x(v.x), y(v.y) {} + float& operator[](size_t i) + { + if (i == 0) + { + return x; + } + return y; + } + + const float& operator[](size_t i) const + { + if (i == 0) + { + return x; + } + return y; + } + float getLength() const; float getLengthSquare() const; @@ -98,6 +117,32 @@ namespace love Vector3(const Vector2& v, float z = 0.0f) : x(v.x), y(v.y), z(z) {} + float& operator[](size_t i) + { + if (i == 0) + { + return x; + } + else if (i == 1) + { + return y; + } + return z; + } + + const float& operator[](size_t i) const + { + if (i == 0) + { + return x; + } + else if (i == 1) + { + return y; + } + return z; + } + bool isZero() const { return this->x == 0.0f && this->y == 0.0f && this->z == 0.0f; @@ -151,6 +196,40 @@ namespace love Vector4(const Vector3& v, float w = 0.0f) : x(v.x), y(v.y), z(v.z), w(w) {} + float& operator[](size_t i) + { + if (i == 0) + { + return x; + } + else if (i == 1) + { + return y; + } + else if (i == 2) + { + return z; + } + return w; + } + + const float& operator[](size_t i) const + { + if (i == 0) + { + return x; + } + else if (i == 1) + { + return y; + } + else if (i == 2) + { + return z; + } + return w; + } + float getLength() const; float getLengthSquare() const; diff --git a/include/common/version.hpp b/include/common/version.hpp index 7cc2236df..98f6415f4 100644 --- a/include/common/version.hpp +++ b/include/common/version.hpp @@ -77,5 +77,5 @@ namespace love static constexpr Version LOVE_FRAMEWORK(__LOVE_VERSION__); static constexpr const char* CODENAME = "Mysterious Mysteries"; - static constexpr std::array COMPATIBILITY = { __APP_VERSION__ }; + static constexpr std::array COMPATIBILITY = { __APP_VERSION__, nullptr }; } // namespace love diff --git a/include/modules/graphics/graphics.tcc b/include/modules/graphics/graphics.tcc index 97e2cc048..c652903d2 100644 --- a/include/modules/graphics/graphics.tcc +++ b/include/modules/graphics/graphics.tcc @@ -4,9 +4,10 @@ #include #include #include +#include #include -#include +#include #include #include @@ -38,9 +39,7 @@ namespace love { - using OptionalColor = std::optional; - using OptionalInt = std::optional; - using OptionalDouble = std::optional; + using OptionalColor = Optional; template class Graphics : public Module @@ -301,7 +300,7 @@ namespace love renderTargetSwitchCount(0) { this->transformStack.reserve(16); - this->transformStack.push_back(Matrix4()); + this->transformStack.push_back(Matrix4()); this->pixelScaleStack.reserve(16); this->pixelScaleStack.push_back(1.0); @@ -330,22 +329,22 @@ namespace love { Renderer::Instance().BindFramebuffer(); - if (color.has_value()) + if (color.hasValue) { // GammaCorrectColor(color); - Renderer::Instance().Clear(color.value()); + Renderer::Instance().Clear(color.value); } - if (stencil.has_value() && depth.has_value()) - Renderer::Instance().ClearDepthStencil(stencil.value(), 0xFF, - depth.value()); + if (stencil.hasValue && depth.hasValue) + Renderer::Instance().ClearDepthStencil(stencil.value, 0xFF, + depth.value); } void Clear(std::vector& colors, OptionalInt stencil, OptionalDouble depth) { int colorCount = colors.size(); - if (colorCount == 0 || !stencil.has_value() || !depth.has_value()) + if (colorCount == 0 || !stencil.hasValue || !depth.hasValue) this->Clear(colorCount > 0 ? colors[0] : Color {}, stencil, depth); } @@ -394,12 +393,13 @@ namespace love void SetFont(Font* font) { - this->states.back().font = font; + this->states.back().font.Set(font); } Font* GetFont() { - return this->states.back().font; + this->CheckSetDefaultFont(); + return this->states.back().font.Get(); } SpriteBatch* NewSpriteBatch(Texture* texture, int size) const @@ -715,7 +715,7 @@ namespace love this->states.back().font.Set(this->defaultFont.Get()); } - void Print(const ColoredStrings& strings, const Matrix4& matrix) + void Print(const ColoredStrings& strings, const Matrix4& matrix) { this->CheckSetDefaultFont(); @@ -723,13 +723,13 @@ namespace love this->Print(strings, this->states.back().font.Get(), matrix); } - void Print(const ColoredStrings& strings, Font* font, const Matrix4& matrix) + void Print(const ColoredStrings& strings, Font* font, const Matrix4& matrix) { font->Print(*this, strings, matrix, this->states.back().foreground); } void Printf(const ColoredStrings& strings, float wrap, Font::AlignMode align, - const Matrix4& matrix) + const Matrix4& matrix) { this->CheckSetDefaultFont(); @@ -738,7 +738,7 @@ namespace love } void Printf(const ColoredStrings& strings, Font* font, float wrap, Font::AlignMode align, - const Matrix4& matrix) + const Matrix4& matrix) { font->Printf(*this, strings, wrap, align, matrix, this->states.back().foreground); } @@ -802,7 +802,7 @@ namespace love void PushIdentityTransform() { - this->transformStack.push_back(Matrix4()); + this->transformStack.push_back(Matrix4()); } void PopTransform() @@ -810,7 +810,7 @@ namespace love this->transformStack.pop_back(); } - const Matrix4& GetTransform() const + const Matrix4& GetTransform() const { return this->transformStack.back(); } @@ -826,7 +826,7 @@ namespace love this->pixelScaleStack.back() *= (fabs(x) + fabs(y)) / 2.0; } - void ApplyTransform(const Matrix4& matrix) + void ApplyTransform(const Matrix4& matrix) { auto& current = this->transformStack.back(); current *= matrix; @@ -836,7 +836,7 @@ namespace love this->pixelScaleStack.back() = (scaleX + scaleY) / 2.0; } - void ReplaceTransform(const Matrix4& matrix) + void ReplaceTransform(const Matrix4& matrix) { this->transformStack.back() = matrix; @@ -848,7 +848,8 @@ namespace love Vector2 TransformPoint(Vector2 point) { Vector2 result {}; - this->transformStack.back().TransformXY(&result, &point, 1); + this->transformStack.back().TransformXY(std::views::single(result), + std::views::single(point)); return result; } @@ -856,7 +857,8 @@ namespace love Vector2 InverseTransformPoint(Vector2 point) { Vector2 result {}; - this->transformStack.back().Inverse().TransformXY(&result, &point, 1); + this->transformStack.back().Inverse().TransformXY(std::views::single(result), + std::views::single(point)); return result; } @@ -884,7 +886,7 @@ namespace love this->SetColor(state.foreground); this->SetBackgroundColor(state.background); - /* todo: set blend state */ + this->SetBlendState(state.blendState); this->SetLineWidth(state.line.width); this->SetLineStyle(state.line.style); @@ -892,6 +894,11 @@ namespace love this->SetPointSize(state.pointSize); + if (state.scissor.active) + this->SetScissor(state.scissor.bounds); + else + this->SetScissor(); + this->SetMeshCullMode(state.cullMode); this->SetFrontFaceWinding(state.windingMode); @@ -926,7 +933,8 @@ namespace love this->SetBackgroundColor(state.background); - /* todo set blend state */ + if (!(state.blendState == current.blendState)) + this->SetBlendState(state.blendState); this->SetLineWidth(state.line.width); this->SetLineStyle(state.line.style); @@ -935,6 +943,17 @@ namespace love if (state.pointSize != current.pointSize) this->SetPointSize(state.pointSize); + bool scissorActive = state.scissor.active != current.scissor.active; + bool sameScissorBounds = state.scissor.bounds == current.scissor.bounds; + + if (scissorActive || (state.scissor.active && !sameScissorBounds)) + { + if (state.scissor.active) + this->SetScissor(state.scissor.bounds); + else + this->SetScissor(); + } + this->SetMeshCullMode(state.cullMode); if (state.windingMode != current.windingMode) @@ -1150,7 +1169,8 @@ namespace love DrawCommand command(count, vertex::PRIMITIVE_TRIANGLE_FAN); if (is2D) - transform.TransformXY(command.Positions().get(), points.data(), command.count); + transform.TransformXY(std::span(command.Positions().get(), command.count), + points); command.FillVertices(this->GetColor()); @@ -1389,7 +1409,7 @@ namespace love DrawCommand command(points.size(), vertex::PRIMITIVE_POINTS); if (is2D) - transform.TransformXY(command.Positions().get(), points.data(), points.size()); + transform.TransformXY(std::span(command.Positions().get(), points.size()), points); if (colors.size() > 1) command.FillVertices(colors); @@ -1460,7 +1480,7 @@ namespace love } } - void InternalScale(const Matrix4& transform) + void InternalScale(const Matrix4& transform) { this->transformStack.back() *= transform; } @@ -1512,7 +1532,7 @@ namespace love protected: std::vector pixelScaleStack; - std::vector> transformStack; + std::vector transformStack; std::vector states; std::vector stackTypeStack; diff --git a/include/modules/graphics/wrap_graphics.hpp b/include/modules/graphics/wrap_graphics.hpp index ced9315fb..630b8735e 100644 --- a/include/modules/graphics/wrap_graphics.hpp +++ b/include/modules/graphics/wrap_graphics.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include namespace Wrap_Graphics @@ -26,7 +26,7 @@ namespace Wrap_Graphics float oy = luaL_optnumber(L, index + 6, 0.0); float kx = luaL_optnumber(L, index + 7, 0.0); float ky = luaL_optnumber(L, index + 8, 0.0); - func(love::Matrix4(x, y, a, sx, sy, ox, oy, kx, ky)); + func(love::Matrix4(x, y, a, sx, sy, ox, oy, kx, ky)); } } diff --git a/include/modules/love/love.hpp b/include/modules/love/love.hpp index ab89679d4..6e46ae123 100644 --- a/include/modules/love/love.hpp +++ b/include/modules/love/love.hpp @@ -36,4 +36,11 @@ namespace love int GetVersion(lua_State* L); int IsVersionCompatible(lua_State* L); + + int SetGammaCorrect(lua_State* L); } // namespace love + +extern "C" +{ + extern int luaopen_https(lua_State*); +} diff --git a/include/objects/font/font.hpp b/include/objects/font/font.hpp index 4cfa88196..d719fbb54 100644 --- a/include/objects/font/font.hpp +++ b/include/objects/font/font.hpp @@ -96,10 +96,10 @@ namespace love {} void Print(Graphics& graphics, const ColoredStrings& text, - const Matrix4& localTransform, const Color& color); + const Matrix4& localTransform, const Color& color); void Printf(Graphics& graphics, const ColoredStrings& text, float wrap, - AlignMode alignment, const Matrix4& localTransform, + AlignMode alignment, const Matrix4& localTransform, const Color& color); int GetAscent() const; @@ -175,7 +175,7 @@ namespace love const Glyph& FindGlyph(TextShaper::GlyphIndex glyphIndex); - void Printv(Graphics& graphics, const Matrix4& transform, + void Printv(Graphics& graphics, const Matrix4& transform, const std::vector& drawCommands, const std::vector& vertices); diff --git a/include/objects/mesh/mesh.hpp b/include/objects/mesh/mesh.hpp index 08554879d..b7b29a370 100644 --- a/include/objects/mesh/mesh.hpp +++ b/include/objects/mesh/mesh.hpp @@ -69,10 +69,10 @@ namespace love bool GetDrawRange(int& start, int& count) const; void Draw(Graphics& graphics, - const Matrix4& matrix) override; + const Matrix4& matrix) override; private: - void DrawInternal(Graphics& graphics, const Matrix4& matrix, + void DrawInternal(Graphics& graphics, const Matrix4& matrix, int instanceCount, std::vector* indirectArgs, int argsIndex); @@ -89,4 +89,4 @@ namespace love Range drawRange; bool useIndexBuffer; }; -} // namespace love \ No newline at end of file +} // namespace love diff --git a/include/objects/spritebatch/spritebatch.hpp b/include/objects/spritebatch/spritebatch.hpp index 3450a2acb..e6f97bead 100644 --- a/include/objects/spritebatch/spritebatch.hpp +++ b/include/objects/spritebatch/spritebatch.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -23,13 +23,13 @@ namespace love virtual ~SpriteBatch(); - int Add(const Matrix4& matrix, int index = -1); + int Add(const Matrix4& matrix, int index = -1); - int Add(Quad* quad, const Matrix4& matrix, int index = -1); + int Add(Quad* quad, const Matrix4& matrix, int index = -1); - int AddLayer(int layer, const Matrix4& matrix, int index = -1); + int AddLayer(int layer, const Matrix4& matrix, int index = -1); - int AddLayer(int layer, Quad* quad, const Matrix4& matrix, int index = -1); + int AddLayer(int layer, Quad* quad, const Matrix4& matrix, int index = -1); void Clear(); @@ -58,7 +58,7 @@ namespace love bool GetDrawRange(int& start, int& count) const; void Draw(Graphics& graphics, - const Matrix4& matrix) override; + const Matrix4& matrix) override; private: void SetBufferSize(int size); @@ -78,4 +78,4 @@ namespace love int rangeStart; int rangeCount; }; -} // namespace love \ No newline at end of file +} // namespace love diff --git a/include/objects/textbatch/textbatch.hpp b/include/objects/textbatch/textbatch.hpp index 14bad15f4..fb095c299 100644 --- a/include/objects/textbatch/textbatch.hpp +++ b/include/objects/textbatch/textbatch.hpp @@ -23,10 +23,10 @@ namespace love void Set(const ColoredStrings& text, float wrap, Font::AlignMode align); - int Add(const ColoredStrings& text, const Matrix4& matrix); + int Add(const ColoredStrings& text, const Matrix4& matrix); int Addf(const ColoredStrings& text, float wrap, Font::AlignMode align, - const Matrix4& matrix); + const Matrix4& matrix); void Clear(); @@ -42,7 +42,7 @@ namespace love int GetHeight(int index = 0) const; void Draw(Graphics& graphics, - const Matrix4& matrix) override; + const Matrix4& matrix) override; private: struct TextData @@ -53,7 +53,7 @@ namespace love TextShaper::TextInfo textInfo; bool useMatrix; bool appendVertices; - Matrix4 matrix; + Matrix4 matrix; }; void UploadVertices(const std::vector& vertices, size_t offset); diff --git a/include/objects/texture/texture.tcc b/include/objects/texture/texture.tcc index ef1dceb78..b856ac1e8 100644 --- a/include/objects/texture/texture.tcc +++ b/include/objects/texture/texture.tcc @@ -17,6 +17,8 @@ #include #include +#include + namespace love { using VectorMipmapLayers = std::vector>>; @@ -510,11 +512,10 @@ namespace love return this->quad; } - virtual void Draw(Graphics& graphics, - const Matrix4& transform) = 0; + virtual void Draw(Graphics& graphics, const Matrix4& transform) = 0; virtual void Draw(Graphics& graphics, Quad* quad, - const Matrix4& transform) = 0; + const Matrix4& transform) = 0; // clang-format off static constexpr BidirectionalMap textureTypes = { diff --git a/include/objects/transform/transform.hpp b/include/objects/transform/transform.hpp index 454a8071b..889831fe4 100644 --- a/include/objects/transform/transform.hpp +++ b/include/objects/transform/transform.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -21,7 +21,7 @@ namespace love Transform(); - Transform(const Matrix4& matrix); + Transform(const Matrix4& matrix); Transform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky); @@ -52,9 +52,9 @@ namespace love Vector2 InverseTransformPoint(Vector2 point); - Matrix4& GetMatrix(); + Matrix4& GetMatrix(); - void SetMatrix(const Matrix4& matrix); + void SetMatrix(const Matrix4& matrix); // clang-format off static constexpr BidirectionalMap matrixLayouts = { @@ -64,7 +64,7 @@ namespace love // clang-format on private: - inline const Matrix4& GetInverseMatrix() + inline const Matrix4& GetInverseMatrix() { if (this->inverseDirty) { @@ -75,8 +75,8 @@ namespace love return this->inverseMatrix; } - Matrix4 matrix; + Matrix4 matrix; bool inverseDirty; - Matrix4 inverseMatrix; + Matrix4 inverseMatrix; }; } // namespace love diff --git a/include/utilities/driver/renderer/vertex.hpp b/include/utilities/driver/renderer/vertex.hpp index 0a17a1a87..acc208e18 100644 --- a/include/utilities/driver/renderer/vertex.hpp +++ b/include/utilities/driver/renderer/vertex.hpp @@ -82,7 +82,7 @@ namespace love struct Vertex { - std::array position; + Vector3 position; std::array color; std::array texcoord; }; diff --git a/include/utilities/log/logfile.hpp b/include/utilities/log/logfile.hpp index e8639a405..a12e0357f 100644 --- a/include/utilities/log/logfile.hpp +++ b/include/utilities/log/logfile.hpp @@ -14,9 +14,9 @@ class Log { public: - static Log& Instance() + static Log& Instance(bool enable = false) { - static Log instance; + static Log instance(enable); return instance; } @@ -51,9 +51,9 @@ class Log static inline const char* FILENAME = "debug.log"; static constexpr const char* BUFFER_FORMAT = "%s(%zu:%zu): `%s`:\n%s\n\n"; - Log() : file(nullptr) + Log(bool enable) : file(nullptr) { - if (m_enabled) + if (m_enabled || enable) this->file = fopen(FILENAME, "w"); } diff --git a/include/utilities/temptransform.hpp b/include/utilities/temptransform.hpp index b36e4bbf5..ef1a56a61 100644 --- a/include/utilities/temptransform.hpp +++ b/include/utilities/temptransform.hpp @@ -12,8 +12,7 @@ namespace love this->graphics->PushTransform(); } - TempTransform(Graphics& graphics, - const Matrix4& transform) : + TempTransform(Graphics& graphics, const Matrix4& transform) : TempTransform(graphics) { this->graphics->PushTransform(); @@ -21,15 +20,17 @@ namespace love } template - void TransformXY(vDst dst, vSrc src, int count) + void TransformXY(vDst&& dst, vSrc&& src) { - this->graphics->GetTransform().TransformXYVert(dst, src, count); + this->graphics->GetTransform().TransformXY(std::forward(dst), + std::forward(src)); } template - void TransformXYPure(vDst dst, vSrc src, int count) + void TransformXYPure(vDst&& dst, vSrc&& src) { - this->graphics->GetTransform().TransformXYVertPure(dst, src, count); + this->graphics->GetTransform().TransformXY(std::forward(dst), + std::forward(src)); } ~TempTransform() diff --git a/platform/cafe/CMakeLists.txt b/platform/cafe/CMakeLists.txt index 08b46614b..f0f25db58 100644 --- a/platform/cafe/CMakeLists.txt +++ b/platform/cafe/CMakeLists.txt @@ -3,15 +3,15 @@ dkp_add_asset_target(${PROJECT_NAME}_cafe_content content) dkp_track_assets(${PROJECT_NAME}_cafe_content FOLDER shaders - FILES - color.gsh + FILES + color.gsh texture.gsh ) dkp_track_assets(${PROJECT_NAME}_cafe_content FOLDER nogame - FILES - cartridge.png + FILES + cartridge.png nogame.png ) @@ -21,7 +21,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE # find source -type f | grep "\.cpp$" | clip target_sources(${PROJECT_NAME} PRIVATE - source/common/matrix_ext.cpp source/common/screen_ext.cpp source/modules/fontmodule_ext.cpp source/modules/graphics_ext.cpp diff --git a/platform/cafe/include/common/matrix_ext.hpp b/platform/cafe/include/common/matrix_ext.hpp index 15f77240d..d8f10a68b 100644 --- a/platform/cafe/include/common/matrix_ext.hpp +++ b/platform/cafe/include/common/matrix_ext.hpp @@ -7,153 +7,6 @@ namespace love template<> class Matrix4 : public Matrix4 { - public: - Matrix4(); - - Matrix4(const float elements[16]); - - Matrix4(const Matrix4& a, const Matrix4& b); - - Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, - float ky); - - Matrix4(float t00, float t10, float t01, float t11, float x, float y); - - void SetIdentity(); - - void Transpose() - {} - - void SetTranslation(float x, float y); - - void Translate(float x, float y); - - void Rotate(float r); - - void Scale(float sx, float sy); - - void Shear(float kx, float ky); - - bool IsAffine2DTransform() const; - - bool IsAffine3DTransform() const; - - Matrix4 Inverse() const; - - void SetRawTransformation(float t00, float t10, float t01, float t11, float x, float y); - - void SetTransformation(float x, float y, float angle, float sx, float sy, float ox, - float oy, float kx, float ky); - - void Translation(float x, float y); - - void SetRotation(float r); - - void SetScale(float x, float y); - - void SetShear(float kx, float ky); - - void GetApproximateScale(float& sx, float& sy) const; - - Matrix4 operator*(const Matrix4& m) const; - - void operator*=(const Matrix4& m); - - static Matrix4 Ortho(float left, float right, float bottom, float top, float near, - float far); - - static void Multiply(const Matrix4& a, const Matrix4& b, Matrix4& result); - - float Get(const unsigned row, const unsigned column) const - { - return this->elements[column * 4 + row]; - } - - void Set(const unsigned row, const unsigned column, const float value) - { - this->elements[column * 4 + row] = value; - } - - void TransformXY(float elements[16]); - - void TransformXY(); - - /** - * Transforms an array of 2-component vertices by this Matrix. The source - * and destination arrays may be the same. - **/ - template - void TransformXY(Vdst* dst, const Vsrc* src, int size) const; - - template - void TransformXYVert(Vdst* dst, const Vsrc* src, int size) const; - - template - void TransformXYVertPure(Vdst* dst, const Vsrc* src, int size) const; - - /** - * Transforms an array of 2-component vertices by this Matrix, and stores - * them in an array of 3-component vertices. - **/ - template - void TransformXY0(Vdst* dst, const Vsrc* src, int size) const; - - private: - static void Multiply(const Matrix4& a, const Matrix4& b, float elements[16]); - - float elements[16]; - }; - - /* use with Vector2 */ - template - void Matrix4::TransformXY(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->elements[0] * src[i].x) + (this->elements[4] * src[i].y) + (0) + - (this->elements[12]); - float y = (this->elements[1] * src[i].x) + (this->elements[5] * src[i].y) + (0) + - (this->elements[13]); - - dst[i].x = x; - dst[i].y = y; - } - } - - /* use with Vertex */ - template - void Matrix4::TransformXYVert(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->elements[0] * src[i].position[0]) + - (this->elements[4] * src[i].position[1]) + (0) + (this->elements[12]); - - float y = (this->elements[1] * src[i].position[0]) + - (this->elements[5] * src[i].position[1]) + (0) + (this->elements[13]); - - dst[i].x = x; - dst[i].y = y; - } - } - - /* use with Vertex */ - template - void Matrix4::TransformXYVertPure(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->elements[0] * src[i].position[0]) + - (this->elements[4] * src[i].position[1]) + (0) + (this->elements[12]); - - float y = (this->elements[1] * src[i].position[0]) + - (this->elements[5] * src[i].position[1]) + (0) + (this->elements[13]); - - dst[i].position[0] = x; - dst[i].position[1] = y; - } + using Matrix4::Matrix4; } } // namespace love diff --git a/platform/cafe/include/modules/graphics_ext.hpp b/platform/cafe/include/modules/graphics_ext.hpp index f5bdadb54..52934def9 100644 --- a/platform/cafe/include/modules/graphics_ext.hpp +++ b/platform/cafe/include/modules/graphics_ext.hpp @@ -17,10 +17,9 @@ namespace love Texture* NewTexture(const Texture<>::Settings& settings, const Texture<>::Slices* slices = nullptr) const; - void Draw(Texture* texture, Quad* quad, - const Matrix4& matrix); + void Draw(Texture* texture, Quad* quad, const Matrix4& matrix); - void Draw(Drawable* drawable, const Matrix4& matrix); + void Draw(Drawable* drawable, const Matrix4& matrix); void SetViewportSize(int width, int height); diff --git a/platform/cafe/include/objects/texture_ext.hpp b/platform/cafe/include/objects/texture_ext.hpp index 0fdf19128..c7415bff5 100644 --- a/platform/cafe/include/objects/texture_ext.hpp +++ b/platform/cafe/include/objects/texture_ext.hpp @@ -17,10 +17,10 @@ namespace love virtual ~Texture(); virtual void Draw(Graphics& graphics, - const Matrix4& matrix) override; + const Matrix4& matrix) override; virtual void Draw(Graphics& graphics, Quad* quad, - const Matrix4& transform) override; + const Matrix4& transform) override; void ReplacePixels(ImageDataBase* data, int slice, int mipmap, int x, int y, bool reloadMipmaps); diff --git a/platform/cafe/source/common/matrix_ext.cpp b/platform/cafe/source/common/matrix_ext.cpp deleted file mode 100644 index e786d4379..000000000 --- a/platform/cafe/source/common/matrix_ext.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#include - -#include - -using namespace love; - -void Matrix4::Multiply(const Matrix4& a, const Matrix4& b, float elements[16]) -{ - elements[0] = (a.elements[0] * b.elements[0]) + (a.elements[4] * b.elements[1]) + - (a.elements[8] * b.elements[2]) + (a.elements[12] * b.elements[3]); - elements[4] = (a.elements[0] * b.elements[4]) + (a.elements[4] * b.elements[5]) + - (a.elements[8] * b.elements[6]) + (a.elements[12] * b.elements[7]); - elements[8] = (a.elements[0] * b.elements[8]) + (a.elements[4] * b.elements[9]) + - (a.elements[8] * b.elements[10]) + (a.elements[12] * b.elements[11]); - elements[12] = (a.elements[0] * b.elements[12]) + (a.elements[4] * b.elements[13]) + - (a.elements[8] * b.elements[14]) + (a.elements[12] * b.elements[15]); - - elements[1] = (a.elements[1] * b.elements[0]) + (a.elements[5] * b.elements[1]) + - (a.elements[9] * b.elements[2]) + (a.elements[13] * b.elements[3]); - elements[5] = (a.elements[1] * b.elements[4]) + (a.elements[5] * b.elements[5]) + - (a.elements[9] * b.elements[6]) + (a.elements[13] * b.elements[7]); - elements[9] = (a.elements[1] * b.elements[8]) + (a.elements[5] * b.elements[9]) + - (a.elements[9] * b.elements[10]) + (a.elements[13] * b.elements[11]); - elements[13] = (a.elements[1] * b.elements[12]) + (a.elements[5] * b.elements[13]) + - (a.elements[9] * b.elements[14]) + (a.elements[13] * b.elements[15]); - - elements[2] = (a.elements[2] * b.elements[0]) + (a.elements[6] * b.elements[1]) + - (a.elements[10] * b.elements[2]) + (a.elements[14] * b.elements[3]); - elements[6] = (a.elements[2] * b.elements[4]) + (a.elements[6] * b.elements[5]) + - (a.elements[10] * b.elements[6]) + (a.elements[14] * b.elements[7]); - elements[10] = (a.elements[2] * b.elements[8]) + (a.elements[6] * b.elements[9]) + - (a.elements[10] * b.elements[10]) + (a.elements[14] * b.elements[11]); - elements[14] = (a.elements[2] * b.elements[12]) + (a.elements[6] * b.elements[13]) + - (a.elements[10] * b.elements[14]) + (a.elements[14] * b.elements[15]); - - elements[3] = (a.elements[3] * b.elements[0]) + (a.elements[7] * b.elements[1]) + - (a.elements[11] * b.elements[2]) + (a.elements[15] * b.elements[3]); - elements[7] = (a.elements[3] * b.elements[4]) + (a.elements[7] * b.elements[5]) + - (a.elements[11] * b.elements[6]) + (a.elements[15] * b.elements[7]); - elements[11] = (a.elements[3] * b.elements[8]) + (a.elements[7] * b.elements[9]) + - (a.elements[11] * b.elements[10]) + (a.elements[15] * b.elements[11]); - elements[15] = (a.elements[3] * b.elements[12]) + (a.elements[7] * b.elements[13]) + - (a.elements[11] * b.elements[14]) + (a.elements[15] * b.elements[15]); -} - -void Matrix4::Multiply(const Matrix4& a, const Matrix4& b, Matrix4& t) -{ - Matrix4::Multiply(a, b, t.elements); -} - -Matrix4::Matrix4() -{ - this->SetIdentity(); -} - -Matrix4::Matrix4(const float elements[16]) -{ - memcpy(this->elements, elements, sizeof(float) * 16); -} - -Matrix4::Matrix4(const Matrix4& a, const Matrix4& b) -{ - Matrix4::Multiply(a, b, this->elements); -} - -Matrix4::Matrix4(float t00, float t10, float t01, float t11, float x, float y) -{ - this->SetRawTransformation(t00, t10, t01, t11, x, y); -} - -Matrix4::Matrix4(float x, float y, float angle, float sx, float sy, float ox, - float oy, float kx, float ky) -{ - this->SetTransformation(x, y, angle, sx, sy, ox, oy, kx, ky); -} - -bool Matrix4::IsAffine2DTransform() const -{ - return fabsf(this->elements[2] + this->elements[3] + this->elements[6] + this->elements[7] + - this->elements[8] + this->elements[9] + this->elements[11] + this->elements[14]) < - 0.00001f && - fabsf(this->elements[10] + this->elements[15] - 2.0f) < 0.00001f; -} - -Matrix4 Matrix4::operator*(const Matrix4& m) const -{ - return Matrix4(*this, m); -} - -void Matrix4::operator*=(const Matrix4& m) -{ - float elements[16]; - - Matrix4::Multiply(*this, m, elements); - memcpy(this->elements, elements, sizeof(float) * 16); -} - -void Matrix4::SetIdentity() -{ - memset(this->elements, 0, sizeof(float) * 16); - this->elements[15] = this->elements[10] = this->elements[5] = this->elements[0] = 1.0f; -} - -void Matrix4::SetTranslation(float x, float y) -{ - this->SetIdentity(); - - this->elements[12] = x; - this->elements[13] = y; -} - -void Matrix4::Translate(float x, float y) -{ - Matrix4 t; - t.SetTranslation(x, y); - this->operator*=(t); -} - -void Matrix4::SetRotation(float rad) -{ - this->SetIdentity(); - float c = cosf(rad), s = sinf(rad); - - this->elements[0] = c; - this->elements[4] = -s; - this->elements[1] = s; - this->elements[5] = c; -} - -void Matrix4::Rotate(float rad) -{ - Matrix4 t; - t.SetRotation(rad); - this->operator*=(t); -} - -void Matrix4::SetScale(float sx, float sy) -{ - this->SetIdentity(); - - this->elements[0] = sx; - this->elements[5] = sy; -} - -void Matrix4::Scale(float sx, float sy) -{ - Matrix4 t; - t.SetScale(sx, sy); - this->operator*=(t); -} - -void Matrix4::SetShear(float kx, float ky) -{ - this->SetIdentity(); - - this->elements[1] = ky; - this->elements[4] = kx; -} - -void Matrix4::Shear(float kx, float ky) -{ - Matrix4 t; - t.SetShear(kx, ky); - this->operator*=(t); -} - -void Matrix4::GetApproximateScale(float& sx, float& sy) const -{ - sx = sqrtf(this->elements[0] * this->elements[0] + this->elements[4] * this->elements[4]); - sy = sqrtf(this->elements[1] * this->elements[1] + this->elements[5] * this->elements[5]); -} - -void Matrix4::SetRawTransformation(float t00, float t10, float t01, float t11, - float x, float y) -{ - memset(this->elements, 0, sizeof(float) * 16); // zero out matrix - - this->elements[10] = this->elements[15] = 1.0f; - this->elements[0] = t00; - this->elements[1] = t10; - this->elements[4] = t01; - this->elements[5] = t11; - this->elements[12] = x; - this->elements[13] = y; -} - -void Matrix4::SetTransformation(float x, float y, float angle, float sx, float sy, - float ox, float oy, float kx, float ky) -{ - memset(this->elements, 0, sizeof(float) * 16); // zero out matrix - float c = cosf(angle), s = sinf(angle); - - this->elements[10] = this->elements[15] = 1.0f; - this->elements[0] = c * sx - ky * s * sy; // = a - this->elements[1] = s * sx + ky * c * sy; // = b - this->elements[4] = kx * c * sx - s * sy; // = c - this->elements[5] = kx * s * sx + c * sy; // = d - this->elements[12] = x - ox * this->elements[0] - oy * this->elements[4]; - this->elements[13] = y - ox * this->elements[1] - oy * this->elements[5]; -} - -Matrix4 Matrix4::Inverse() const -{ - Matrix4 inv; - - inv.elements[0] = this->elements[5] * this->elements[10] * this->elements[15] - - this->elements[5] * this->elements[11] * this->elements[14] - - this->elements[9] * this->elements[6] * this->elements[15] + - this->elements[9] * this->elements[7] * this->elements[14] + - this->elements[13] * this->elements[6] * this->elements[11] - - this->elements[13] * this->elements[7] * this->elements[10]; - - inv.elements[4] = -this->elements[4] * this->elements[10] * this->elements[15] + - this->elements[4] * this->elements[11] * this->elements[14] + - this->elements[8] * this->elements[6] * this->elements[15] - - this->elements[8] * this->elements[7] * this->elements[14] - - this->elements[12] * this->elements[6] * this->elements[11] + - this->elements[12] * this->elements[7] * this->elements[10]; - - inv.elements[8] = this->elements[4] * this->elements[9] * this->elements[15] - - this->elements[4] * this->elements[11] * this->elements[13] - - this->elements[8] * this->elements[5] * this->elements[15] + - this->elements[8] * this->elements[7] * this->elements[13] + - this->elements[12] * this->elements[5] * this->elements[11] - - this->elements[12] * this->elements[7] * this->elements[9]; - - inv.elements[12] = -this->elements[4] * this->elements[9] * this->elements[14] + - this->elements[4] * this->elements[10] * this->elements[13] + - this->elements[8] * this->elements[5] * this->elements[14] - - this->elements[8] * this->elements[6] * this->elements[13] - - this->elements[12] * this->elements[5] * this->elements[10] + - this->elements[12] * this->elements[6] * this->elements[9]; - - inv.elements[1] = -this->elements[1] * this->elements[10] * this->elements[15] + - this->elements[1] * this->elements[11] * this->elements[14] + - this->elements[9] * this->elements[2] * this->elements[15] - - this->elements[9] * this->elements[3] * this->elements[14] - - this->elements[13] * this->elements[2] * this->elements[11] + - this->elements[13] * this->elements[3] * this->elements[10]; - - inv.elements[5] = this->elements[0] * this->elements[10] * this->elements[15] - - this->elements[0] * this->elements[11] * this->elements[14] - - this->elements[8] * this->elements[2] * this->elements[15] + - this->elements[8] * this->elements[3] * this->elements[14] + - this->elements[12] * this->elements[2] * this->elements[11] - - this->elements[12] * this->elements[3] * this->elements[10]; - - inv.elements[9] = -this->elements[0] * this->elements[9] * this->elements[15] + - this->elements[0] * this->elements[11] * this->elements[13] + - this->elements[8] * this->elements[1] * this->elements[15] - - this->elements[8] * this->elements[3] * this->elements[13] - - this->elements[12] * this->elements[1] * this->elements[11] + - this->elements[12] * this->elements[3] * this->elements[9]; - - inv.elements[13] = this->elements[0] * this->elements[9] * this->elements[14] - - this->elements[0] * this->elements[10] * this->elements[13] - - this->elements[8] * this->elements[1] * this->elements[14] + - this->elements[8] * this->elements[2] * this->elements[13] + - this->elements[12] * this->elements[1] * this->elements[10] - - this->elements[12] * this->elements[2] * this->elements[9]; - - inv.elements[2] = this->elements[1] * this->elements[6] * this->elements[15] - - this->elements[1] * this->elements[7] * this->elements[14] - - this->elements[5] * this->elements[2] * this->elements[15] + - this->elements[5] * this->elements[3] * this->elements[14] + - this->elements[13] * this->elements[2] * this->elements[7] - - this->elements[13] * this->elements[3] * this->elements[6]; - - inv.elements[6] = -this->elements[0] * this->elements[6] * this->elements[15] + - this->elements[0] * this->elements[7] * this->elements[14] + - this->elements[4] * this->elements[2] * this->elements[15] - - this->elements[4] * this->elements[3] * this->elements[14] - - this->elements[12] * this->elements[2] * this->elements[7] + - this->elements[12] * this->elements[3] * this->elements[6]; - - inv.elements[10] = this->elements[0] * this->elements[5] * this->elements[15] - - this->elements[0] * this->elements[7] * this->elements[13] - - this->elements[4] * this->elements[1] * this->elements[15] + - this->elements[4] * this->elements[3] * this->elements[13] + - this->elements[12] * this->elements[1] * this->elements[7] - - this->elements[12] * this->elements[3] * this->elements[5]; - - inv.elements[14] = -this->elements[0] * this->elements[5] * this->elements[14] + - this->elements[0] * this->elements[6] * this->elements[13] + - this->elements[4] * this->elements[1] * this->elements[14] - - this->elements[4] * this->elements[2] * this->elements[13] - - this->elements[12] * this->elements[1] * this->elements[6] + - this->elements[12] * this->elements[2] * this->elements[5]; - - inv.elements[3] = -this->elements[1] * this->elements[6] * this->elements[11] + - this->elements[1] * this->elements[7] * this->elements[10] + - this->elements[5] * this->elements[2] * this->elements[11] - - this->elements[5] * this->elements[3] * this->elements[10] - - this->elements[9] * this->elements[2] * this->elements[7] + - this->elements[9] * this->elements[3] * this->elements[6]; - - inv.elements[7] = this->elements[0] * this->elements[6] * this->elements[11] - - this->elements[0] * this->elements[7] * this->elements[10] - - this->elements[4] * this->elements[2] * this->elements[11] + - this->elements[4] * this->elements[3] * this->elements[10] + - this->elements[8] * this->elements[2] * this->elements[7] - - this->elements[8] * this->elements[3] * this->elements[6]; - - inv.elements[11] = -this->elements[0] * this->elements[5] * this->elements[11] + - this->elements[0] * this->elements[7] * this->elements[9] + - this->elements[4] * this->elements[1] * this->elements[11] - - this->elements[4] * this->elements[3] * this->elements[9] - - this->elements[8] * this->elements[1] * this->elements[7] + - this->elements[8] * this->elements[3] * this->elements[5]; - - inv.elements[15] = this->elements[0] * this->elements[5] * this->elements[10] - - this->elements[0] * this->elements[6] * this->elements[9] - - this->elements[4] * this->elements[1] * this->elements[10] + - this->elements[4] * this->elements[2] * this->elements[9] + - this->elements[8] * this->elements[1] * this->elements[6] - - this->elements[8] * this->elements[2] * this->elements[5]; - - float det = this->elements[0] * inv.elements[0] + this->elements[1] * inv.elements[4] + - this->elements[2] * inv.elements[8] + this->elements[3] * inv.elements[12]; - - float invdet = 1.0f / det; - - for (int i = 0; i < 16; i++) - inv.elements[i] *= invdet; - - return inv; -} - -Matrix4 Matrix4::Ortho(float left, float right, float bottom, - float top, float near, float far) -{ - Matrix4 matrix; - - matrix.elements[0] = 2.0f / (right - left); - matrix.elements[5] = 2.0f / (top - bottom); - matrix.elements[10] = -2.0f / (far - near); - - matrix.elements[12] = -(right + left) / (right - left); - matrix.elements[13] = -(top + bottom) / (top - bottom); - matrix.elements[14] = -(far + near) / (far - near); - - return matrix; -} diff --git a/platform/cafe/source/modules/graphics_ext.cpp b/platform/cafe/source/modules/graphics_ext.cpp index 99e0a5a14..d8da4ecb7 100644 --- a/platform/cafe/source/modules/graphics_ext.cpp +++ b/platform/cafe/source/modules/graphics_ext.cpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include @@ -75,13 +75,13 @@ Texture* Graphics::NewTexture(const Texture<>::Set return new Texture(this, settings, slices); } -void Graphics::Draw(Drawable* drawable, const Matrix4& matrix) +void Graphics::Draw(Drawable* drawable, const Matrix4& matrix) { drawable->Draw(*this, matrix); } void Graphics::Draw(Texture* texture, Quad* quad, - const Matrix4& matrix) + const Matrix4& matrix) { texture->Draw(*this, quad, matrix); } diff --git a/platform/cafe/source/objects/texture_ext.cpp b/platform/cafe/source/objects/texture_ext.cpp index 6adf6c90d..f1f756723 100644 --- a/platform/cafe/source/objects/texture_ext.cpp +++ b/platform/cafe/source/objects/texture_ext.cpp @@ -303,14 +303,13 @@ void Texture::ReplacePixels(const void* data, size_t size, int sl GX2Invalidate(Texture::INVALIDATE_MODE, this->texture->surface.image, imageSize); } -void Texture::Draw(Graphics& graphics, - const Matrix4& matrix) +void Texture::Draw(Graphics& graphics, const Matrix4& matrix) { this->Draw(graphics, this->quad, matrix); } void Texture::Draw(Graphics& graphics, Quad* quad, - const Matrix4& matrix) + const Matrix4& matrix) { if (!this->readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); @@ -321,7 +320,7 @@ void Texture::Draw(Graphics& graphics, Quad* quad, const auto& stateTransform = graphics.GetTransform(); bool is2D = stateTransform.IsAffine2DTransform(); - Matrix4 transform(stateTransform, matrix); + Matrix4 transform(stateTransform, matrix); love::DrawCommand command(4); command.shader = Shader<>::STANDARD_TEXTURE; @@ -330,7 +329,8 @@ void Texture::Draw(Graphics& graphics, Quad* quad, command.handles = { this }; if (is2D) - transform.TransformXY(command.Positions().get(), quad->GetVertexPositions(), command.count); + transform.TransformXY(std::span(command.Positions().get(), command.count), + std::span(quad->GetVertexPositions(), command.count)); const auto* textureCoords = quad->GetVertexTextureCoords(); command.FillVertices(graphics.GetColor(), textureCoords); diff --git a/platform/ctr/CMakeLists.txt b/platform/ctr/CMakeLists.txt index ec5aa83bf..af2afe150 100644 --- a/platform/ctr/CMakeLists.txt +++ b/platform/ctr/CMakeLists.txt @@ -37,7 +37,6 @@ dkp_install_assets(${PROJECT_NAME}_ctr_romfs # find source -type f | grep "\.cpp$" | clip target_sources(${PROJECT_NAME} PRIVATE - source/common/matrix_ext.cpp source/common/screen_ext.cpp source/modules/fontmodule_ext.cpp source/modules/graphics_ext.cpp diff --git a/platform/ctr/include/common/matrix_ext.hpp b/platform/ctr/include/common/matrix_ext.hpp deleted file mode 100644 index 570011c76..000000000 --- a/platform/ctr/include/common/matrix_ext.hpp +++ /dev/null @@ -1,181 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include - -namespace love -{ - template<> - class Matrix4 : public Matrix4 - { - public: - Matrix4(); - - Matrix4(const C3D_Mtx& matrix); - - Matrix4(const Matrix4& a, const Matrix4& b); - - Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, - float ky); - - Matrix4(float t00, float t10, float t01, float t11, float x, float y); - - const C3D_Mtx& GetElements() const - { - return this->matrix; - } - - void SetIdentity(); - - void Transpose() - { - Mtx_Transpose(&this->matrix); - } - - void SetTranslation(float x, float y); - - void Translate(float x, float y); - - void Rotate(float r); - - void Scale(float sx, float sy); - - void Shear(float kx, float ky); - - bool IsAffine2DTransform() const; - - bool IsAffine3DTransform() const; - - Matrix4 Inverse() const; - - void SetRawTransformation(float t00, float t10, float t01, float t11, float x, float y); - - void SetTransformation(float x, float y, float angle, float sx, float sy, float ox, - float oy, float kx, float ky); - - void Translation(float x, float y); - - void SetRotation(float r); - - void SetScale(float x, float y); - - void SetShear(float kx, float ky); - - void GetApproximateScale(float& sx, float& sy) const; - - Matrix4 operator*(const Matrix4& m) const; - - void operator*=(const Matrix4& m); - - static Matrix4 Ortho(float left, float right, float bottom, float top, float near, - float far); - - static void Multiply(const Matrix4& a, const Matrix4& b, Matrix4& result); - - float Get(const unsigned row, const unsigned column) const - { - return this->matrix.m[row * 4 + (3 - column)]; - } - - void Set(const unsigned row, const unsigned column, const float value) - { - this->matrix.m[row * 4 + (3 - column)] = value; - } - - void TransformXY(const C3D_Mtx& elements); - - void TransformXY(); - - /** - * Transforms an array of 2-component vertices by this Matrix. The source - * and destination arrays may be the same. - **/ - template - void TransformXY(Vdst* dst, const Vsrc* src, int size) const; - - template - void TransformXYVert(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->matrix.r[0].x * src[i].position[0]) + - (this->matrix.r[0].y * src[i].position[1]) + (0) + (this->matrix.r[0].w); - - float y = (this->matrix.r[1].x * src[i].position[0]) + - (this->matrix.r[1].y * src[i].position[1]) + (0) + (this->matrix.r[1].w); - - dst[i].x = x; - dst[i].y = y; - } - } - - template - void TransformXYVertPure(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->matrix.r[0].x * src[i].position[0]) + - (this->matrix.r[0].y * src[i].position[1]) + (0) + (this->matrix.r[0].w); - - float y = (this->matrix.r[1].x * src[i].position[0]) + - (this->matrix.r[1].y * src[i].position[1]) + (0) + (this->matrix.r[1].w); - - dst[i].position[0] = x; - dst[i].position[1] = y; - } - } - /** - * Transforms an array of 2-component vertices by this Matrix, and stores - * them in an array of 3-component vertices. - **/ - template - void TransformXY0(Vdst* dst, const Vsrc* src, int size) const; - - void TransformXY(Vector2* dst, const vertex::Vertex* src, int size) const; - - private: - static void Multiply(const Matrix4& a, const Matrix4& b, C3D_Mtx& c); - - C3D_Mtx matrix; - }; - - template - void Matrix4::TransformXY(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - - // clang-format off - float x = (this->matrix.r[0].x * src[i].x) + (this->matrix.r[0].y * src[i].y) + (0) + (this->matrix.r[0].w); - float y = (this->matrix.r[1].x * src[i].x) + (this->matrix.r[1].y * src[i].y) + (0) + (this->matrix.r[1].w); - // clang-format on - - dst[i].x = x; - dst[i].y = y; - } - } - - inline void Matrix4::TransformXY(Vector2* dst, const vertex::Vertex* src, - int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - - // clang-format off - float x = (this->matrix.r[0].x * src[i].position[0]) + (this->matrix.r[0].y * src[i].position[1]) + (0) + (this->matrix.r[0].w); - float y = (this->matrix.r[1].x * src[i].position[0]) + (this->matrix.r[1].y * src[i].position[1]) + (0) + (this->matrix.r[1].w); - //clang-format on - - dst[i].x = x; - dst[i].y = y; - } - } -} // namespace love diff --git a/platform/ctr/include/modules/graphics_ext.hpp b/platform/ctr/include/modules/graphics_ext.hpp index d38c5a8b1..6dfe4596b 100644 --- a/platform/ctr/include/modules/graphics_ext.hpp +++ b/platform/ctr/include/modules/graphics_ext.hpp @@ -20,9 +20,9 @@ namespace love Texture* NewTexture(const Texture<>::Settings& settings, const Texture<>::Slices* slices = nullptr) const; - void Draw(Texture* texture, Quad* quad, const Matrix4& matrix); + void Draw(Texture* texture, Quad* quad, const Matrix4& matrix); - void Draw(Drawable* drawable, const Matrix4& matrix); + void Draw(Drawable* drawable, const Matrix4& matrix); void SetShader(); diff --git a/platform/ctr/include/objects/joystick_ext.hpp b/platform/ctr/include/objects/joystick_ext.hpp index 292d841f0..25c1009f4 100644 --- a/platform/ctr/include/objects/joystick_ext.hpp +++ b/platform/ctr/include/objects/joystick_ext.hpp @@ -88,7 +88,11 @@ namespace love return false; } - void GetVibration(float& left, float& right) {}; + void GetVibration(float& left, float& right) + { + left = 0; + right = 0; + }; bool HasSensor(Sensor::SensorType type) const; diff --git a/platform/ctr/include/objects/texture_ext.hpp b/platform/ctr/include/objects/texture_ext.hpp index 35d93b31c..5f192f982 100644 --- a/platform/ctr/include/objects/texture_ext.hpp +++ b/platform/ctr/include/objects/texture_ext.hpp @@ -14,10 +14,10 @@ namespace love virtual ~Texture(); virtual void Draw(Graphics& graphics, - const Matrix4& matrix) override; + const Matrix4& matrix) override; virtual void Draw(Graphics& graphics, Quad* quad, - const Matrix4& transform) override; + const Matrix4& transform) override; void ReplacePixels(ImageData* data, int slice, int mipmap, int x, int y, bool reloadMipmaps); diff --git a/platform/ctr/include/utilities/driver/renderer_ext.hpp b/platform/ctr/include/utilities/driver/renderer_ext.hpp index 6b58d5681..0bcaf5f3e 100644 --- a/platform/ctr/include/utilities/driver/renderer_ext.hpp +++ b/platform/ctr/include/utilities/driver/renderer_ext.hpp @@ -29,6 +29,7 @@ namespace love static inline constexpr int MAX_OBJECTS = 0x1000; static inline constexpr int VERTEX_BUFFER_SIZE = 6 * MAX_OBJECTS; + static inline constexpr auto TOTAL_BUFFER_SIZE = VERTEX_BUFFER_SIZE * VERTEX_SIZE; static inline constexpr uint8_t MAX_RENDERTARGETS = 0x03; @@ -119,7 +120,7 @@ namespace love } // clang-format off - static constexpr BidirectionalMap primitiveModes = + static constexpr BidirectionalMap primitiveModes = { vertex::PRIMITIVE_TRIANGLES, GPU_TRIANGLES, vertex::PRIMITIVE_TRIANGLE_STRIP, GPU_TRIANGLE_STRIP, diff --git a/platform/ctr/source/common/matrix_ext.cpp b/platform/ctr/source/common/matrix_ext.cpp deleted file mode 100644 index c6f734daf..000000000 --- a/platform/ctr/source/common/matrix_ext.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include - -#include - -using namespace love; - -void Matrix4::Multiply(const Matrix4& a, const Matrix4& b, C3D_Mtx& c) -{ - Mtx_Multiply(&c, &a.matrix, &b.matrix); -} - -void Matrix4::Multiply(const Matrix4& a, const Matrix4& b, Matrix4& c) -{ - Multiply(a, b, c.matrix); -} - -Matrix4::Matrix4() -{ - this->SetIdentity(); -} - -Matrix4::Matrix4(const C3D_Mtx& a) -{ - Mtx_Copy(&this->matrix, &a); -} - -/* credit to @mtheall */ -static bool fuzzy(float const a_, float const b_) -{ - float const EPSILON = 0.00001f; - return fabs(a_ - b_) < EPSILON; -} - -bool Matrix4::IsAffine2DTransform() const -{ - // z-vector must remain unchanged - if (this->matrix.r[0].z != 0.0f || this->matrix.r[1].z != 0.0f || this->matrix.r[2].x != 0.0f || - this->matrix.r[2].y != 0.0f || this->matrix.r[2].z != 1.0f || this->matrix.r[2].w != 0.0f) - return false; - - // last row must be {0, 0, 0, 1} - if (this->matrix.r[3].x != 0.0f || this->matrix.r[3].y != 0.0f || this->matrix.r[3].z != 0.0f || - this->matrix.r[3].w != 1.0f) - return false; - - float const a = this->matrix.r[0].x; - float const b = this->matrix.r[0].y; - float const c = this->matrix.r[1].x; - float const d = this->matrix.r[1].y; - - // M * transpose(M) must be identity matrix, where M is upper-left 2x2 matrix - if (!fuzzy(a * a + b * b, 1.0f) || !fuzzy(c * c + d * d, 1.0f) || !fuzzy(a * c + b * d, 0.0f)) - return false; - - return true; -} - -bool Matrix4::IsAffine3DTransform() const -{ - // last row must be {0, 0, 0, 1} - if (this->matrix.r[3].x != 0.0f || this->matrix.r[3].y != 0.0f || this->matrix.r[3].z != 0.0f || - this->matrix.r[3].w != 1.0f) - return false; - - float const a = this->matrix.r[0].x; - float const b = this->matrix.r[0].y; - float const c = this->matrix.r[0].z; - float const d = this->matrix.r[1].x; - float const e = this->matrix.r[1].y; - float const f = this->matrix.r[1].z; - float const g = this->matrix.r[2].x; - float const h = this->matrix.r[2].y; - float const i = this->matrix.r[2].z; - - // M * transpose(M) must be identity matrix, where M is upper-left 3x3 matrix - if (!fuzzy(a * a + b * b + c * c, 1.0f) || !fuzzy(d * d + e * e + f * f, 1.0f) || - !fuzzy(g * g + h * h + i * i, 1.0f) || !fuzzy(a * d + b * e + c * f, 0.0f) || - !fuzzy(a * g + b * h + c * i, 0.0f) || !fuzzy(d * g + e * h + g * i, 0.0f)) - return false; - - return true; -} -/* ----------------- */ - -Matrix4::Matrix4(const Matrix4& a, const Matrix4& b) -{ - Matrix4::Multiply(a, b, this->matrix); -} - -Matrix4::Matrix4(float x, float y, float angle, float sx, float sy, float ox, - float oy, float kx, float ky) -{ - this->SetTransformation(x, y, angle, sx, sy, ox, oy, ky, ky); -} - -void Matrix4::operator*=(const Matrix4& m) -{ - Matrix4::Multiply(*this, m, this->matrix); -} - -Matrix4 Matrix4::operator*(const Matrix4& m) const -{ - return Matrix4(*this, m); -} - -void Matrix4::SetIdentity() -{ - Mtx_Identity(&this->matrix); -} - -void Matrix4::SetRawTransformation(float t00, float t10, float t01, float t11, - float x, float y) -{ - Mtx_Zeros(&this->matrix); - - this->matrix.r[2].z = this->matrix.r[3].w = 1.0f; - - this->matrix.r[0].x = t00; - this->matrix.r[1].x = t10; - - this->matrix.r[0].y = t01; - this->matrix.r[1].y = t11; - - this->matrix.r[0].w = x; - this->matrix.r[1].w = y; -} - -void Matrix4::SetTransformation(float x, float y, float angle, float sx, float sy, - float ox, float oy, float kx, float ky) -{ - Mtx_Zeros(&this->matrix); - - /* - ** Note that the offsets are applied before rotation, scaling, or shearing; - ** scaling and shearing are applied before rotation. - */ - float c = cosf(angle), s = sinf(angle); - - this->matrix.r[2].z = this->matrix.r[3].w = 1.0f; - - this->matrix.r[0].x = c * sx - ky * s * sy; // = a - this->matrix.r[1].x = s * sx + ky * c * sy; // = b - - this->matrix.r[0].y = kx * c * sx - s * sy; // = c - this->matrix.r[1].y = kx * s * sx + c * sy; // = d - - this->matrix.r[0].w = x - ox * this->matrix.r[0].x - oy * this->matrix.r[0].y; // = c - this->matrix.r[1].w = y - ox * this->matrix.r[1].x - oy * this->matrix.r[1].y; // = d -} - -void Matrix4::Translate(float x, float y) -{ - Mtx_Translate(&this->matrix, x, y, 0.0f, true); -} - -void Matrix4::Rotate(float r) -{ - Mtx_RotateZ(&this->matrix, r, true); -} - -void Matrix4::Scale(float sx, float sy) -{ - Mtx_Scale(&this->matrix, sx, sy, 1.0f); -} - -void Matrix4::GetApproximateScale(float& sx, float& sy) const -{ - // clang-format off - sx = sqrtf(this->matrix.r[0].x * this->matrix.r[0].x + this->matrix.r[0].y * this->matrix.r[0].y); - sy = sqrtf(this->matrix.r[1].x * this->matrix.r[1].x + this->matrix.r[1].y * this->matrix.r[1].y); - // clang-format on -} - -void Matrix4::Shear(float kx, float ky) -{ - C3D_Mtx mtx; - Mtx_Identity(&mtx); - - mtx.r[0].y = kx; - mtx.r[1].x = ky; - - Mtx_Multiply(&this->matrix, &this->matrix, &mtx); -} - -void Matrix4::TransformXY() -{ - auto instance = Renderer::Instance(); - Mtx_Copy(&instance.GetModelView(), &this->matrix); -} - -void Matrix4::TransformXY(const C3D_Mtx& elements) -{ - auto instance = Renderer::Instance(); - Mtx_Copy(&instance.GetModelView(), &elements); -} - -Matrix4 Matrix4::Inverse() const -{ - Matrix4 inv; - Mtx_Copy(&inv.matrix, &this->matrix); - - Mtx_Inverse(&inv.matrix); - - return inv; -} - -Matrix4 Matrix4::Ortho(float left, float right, float bottom, float top, - float near, float far) -{ - Matrix4 ortho; - Mtx_Ortho(&ortho.matrix, left, right, bottom, top, near, far, true); - - return ortho; -} diff --git a/platform/ctr/source/modules/graphics_ext.cpp b/platform/ctr/source/modules/graphics_ext.cpp index f85a5dad5..768b3dd0f 100644 --- a/platform/ctr/source/modules/graphics_ext.cpp +++ b/platform/ctr/source/modules/graphics_ext.cpp @@ -40,13 +40,13 @@ void Graphics::SetShader(Shader* shader) this->states.back().shader.Set(shader); } -void Graphics::Draw(Drawable* drawable, const Matrix4& matrix) +void Graphics::Draw(Drawable* drawable, const Matrix4& matrix) { drawable->Draw(*this, matrix); } void Graphics::Draw(Texture* texture, Quad* quad, - const Matrix4& matrix) + const Matrix4& matrix) { texture->Draw(*this, quad, matrix); } diff --git a/platform/ctr/source/modules/love_ext.cpp b/platform/ctr/source/modules/love_ext.cpp index c5d8180e0..fa1d5b60d 100644 --- a/platform/ctr/source/modules/love_ext.cpp +++ b/platform/ctr/source/modules/love_ext.cpp @@ -9,13 +9,13 @@ using namespace love; static constexpr int SOC_BUFFER_SIZE = 0x100000; static constexpr int SOC_BUFFER_ALIGN = 0x1000; -// static inline uint32_t* socBuffer = nullptr; +static inline uint32_t* socBuffer = nullptr; template<> void love::PreInit() { - // socBuffer = (uint32_t*)aligned_alloc(SOC_BUFFER_ALIGN, SOC_BUFFER_SIZE); - // socInit(socBuffer, SOC_BUFFER_SIZE); + socBuffer = (uint32_t*)aligned_alloc(SOC_BUFFER_ALIGN, SOC_BUFFER_SIZE); + socInit(socBuffer, SOC_BUFFER_SIZE); } template<> @@ -27,6 +27,8 @@ bool love::MainLoop(lua_State* L, int numArgs) template<> void love::OnExit() { - // socExit(); - // free(socBuffer); + socExit(); + + if (socBuffer) + free(socBuffer); } diff --git a/platform/ctr/source/objects/texture_ext.cpp b/platform/ctr/source/objects/texture_ext.cpp index b53f089c2..0ed46aeab 100644 --- a/platform/ctr/source/objects/texture_ext.cpp +++ b/platform/ctr/source/objects/texture_ext.cpp @@ -271,7 +271,7 @@ void Texture::ReplacePixels(const void* data, size_t size, int sli } void Texture::Draw(Graphics& graphics, - const Matrix4& matrix) + const Matrix4& matrix) { this->Draw(graphics, this->quad, matrix); } @@ -315,7 +315,7 @@ static void refreshQuad(StrongReference quad, const Quad::Viewport& viewpo } void Texture::Draw(Graphics& graphics, Quad* quad, - const Matrix4& matrix) + const Matrix4& matrix) { if (!this->readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); @@ -333,15 +333,14 @@ void Texture::Draw(Graphics& graphics, Quad* quad, const auto& transform = graphics.GetTransform(); bool is2D = transform.IsAffine2DTransform(); - Matrix4 translated(graphics.GetTransform(), matrix); + Matrix4 translated(graphics.GetTransform(), matrix); DrawCommand command(0x04, vertex::PRIMITIVE_TRIANGLE_FAN); command.handles = { this->texture }; command.format = CommonFormat::TEXTURE; if (is2D) - translated.TransformXY(command.Positions().get(), quad->GetVertexPositions(), - command.count); + translated.TransformXY(std::span(command.Positions().get(), command.count), std::span(quad->GetVertexPositions(), command.count)); const auto* coords = quad->GetVertexTextureCoords(); command.FillVertices(graphics.GetColor(), coords); diff --git a/platform/ctr/source/objects/truetyperasterizer_ext.cpp b/platform/ctr/source/objects/truetyperasterizer_ext.cpp index fbc6d7ba2..d1511fa61 100644 --- a/platform/ctr/source/objects/truetyperasterizer_ext.cpp +++ b/platform/ctr/source/objects/truetyperasterizer_ext.cpp @@ -68,7 +68,7 @@ bool TrueTypeRasterizer::HasGlyph(uint32_t glyph) const int index = fontGlyphIndexFromCodePoint(this->face, glyph); const auto* info = fontGetInfo(this->face); - return index != info->alterCharIndex; + return index != info->alterCharIndex && glyph != '\t'; } template<> @@ -147,4 +147,4 @@ template<> bool TrueTypeRasterizer::Accepts(FT_Library, Data* data) { return (!std::memcmp(data->GetData(), "CFNT", 4) || !std::memcmp(data->GetData(), "CFNU", 4)); -} \ No newline at end of file +} diff --git a/platform/ctr/source/utilities/driver/renderer/renderer_ext.cpp b/platform/ctr/source/utilities/driver/renderer/renderer_ext.cpp index 387065323..6a2338ca9 100644 --- a/platform/ctr/source/utilities/driver/renderer/renderer_ext.cpp +++ b/platform/ctr/source/utilities/driver/renderer/renderer_ext.cpp @@ -30,7 +30,7 @@ Renderer::Renderer() : targets {}, currentTexture(nullptr) AttrInfo_AddLoader(attributes, 2, GPU_FLOAT, 2); // texcoord BufInfo_Init(&this->bufferInfo); - m_vertices = (Vertex*)linearAlloc(VERTEX_BUFFER_SIZE * VERTEX_SIZE); + m_vertices = (Vertex*)linearAlloc(TOTAL_BUFFER_SIZE); if (!m_vertices) throw love::Exception("Out of memory."); @@ -130,9 +130,6 @@ void Renderer::FlushVertices() { for (const auto& command : m_commands) { - if (command.count + m_vertexOffset > MAX_OBJECTS) - m_vertexOffset = 0; - std::memcpy(m_vertices + m_vertexOffset, command.Vertices().get(), command.size); if (m_format != command.format) @@ -166,6 +163,12 @@ bool Renderer::Render(DrawCommand& command) C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uniforms.uLocMdlView, &this->context.modelView); } + if ((command.count + m_vertexOffset) * VERTEX_SIZE > TOTAL_BUFFER_SIZE) + { + FlushVertices(); + m_vertexOffset = 0; + } + // check if texture is the same, or no texture at all if (command.handles.empty() || (command.handles.size() > 0 && this->currentTexture == command.handles.back())) diff --git a/platform/hac/CMakeLists.txt b/platform/hac/CMakeLists.txt index 9feac8fe8..55a24fd21 100644 --- a/platform/hac/CMakeLists.txt +++ b/platform/hac/CMakeLists.txt @@ -11,9 +11,9 @@ nx_add_shader_program(video_fsh "shaders/video_fsh.glsl" "frag") dkp_install_assets (${PROJECT_NAME}_hac_romfs DESTINATION "shaders" TARGETS - transform_vsh - color_fsh - texture_fsh + transform_vsh + color_fsh + texture_fsh video_fsh ) @@ -30,7 +30,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE # find source -type f | grep "\.cpp$" | clip target_sources(${PROJECT_NAME} PRIVATE - source/common/matrix_ext.cpp source/common/screen_ext.cpp source/modules/fontmodule_ext.cpp source/modules/graphics_ext.cpp diff --git a/platform/hac/include/common/matrix_ext.hpp b/platform/hac/include/common/matrix_ext.hpp index 172cd5538..70a10d044 100644 --- a/platform/hac/include/common/matrix_ext.hpp +++ b/platform/hac/include/common/matrix_ext.hpp @@ -7,149 +7,6 @@ namespace love template<> class Matrix4 : public Matrix4 { - public: - Matrix4(); - - Matrix4(const float elements[16]); - - Matrix4(const Matrix4& a, const Matrix4& b); - - Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, - float ky); - - Matrix4(float t00, float t10, float t01, float t11, float x, float y); - - void SetIdentity(); - - void Transpose() - {} - - void SetTranslation(float x, float y); - - void Translate(float x, float y); - - void Rotate(float r); - - void Scale(float sx, float sy); - - void Shear(float kx, float ky); - - bool IsAffine2DTransform() const; - - bool IsAffine3DTransform() const; - - Matrix4 Inverse() const; - - void SetRawTransformation(float t00, float t10, float t01, float t11, float x, float y); - - void SetTransformation(float x, float y, float angle, float sx, float sy, float ox, - float oy, float kx, float ky); - - void Translation(float x, float y); - - void SetRotation(float r); - - void SetScale(float x, float y); - - void SetShear(float kx, float ky); - - void GetApproximateScale(float& sx, float& sy) const; - - Matrix4 operator*(const Matrix4& m) const; - - void operator*=(const Matrix4& m); - - static Matrix4 Ortho(float left, float right, float bottom, float top, float near, - float far); - - static void Multiply(const Matrix4& a, const Matrix4& b, Matrix4& result); - - float Get(const unsigned row, const unsigned column) const - { - return this->elements[column * 4 + row]; - } - - void Set(const unsigned row, const unsigned column, const float value) - { - this->elements[column * 4 + row] = value; - } - - void TransformXY(float elements[16]); - - void TransformXY(); - - /** - * Transforms an array of 2-component vertices by this Matrix. The source - * and destination arrays may be the same. - **/ - template - void TransformXY(Vdst* dst, const Vsrc* src, int size) const; - - template - void TransformXYVert(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->elements[0] * src[i].position[0]) + - (this->elements[4] * src[i].position[1]) + (0) + (this->elements[12]); - - float y = (this->elements[1] * src[i].position[0]) + - (this->elements[5] * src[i].position[1]) + (0) + (this->elements[13]); - - dst[i].x = x; - dst[i].y = y; - } - } - - template - void TransformXYVertPure(Vdst* dst, const Vsrc* src, int size) const; - - /** - * Transforms an array of 2-component vertices by this Matrix, and stores - * them in an array of 3-component vertices. - **/ - template - void TransformXY0(Vdst* dst, const Vsrc* src, int size) const; - - private: - static void Multiply(const Matrix4& a, const Matrix4& b, float elements[16]); - - float elements[16]; - }; - - /* use with Vector2 */ - template - void Matrix4::TransformXY(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->elements[0] * src[i].x) + (this->elements[4] * src[i].y) + (0) + - (this->elements[12]); - float y = (this->elements[1] * src[i].x) + (this->elements[5] * src[i].y) + (0) + - (this->elements[13]); - - dst[i].x = x; - dst[i].y = y; - } - } - - /* use with Vertex */ - template - void Matrix4::TransformXYVertPure(Vdst* dst, const Vsrc* src, int size) const - { - for (int i = 0; i < size; i++) - { - // Store in temp variables in case src = dst - float x = (this->elements[0] * src[i].position[0]) + - (this->elements[4] * src[i].position[1]) + (0) + (this->elements[12]); - - float y = (this->elements[1] * src[i].position[0]) + - (this->elements[5] * src[i].position[1]) + (0) + (this->elements[13]); - - dst[i].position[0] = x; - dst[i].position[1] = y; - } + using Matrix4::Matrix4; } } // namespace love diff --git a/platform/hac/include/modules/graphics_ext.hpp b/platform/hac/include/modules/graphics_ext.hpp index 2896faa37..253241b82 100644 --- a/platform/hac/include/modules/graphics_ext.hpp +++ b/platform/hac/include/modules/graphics_ext.hpp @@ -21,9 +21,9 @@ namespace love Texture* NewTexture(const Texture<>::Settings& settings, const Texture<>::Slices* slices = nullptr) const; - void Draw(Texture* texture, Quad* quad, const Matrix4& matrix); + void Draw(Texture* texture, Quad* quad, const Matrix4& matrix); - void Draw(Drawable* drawable, const Matrix4& matrix); + void Draw(Drawable* drawable, const Matrix4& matrix); void SetViewportSize(int width, int height); }; // namespace love diff --git a/platform/hac/include/objects/texture_ext.hpp b/platform/hac/include/objects/texture_ext.hpp index 868dfbaa5..6deeaee47 100644 --- a/platform/hac/include/objects/texture_ext.hpp +++ b/platform/hac/include/objects/texture_ext.hpp @@ -16,10 +16,10 @@ namespace love virtual ~Texture(); virtual void Draw(Graphics& graphics, - const Matrix4& matrix) override; + const Matrix4& matrix) override; virtual void Draw(Graphics& graphics, Quad* quad, - const Matrix4& transform) override; + const Matrix4& transform) override; void ReplacePixels(ImageDataBase* data, int slice, int mipmap, int x, int y, bool reloadMipmaps); diff --git a/platform/hac/include/utilities/driver/renderer_ext.hpp b/platform/hac/include/utilities/driver/renderer_ext.hpp index 7a5390f45..9cac26398 100644 --- a/platform/hac/include/utilities/driver/renderer_ext.hpp +++ b/platform/hac/include/utilities/driver/renderer_ext.hpp @@ -88,6 +88,13 @@ namespace love return instance; } + void ClearCanvas(Texture* texture) + { + this->BindFramebuffer(texture); + this->Clear(Color::TRANSPARENT); + this->BindFramebuffer(); + } + virtual ~Renderer(); Info GetRendererInfo(); diff --git a/platform/hac/source/common/matrix_ext.cpp b/platform/hac/source/common/matrix_ext.cpp deleted file mode 100644 index 6c4293f53..000000000 --- a/platform/hac/source/common/matrix_ext.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include - -#include -#include - -using namespace love; - -void Matrix4::Multiply(const Matrix4& a, const Matrix4& b, float elements[16]) -{ - float32x4_t cola1 = vld1q_f32(&a.elements[0]); - float32x4_t cola2 = vld1q_f32(&a.elements[4]); - float32x4_t cola3 = vld1q_f32(&a.elements[8]); - float32x4_t cola4 = vld1q_f32(&a.elements[12]); - - float32x4_t col1 = vmulq_n_f32(cola1, b.elements[0]); - col1 = vmlaq_n_f32(col1, cola2, b.elements[1]); - col1 = vmlaq_n_f32(col1, cola3, b.elements[2]); - col1 = vmlaq_n_f32(col1, cola4, b.elements[3]); - - float32x4_t col2 = vmulq_n_f32(cola1, b.elements[4]); - col2 = vmlaq_n_f32(col2, cola2, b.elements[5]); - col2 = vmlaq_n_f32(col2, cola3, b.elements[6]); - col2 = vmlaq_n_f32(col2, cola4, b.elements[7]); - - float32x4_t col3 = vmulq_n_f32(cola1, b.elements[8]); - col3 = vmlaq_n_f32(col3, cola2, b.elements[9]); - col3 = vmlaq_n_f32(col3, cola3, b.elements[10]); - col3 = vmlaq_n_f32(col3, cola4, b.elements[11]); - - float32x4_t col4 = vmulq_n_f32(cola1, b.elements[12]); - col4 = vmlaq_n_f32(col4, cola2, b.elements[13]); - col4 = vmlaq_n_f32(col4, cola3, b.elements[14]); - col4 = vmlaq_n_f32(col4, cola4, b.elements[15]); - - vst1q_f32(&elements[0], col1); - vst1q_f32(&elements[4], col2); - vst1q_f32(&elements[8], col3); - vst1q_f32(&elements[12], col4); -} - -void Matrix4::Multiply(const Matrix4& a, const Matrix4& b, Matrix4& t) -{ - Matrix4::Multiply(a, b, t.elements); -} - -Matrix4::Matrix4() -{ - this->SetIdentity(); -} - -Matrix4::Matrix4(const float elements[16]) -{ - memcpy(this->elements, elements, sizeof(float) * 16); -} - -Matrix4::Matrix4(const Matrix4& a, const Matrix4& b) -{ - Matrix4::Multiply(a, b, this->elements); -} - -Matrix4::Matrix4(float t00, float t10, float t01, float t11, float x, float y) -{ - this->SetRawTransformation(t00, t10, t01, t11, x, y); -} - -Matrix4::Matrix4(float x, float y, float angle, float sx, float sy, float ox, - float oy, float kx, float ky) -{ - this->SetTransformation(x, y, angle, sx, sy, ox, oy, kx, ky); -} - -bool Matrix4::IsAffine2DTransform() const -{ - return fabsf(this->elements[2] + this->elements[3] + this->elements[6] + this->elements[7] + - this->elements[8] + this->elements[9] + this->elements[11] + this->elements[14]) < - 0.00001f && - fabsf(this->elements[10] + this->elements[15] - 2.0f) < 0.00001f; -} - -Matrix4 Matrix4::operator*(const Matrix4& m) const -{ - return Matrix4(*this, m); -} - -void Matrix4::operator*=(const Matrix4& m) -{ - float elements[16]; - - Matrix4::Multiply(*this, m, elements); - memcpy(this->elements, elements, sizeof(float) * 16); -} - -void Matrix4::SetIdentity() -{ - memset(this->elements, 0, sizeof(float) * 16); - this->elements[15] = this->elements[10] = this->elements[5] = this->elements[0] = 1.0f; -} - -void Matrix4::SetTranslation(float x, float y) -{ - this->SetIdentity(); - - this->elements[12] = x; - this->elements[13] = y; -} - -void Matrix4::Translate(float x, float y) -{ - Matrix4 t; - t.SetTranslation(x, y); - this->operator*=(t); -} - -void Matrix4::SetRotation(float rad) -{ - this->SetIdentity(); - float c = cosf(rad), s = sinf(rad); - - this->elements[0] = c; - this->elements[4] = -s; - this->elements[1] = s; - this->elements[5] = c; -} - -void Matrix4::Rotate(float rad) -{ - Matrix4 t; - t.SetRotation(rad); - this->operator*=(t); -} - -void Matrix4::SetScale(float sx, float sy) -{ - this->SetIdentity(); - - this->elements[0] = sx; - this->elements[5] = sy; -} - -void Matrix4::Scale(float sx, float sy) -{ - Matrix4 t; - t.SetScale(sx, sy); - this->operator*=(t); -} - -void Matrix4::SetShear(float kx, float ky) -{ - this->SetIdentity(); - - this->elements[1] = ky; - this->elements[4] = kx; -} - -void Matrix4::Shear(float kx, float ky) -{ - Matrix4 t; - t.SetShear(kx, ky); - this->operator*=(t); -} - -void Matrix4::GetApproximateScale(float& sx, float& sy) const -{ - sx = sqrtf(this->elements[0] * this->elements[0] + this->elements[4] * this->elements[4]); - sy = sqrtf(this->elements[1] * this->elements[1] + this->elements[5] * this->elements[5]); -} - -void Matrix4::SetRawTransformation(float t00, float t10, float t01, float t11, - float x, float y) -{ - memset(this->elements, 0, sizeof(float) * 16); // zero out matrix - - this->elements[10] = this->elements[15] = 1.0f; - this->elements[0] = t00; - this->elements[1] = t10; - this->elements[4] = t01; - this->elements[5] = t11; - this->elements[12] = x; - this->elements[13] = y; -} - -void Matrix4::SetTransformation(float x, float y, float angle, float sx, float sy, - float ox, float oy, float kx, float ky) -{ - memset(this->elements, 0, sizeof(float) * 16); // zero out matrix - float c = cosf(angle), s = sinf(angle); - - this->elements[10] = this->elements[15] = 1.0f; - this->elements[0] = c * sx - ky * s * sy; // = a - this->elements[1] = s * sx + ky * c * sy; // = b - this->elements[4] = kx * c * sx - s * sy; // = c - this->elements[5] = kx * s * sx + c * sy; // = d - this->elements[12] = x - ox * this->elements[0] - oy * this->elements[4]; - this->elements[13] = y - ox * this->elements[1] - oy * this->elements[5]; -} - -Matrix4 Matrix4::Inverse() const -{ - Matrix4 inv; - - inv.elements[0] = this->elements[5] * this->elements[10] * this->elements[15] - - this->elements[5] * this->elements[11] * this->elements[14] - - this->elements[9] * this->elements[6] * this->elements[15] + - this->elements[9] * this->elements[7] * this->elements[14] + - this->elements[13] * this->elements[6] * this->elements[11] - - this->elements[13] * this->elements[7] * this->elements[10]; - - inv.elements[4] = -this->elements[4] * this->elements[10] * this->elements[15] + - this->elements[4] * this->elements[11] * this->elements[14] + - this->elements[8] * this->elements[6] * this->elements[15] - - this->elements[8] * this->elements[7] * this->elements[14] - - this->elements[12] * this->elements[6] * this->elements[11] + - this->elements[12] * this->elements[7] * this->elements[10]; - - inv.elements[8] = this->elements[4] * this->elements[9] * this->elements[15] - - this->elements[4] * this->elements[11] * this->elements[13] - - this->elements[8] * this->elements[5] * this->elements[15] + - this->elements[8] * this->elements[7] * this->elements[13] + - this->elements[12] * this->elements[5] * this->elements[11] - - this->elements[12] * this->elements[7] * this->elements[9]; - - inv.elements[12] = -this->elements[4] * this->elements[9] * this->elements[14] + - this->elements[4] * this->elements[10] * this->elements[13] + - this->elements[8] * this->elements[5] * this->elements[14] - - this->elements[8] * this->elements[6] * this->elements[13] - - this->elements[12] * this->elements[5] * this->elements[10] + - this->elements[12] * this->elements[6] * this->elements[9]; - - inv.elements[1] = -this->elements[1] * this->elements[10] * this->elements[15] + - this->elements[1] * this->elements[11] * this->elements[14] + - this->elements[9] * this->elements[2] * this->elements[15] - - this->elements[9] * this->elements[3] * this->elements[14] - - this->elements[13] * this->elements[2] * this->elements[11] + - this->elements[13] * this->elements[3] * this->elements[10]; - - inv.elements[5] = this->elements[0] * this->elements[10] * this->elements[15] - - this->elements[0] * this->elements[11] * this->elements[14] - - this->elements[8] * this->elements[2] * this->elements[15] + - this->elements[8] * this->elements[3] * this->elements[14] + - this->elements[12] * this->elements[2] * this->elements[11] - - this->elements[12] * this->elements[3] * this->elements[10]; - - inv.elements[9] = -this->elements[0] * this->elements[9] * this->elements[15] + - this->elements[0] * this->elements[11] * this->elements[13] + - this->elements[8] * this->elements[1] * this->elements[15] - - this->elements[8] * this->elements[3] * this->elements[13] - - this->elements[12] * this->elements[1] * this->elements[11] + - this->elements[12] * this->elements[3] * this->elements[9]; - - inv.elements[13] = this->elements[0] * this->elements[9] * this->elements[14] - - this->elements[0] * this->elements[10] * this->elements[13] - - this->elements[8] * this->elements[1] * this->elements[14] + - this->elements[8] * this->elements[2] * this->elements[13] + - this->elements[12] * this->elements[1] * this->elements[10] - - this->elements[12] * this->elements[2] * this->elements[9]; - - inv.elements[2] = this->elements[1] * this->elements[6] * this->elements[15] - - this->elements[1] * this->elements[7] * this->elements[14] - - this->elements[5] * this->elements[2] * this->elements[15] + - this->elements[5] * this->elements[3] * this->elements[14] + - this->elements[13] * this->elements[2] * this->elements[7] - - this->elements[13] * this->elements[3] * this->elements[6]; - - inv.elements[6] = -this->elements[0] * this->elements[6] * this->elements[15] + - this->elements[0] * this->elements[7] * this->elements[14] + - this->elements[4] * this->elements[2] * this->elements[15] - - this->elements[4] * this->elements[3] * this->elements[14] - - this->elements[12] * this->elements[2] * this->elements[7] + - this->elements[12] * this->elements[3] * this->elements[6]; - - inv.elements[10] = this->elements[0] * this->elements[5] * this->elements[15] - - this->elements[0] * this->elements[7] * this->elements[13] - - this->elements[4] * this->elements[1] * this->elements[15] + - this->elements[4] * this->elements[3] * this->elements[13] + - this->elements[12] * this->elements[1] * this->elements[7] - - this->elements[12] * this->elements[3] * this->elements[5]; - - inv.elements[14] = -this->elements[0] * this->elements[5] * this->elements[14] + - this->elements[0] * this->elements[6] * this->elements[13] + - this->elements[4] * this->elements[1] * this->elements[14] - - this->elements[4] * this->elements[2] * this->elements[13] - - this->elements[12] * this->elements[1] * this->elements[6] + - this->elements[12] * this->elements[2] * this->elements[5]; - - inv.elements[3] = -this->elements[1] * this->elements[6] * this->elements[11] + - this->elements[1] * this->elements[7] * this->elements[10] + - this->elements[5] * this->elements[2] * this->elements[11] - - this->elements[5] * this->elements[3] * this->elements[10] - - this->elements[9] * this->elements[2] * this->elements[7] + - this->elements[9] * this->elements[3] * this->elements[6]; - - inv.elements[7] = this->elements[0] * this->elements[6] * this->elements[11] - - this->elements[0] * this->elements[7] * this->elements[10] - - this->elements[4] * this->elements[2] * this->elements[11] + - this->elements[4] * this->elements[3] * this->elements[10] + - this->elements[8] * this->elements[2] * this->elements[7] - - this->elements[8] * this->elements[3] * this->elements[6]; - - inv.elements[11] = -this->elements[0] * this->elements[5] * this->elements[11] + - this->elements[0] * this->elements[7] * this->elements[9] + - this->elements[4] * this->elements[1] * this->elements[11] - - this->elements[4] * this->elements[3] * this->elements[9] - - this->elements[8] * this->elements[1] * this->elements[7] + - this->elements[8] * this->elements[3] * this->elements[5]; - - inv.elements[15] = this->elements[0] * this->elements[5] * this->elements[10] - - this->elements[0] * this->elements[6] * this->elements[9] - - this->elements[4] * this->elements[1] * this->elements[10] + - this->elements[4] * this->elements[2] * this->elements[9] + - this->elements[8] * this->elements[1] * this->elements[6] - - this->elements[8] * this->elements[2] * this->elements[5]; - - float det = this->elements[0] * inv.elements[0] + this->elements[1] * inv.elements[4] + - this->elements[2] * inv.elements[8] + this->elements[3] * inv.elements[12]; - - float invdet = 1.0f / det; - - for (int i = 0; i < 16; i++) - inv.elements[i] *= invdet; - - return inv; -} - -Matrix4 Matrix4::Ortho(float left, float right, float bottom, float top, - float near, float far) -{ - Matrix4 matrix; - - matrix.elements[0] = 2.0f / (right - left); - matrix.elements[5] = 2.0f / (top - bottom); - matrix.elements[10] = -2.0f / (far - near); - - matrix.elements[12] = -(right + left) / (right - left); - matrix.elements[13] = -(top + bottom) / (top - bottom); - matrix.elements[14] = -(far + near) / (far - near); - - return matrix; -} diff --git a/platform/hac/source/modules/graphics_ext.cpp b/platform/hac/source/modules/graphics_ext.cpp index f5b3e41bc..faca3a137 100644 --- a/platform/hac/source/modules/graphics_ext.cpp +++ b/platform/hac/source/modules/graphics_ext.cpp @@ -100,13 +100,13 @@ Texture* Graphics::NewTexture(const Texture<>::Setti return new Texture(this, settings, slices); } -void Graphics::Draw(Drawable* drawable, const Matrix4& matrix) +void Graphics::Draw(Drawable* drawable, const Matrix4& matrix) { drawable->Draw(*this, matrix); } void Graphics::Draw(Texture* texture, Quad* quad, - const Matrix4& matrix) + const Matrix4& matrix) { texture->Draw(*this, quad, matrix); } diff --git a/platform/hac/source/objects/texture_ext.cpp b/platform/hac/source/objects/texture_ext.cpp index b6b717ca5..d8579c413 100644 --- a/platform/hac/source/objects/texture_ext.cpp +++ b/platform/hac/source/objects/texture_ext.cpp @@ -220,13 +220,8 @@ void Texture::CreateTexture() { bool clear = !hasData; - auto& instance = Renderer::Instance(); - createFramebufferObject(this->image, this->memory, this->descriptor, _width, _height); - - instance.BindFramebuffer(this); - instance.Clear({ 0, 0, 0, 0 }); - instance.BindFramebuffer(nullptr); + Renderer::Instance().ClearCanvas(this); } else { @@ -385,14 +380,13 @@ void Texture::ReplacePixels(const void* data, size_t size, int sli tempImageMemory.destroy(); } -void Texture::Draw(Graphics& graphics, - const Matrix4& matrix) +void Texture::Draw(Graphics& graphics, const Matrix4& matrix) { this->Draw(graphics, this->quad, matrix); } void Texture::Draw(Graphics& graphics, Quad* quad, - const Matrix4& matrix) + const Matrix4& matrix) { if (!this->readable) throw love::Exception("Textures with non-readable formats cannot be drawn."); @@ -403,7 +397,7 @@ void Texture::Draw(Graphics& graphics, Quad* quad, const auto& stateTransform = graphics.GetTransform(); bool is2D = stateTransform.IsAffine2DTransform(); - Matrix4 transform(stateTransform, matrix); + Matrix4 transform(stateTransform, matrix); DrawCommand command(4); command.shader = Shader<>::STANDARD_TEXTURE; @@ -412,7 +406,10 @@ void Texture::Draw(Graphics& graphics, Quad* quad, command.handles = { this }; if (is2D) - transform.TransformXY(command.Positions().get(), quad->GetVertexPositions(), command.count); + { + transform.TransformXY(std::span(command.Positions().get(), command.count), + std::span(quad->GetVertexPositions(), command.count)); + } const auto* textureCoords = quad->GetVertexTextureCoords(); command.FillVertices(graphics.GetColor(), textureCoords); diff --git a/source/modules/graphics/wrap_graphics.cpp b/source/modules/graphics/wrap_graphics.cpp index c2bd50606..6157bd932 100644 --- a/source/modules/graphics/wrap_graphics.cpp +++ b/source/modules/graphics/wrap_graphics.cpp @@ -19,6 +19,8 @@ #include +#include + using Renderer = love::Renderer; using namespace love; @@ -78,10 +80,10 @@ int Wrap_Graphics::Clear(lua_State* L) OptionalColor newColor {}; - newColor.value().r = luaL_checknumber(L, 1); - newColor.value().g = luaL_checknumber(L, 2); - newColor.value().b = luaL_checknumber(L, 3); - newColor.value().a = luaL_optnumber(L, 4, 1.0); + newColor.value.r = luaL_checknumber(L, 1); + newColor.value.g = luaL_checknumber(L, 2); + newColor.value.b = luaL_checknumber(L, 3); + newColor.value.a = luaL_optnumber(L, 4, 1.0); colors.push_back(newColor); @@ -92,10 +94,10 @@ int Wrap_Graphics::Clear(lua_State* L) start = 2; else if (argtype != LUA_TNONE && argtype != LUA_TNIL) { - color.value().r = luaL_checknumber(L, 1); - color.value().g = luaL_checknumber(L, 2); - color.value().b = luaL_checknumber(L, 3); - color.value().a = luaL_optnumber(L, 4, 1.0); + color.value.r = luaL_checknumber(L, 1); + color.value.g = luaL_checknumber(L, 2); + color.value.b = luaL_checknumber(L, 3); + color.value.a = luaL_optnumber(L, 4, 1.0); start = 5; } @@ -108,7 +110,7 @@ int Wrap_Graphics::Clear(lua_State* L) { } else if (argtype == LUA_TNUMBER) - stencil.value() = luaL_checkinteger(L, start); + stencil.value = luaL_checkinteger(L, start); argtype = lua_type(L, start + 1); @@ -116,7 +118,7 @@ int Wrap_Graphics::Clear(lua_State* L) { } else if (argtype == LUA_TNUMBER) - depth.value() = luaL_checknumber(L, start + 1); + depth.value = luaL_checknumber(L, start + 1); } if (colors.empty()) @@ -448,13 +450,13 @@ int Wrap_Graphics::Print(lua_State* L) { auto* font = Wrap_Font::CheckFont(L, 2); - Wrap_Graphics::CheckStandardTransform(L, 3, [&](const Matrix4& matrix) { + Wrap_Graphics::CheckStandardTransform(L, 3, [&](const Matrix4& matrix) { luax::CatchException(L, [&]() { instance()->Print(strings, font, matrix); }); }); } else { - Wrap_Graphics::CheckStandardTransform(L, 2, [&](const Matrix4& matrix) { + Wrap_Graphics::CheckStandardTransform(L, 2, [&](const Matrix4& matrix) { luax::CatchException(L, [&]() { instance()->Print(strings, matrix); }); }); } @@ -476,7 +478,7 @@ int Wrap_Graphics::Printf(lua_State* L) start++; } - Matrix4 matrix; + Matrix4 matrix; int formatIndex = start + 2; @@ -497,7 +499,7 @@ int Wrap_Graphics::Printf(lua_State* L) float kx = luaL_optnumber(L, start + 9, 0.0); float ky = luaL_optnumber(L, start + 10, 0.0); - matrix = Matrix4(x, y, a, sx, sy, ox, oy, kx, ky); + matrix = Matrix4(x, y, a, sx, sy, ox, oy, kx, ky); } float wrap = luaL_checknumber(L, formatIndex); @@ -516,33 +518,36 @@ int Wrap_Graphics::Printf(lua_State* L) return 0; } +static std::optional getTextureKey(Texture<>::SettingType type) +{ + return Texture<>::settingsTypes.ReverseFind(type); +} + static void checkTextureSettings(lua_State* L, int index, bool option, bool checkType, - bool checkDimensions, std::optional forceRenderTarget, + bool checkDimensions, OptionalBool forceRenderTarget, Texture<>::Settings& settings, bool& setDpiScale) { setDpiScale = false; - if (forceRenderTarget.has_value()) - settings.renderTarget = forceRenderTarget.value(); + if (forceRenderTarget.hasValue) + settings.renderTarget = forceRenderTarget.value; if (option && lua_isnoneornil(L, index)) return; luax::CheckTableFields::SettingType>( L, index, "texture setting name", [](const char* v) { - std::optional<::Texture<>::SettingType> value; + std::optional::SettingType> value; return (Texture<>::settingsTypes.Find(v) != std::nullopt); }); - if (!forceRenderTarget.has_value()) + if (!forceRenderTarget.hasValue) { - bool defaultValue = settings.renderTarget; - const char* key = *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_RENDER_TARGET); - - settings.renderTarget = luax::BoolFlag(L, index, key, defaultValue); + const auto key = getTextureKey(Texture<>::SETTING_RENDER_TARGET); + settings.renderTarget = luax::BoolFlag(L, index, *key, settings.renderTarget); } - lua_getfield(L, index, *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_FORMAT)); + lua_getfield(L, index, *getTextureKey(Texture<>::SETTING_FORMAT)); if (!lua_isnoneornil(L, -1)) { const char* string = luaL_checkstring(L, -1); @@ -550,12 +555,14 @@ static void checkTextureSettings(lua_State* L, int index, bool option, bool chec if (!(format = pixelFormats.Find(string))) luax::EnumError(L, "pixel format", string); + + settings.format = *format; } lua_pop(L, 1); if (checkType) { - lua_getfield(L, index, *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_TYPE)); + lua_getfield(L, index, *getTextureKey(Texture<>::SETTING_TYPE)); if (!lua_isnoneornil(L, -1)) { const char* string = luaL_checkstring(L, -1); @@ -563,14 +570,16 @@ static void checkTextureSettings(lua_State* L, int index, bool option, bool chec if (!(type = Texture<>::textureTypes.Find(string))) luax::EnumError(L, "texture type", string); + + settings.type = *type; } lua_pop(L, 1); } if (checkDimensions) { - const char* keyWidth = *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_WIDTH); - const char* keyHeight = *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_HEIGHT); + const char* keyWidth = *getTextureKey(Texture<>::SETTING_WIDTH); + const char* keyHeight = *getTextureKey(Texture<>::SETTING_HEIGHT); settings.width = luax::CheckIntFlag(L, index, keyWidth); settings.height = luax::CheckIntFlag(L, index, keyHeight); @@ -578,14 +587,12 @@ static void checkTextureSettings(lua_State* L, int index, bool option, bool chec if (settings.type == Texture<>::TEXTURE_2D_ARRAY || settings.type == Texture<>::TEXTURE_VOLUME) { - const char* keyLayers = - *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_LAYERS); - - settings.layers = luax::CheckIntFlag(L, index, keyLayers); + const char* keyLayers = *getTextureKey(Texture<>::SETTING_LAYERS); + settings.layers = luax::CheckIntFlag(L, index, keyLayers); } } - lua_getfield(L, index, *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_MIPMAPS)); + lua_getfield(L, index, *getTextureKey(Texture<>::SETTING_MIPMAPS)); if (!lua_isnoneornil(L, -1)) { if (lua_type(L, -1) == LUA_TBOOLEAN) @@ -600,32 +607,33 @@ static void checkTextureSettings(lua_State* L, int index, bool option, bool chec if (!(mode = Texture<>::mipmapModes.Find(string))) luax::EnumError(L, "Texture mipmap mode", Texture<>::mipmapModes, string); + + settings.mipmaps = *mode; } } lua_pop(L, 1); - lua_getfield(L, index, *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_MIPMAP_COUNT)); + lua_getfield(L, index, *getTextureKey(Texture<>::SETTING_MIPMAP_COUNT)); if (!lua_isnoneornil(L, -1)) settings.mipmapCount = luaL_checkinteger(L, -1); lua_pop(L, 1); - const char* keyLinear = *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_LINEAR); - const char* keyMSAA = *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_MSAA); + const char* keyLinear = *getTextureKey(Texture<>::SETTING_LINEAR); + const char* keyMSAA = *getTextureKey(Texture<>::SETTING_MSAA); settings.linear = luax::BoolFlag(L, index, keyLinear, settings.linear); settings.msaa = luax::IntFlag(L, index, keyMSAA, settings.msaa); - const char* keyComputeWrite = - *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_COMPUTE_WRITE); + const char* keyComputeWrite = *getTextureKey(Texture<>::SETTING_COMPUTE_WRITE); settings.computeWrite = luax::BoolFlag(L, index, keyComputeWrite, settings.computeWrite); - lua_getfield(L, index, *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_READABLE)); + lua_getfield(L, index, *getTextureKey(Texture<>::SETTING_READABLE)); if (!lua_isnoneornil(L, -1)) settings.readable = luax::CheckBoolean(L, -1); lua_pop(L, 1); - lua_getfield(L, index, *Texture<>::settingsTypes.ReverseFind(Texture<>::SETTING_DPI_SCALE)); + lua_getfield(L, index, *getTextureKey(Texture<>::SETTING_DPI_SCALE)); if (lua_isnumber(L, -1)) { settings.dpiScale = lua_tonumber(L, -1); @@ -733,7 +741,7 @@ int Wrap_Graphics::Draw(lua_State* L) } // clang-format off - Wrap_Graphics::CheckStandardTransform(L, start, [&](const Matrix4& matrix) { + Wrap_Graphics::CheckStandardTransform(L, start, [&](const Matrix4& matrix) { luax::CatchException(L, [&](){ if (texture && quad) instance()->Draw(texture, quad, matrix); @@ -819,7 +827,7 @@ int Wrap_Graphics::NewCanvas(lua_State* L) checkGraphicsCreated(L); Texture<>::Settings settings {}; - std::optional forceRenderTarget(true); + OptionalBool forceRenderTarget(true); bool setDPIScale = false; if (lua_istable(L, 1)) @@ -1430,7 +1438,7 @@ int Wrap_Graphics::Shear(lua_State* L) int Wrap_Graphics::ApplyTransform(lua_State* L) { - Wrap_Graphics::CheckStandardTransform(L, 1, [&](const Matrix4& matrix) { + Wrap_Graphics::CheckStandardTransform(L, 1, [&](const Matrix4& matrix) { luax::CatchException(L, [&]() { instance()->ApplyTransform(matrix); }); }); @@ -1439,7 +1447,7 @@ int Wrap_Graphics::ApplyTransform(lua_State* L) int Wrap_Graphics::ReplaceTransform(lua_State* L) { - Wrap_Graphics::CheckStandardTransform(L, 1, [&](const Matrix4& matrix) { + Wrap_Graphics::CheckStandardTransform(L, 1, [&](const Matrix4& matrix) { luax::CatchException(L, [&]() { instance()->ReplaceTransform(matrix); }); }); @@ -1781,7 +1789,9 @@ int Wrap_Graphics::SetColorMask(lua_State* L) { RenderState::ColorMask 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) mask.r = mask.g = mask.b = mask.a = luax::CheckBoolean(L, 1); else { diff --git a/source/modules/love/love.cpp b/source/modules/love/love.cpp index 60b7c1eac..7996af260 100644 --- a/source/modules/love/love.cpp +++ b/source/modules/love/love.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include @@ -32,6 +31,8 @@ static constexpr char nestlink_lua[] = { #include "scripts/nestlink.lua" }; +#include + #include #include #include @@ -85,9 +86,34 @@ static constexpr luaL_Reg modules[] = // clang-format on #include +#include + +static void addCompatibilityAlias(lua_State* L, const char* module, const char* name, + const char* alias) +{ + lua_getglobal(L, module); + + if (lua_istable(L, -1)) + { + lua_getfield(L, -1, alias); + bool hasAlias = !lua_isnoneornil(L, -1); + lua_pop(L, 1); + + if (!hasAlias) + { + lua_getfield(L, -1, name); + lua_setfield(L, -2, alias); + } + } + + lua_pop(L, 1); +} int love::Initialize(lua_State* L) { + for (size_t i = 0; modules[i].name != nullptr; i++) + luax::Preload(L, modules[i].func, modules[i].name); + luax::InsistPinnedThread(L); luax::InsistGlobal(L, "love"); @@ -130,23 +156,49 @@ int love::Initialize(lua_State* L) lua_pushnumber(L, LOVE_POTION.micro); lua_setfield(L, -2, "_potion_version_revision"); - lua_pushcfunction(L, GetVersion); + lua_newtable(L); + for (int index = 0; love::COMPATIBILITY[index] != nullptr; index++) + { + lua_pushstring(L, love::COMPATIBILITY[index]); + lua_rawseti(L, -2, index + 1); + } + lua_setfield(L, -2, "_version_compat"); + + lua_pushcfunction(L, love::GetVersion); lua_setfield(L, -2, "getVersion"); - lua_pushcfunction(L, IsVersionCompatible); + lua_pushcfunction(L, love::IsVersionCompatible); lua_setfield(L, -2, "isVersionCompatible"); - for (size_t i = 0; modules[i].name != nullptr; i++) - luax::Preload(L, modules[i].func, modules[i].name); + lua_pushstring(L, System::GetOS()); + lua_setfield(L, -2, "_os"); + + lua_pushstring(L, __CONSOLE__); + lua_setfield(L, -2, "_console"); luax::Require(L, "love.data"); lua_pop(L, 1); +#if LUA_VERSION_NUM <= 501 + addCompatibilityAlias(L, "math", "fmod", "mod"); + addCompatibilityAlias(L, "string", "gmatch", "gfind"); +#endif + love::luasocket::preload(L); luax::Preload(L, luaopen_luautf8, "utf8"); luax::Preload(L, luaopen_https, "https"); + { + lua_atpanic(L, [](lua_State* L) -> int { + auto location = std::source_location::current(); + const auto* message = "PANIC: unprotected error in call to Lua API (%s)\n"; + Log::Instance(true).Write(location, message, lua_tostring(L, -1)); + + return 0; + }); + } + return 1; } @@ -160,6 +212,13 @@ int love::GetVersion(lua_State* L) return 4; } +int love::SetGammaCorrect(lua_State* L) +{ + love::Graphics<>::SetGammaCorrect((bool)lua_toboolean(L, 1)); + + return 0; +} + int love::IsVersionCompatible(lua_State* L) { Version check {}; diff --git a/source/modules/love/scripts/arg.lua b/source/modules/love/scripts/arg.lua index 86a1e82d4..342f28cad 100644 --- a/source/modules/love/scripts/arg.lua +++ b/source/modules/love/scripts/arg.lua @@ -131,6 +131,7 @@ function love.arg.parseOption(m, i) end end + table.insert(m.arg, "game") return m.a end @@ -159,11 +160,7 @@ function love.arg.parseOptions() end if not love.arg.options.game.set then - if game then - love.arg.parseOption(love.arg.options.game, game or 0) - else - love.arg.options.game = { a = 1, set = true, arg = { "game" } } - end + love.arg.parseOption(love.arg.options.game, game or 0) end end diff --git a/source/modules/love/scripts/boot.lua b/source/modules/love/scripts/boot.lua index 066655158..089f3d9f8 100644 --- a/source/modules/love/scripts/boot.lua +++ b/source/modules/love/scripts/boot.lua @@ -31,9 +31,13 @@ require("love.arg") require("love.callbacks") local is_debug, log = pcall(require, "love.log") -local file = nil +local function TRACE(format, ...) end + if is_debug then - file = log.new("boot.log") + local file = log.new("boot.log") + TRACE = function(format, ...) + file:trace(format, ...) + end end local function uridecode(s) @@ -42,6 +46,15 @@ local function uridecode(s) end) end +local function https_setup_certs() + local https = require("https") + + if love._os == "Cafe" then + return https.setCertificateFile("/sdcard/config/ssl/cacert.pem") + end + https.setCertificateFile("sdmc/config/ssl/cacert.pem") +end + local no_game_code = false local invalid_game_path = nil local main_file = "main.lua" @@ -145,6 +158,8 @@ function love.boot() no_game_code = true end + https_setup_certs() + if not can_has_game then invalid_game_path = false local nogame = require("love.nogame") @@ -428,11 +443,7 @@ local print, debug, tostring = print, debug, tostring local function error_printer(msg, layer) local trace = debug.traceback("Error: " .. tostring(msg), 1 + (layer or 1)):gsub("\n[^\n]+$", "") - print(trace) - - if file then - file:echo(trace) - end + TRACE(trace) end ----------------------------------------------------------- diff --git a/source/modules/love/scripts/callbacks.lua b/source/modules/love/scripts/callbacks.lua index 0f9aee47d..ee4334953 100644 --- a/source/modules/love/scripts/callbacks.lua +++ b/source/modules/love/scripts/callbacks.lua @@ -23,10 +23,15 @@ freely, subject to the following restrictions: --]] local love = require("love") + local is_debug, log = pcall(require, "love.log") -local file = nil +local function TRACE(format, ...) end + if is_debug then - file = log.new("callbacks.log") + local file = log.new("callbacks.log") + TRACE = function(format, ...) + file:trace(format, ...) + end end function love.createhandlers() @@ -302,18 +307,14 @@ local utf8 = require("utf8") local function error_printer(msg, layer) local trace = debug.traceback("Error: " .. tostring(msg), 1 + (layer or 1)):gsub("\n[^\n]+$", "") - print(trace) - - if file then - file:echo(trace) - end + TRACE(trace) end function love.errhand(msg) msg = tostring(msg) error_printer(msg, 2) - + if not love.window or not love.graphics or not love.event then return end diff --git a/source/modules/love/scripts/logfile.lua b/source/modules/love/scripts/logfile.lua index 6569d7a7f..542b48a75 100644 --- a/source/modules/love/scripts/logfile.lua +++ b/source/modules/love/scripts/logfile.lua @@ -1,9 +1,15 @@ R"luastring"--( +-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string. +-- There is a matching delimiter at the bottom of the file. + +-- Based on the code from https://github.com/rxi/log.lua +-- LICENSE: https://github.com/rxi/log.lua/blob/master/LICENSE + -- make sure love exists. local love = require("love") require("love.arg") -local debug = debug.getinfo +local getinfo = debug.getinfo -- to get the working directory require("love.filesystem") @@ -11,7 +17,18 @@ require("love.filesystem") local log = {} log.__index = log -log.format = "%s:%d:\n%s\n\n" +log.format = "[%-6s%s] %s:\n%s\n" +log.level = "trace" + +local modes = +{ + trace = 0, + debug = 1, + info = 2, + warn = 3, + error = 4, + fatal = 5 +} function log.new(filename) local instance = setmetatable({}, log) @@ -22,18 +39,32 @@ function log.new(filename) return instance end -function log:echo(format, ...) - if not self.file then - return - end +for level, _ in pairs(modes) do + log[level] = function(self, ...) + if not self.file then + return + end + + if modes[self.level] < modes[level] then + return + end - local caller_name = debug(2).short_src - local line_number = debug(2).currentline + local message = tostring(...) + local info = getinfo(2, "Sl") - local buffer = string.format(format, ...) - self.file:write(string.format(log.format, caller_name, line_number, buffer)) + local line = ("%s:%d"):format(info.short_src, info.currentline) + local buffer = log.format:format(level:upper(), os.date(), line, message) + + self.file:write(buffer) + self.file:flush() + end end -return log +return setmetatable(log, { + __call = function(_, ...) + return log.new(...) + end +}) + -- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string. --)luastring"--" diff --git a/source/objects/font/font.cpp b/source/objects/font/font.cpp index 5c8607223..a073eb7f1 100644 --- a/source/objects/font/font.cpp +++ b/source/objects/font/font.cpp @@ -20,8 +20,7 @@ Font::Font(Rasterizer* rasterizer, const SamplerState& state) : textureCacheID(0), shaper(rasterizer->NewTextShaper(), Acquire::NORETAIN), samplerState {}, - dpiScale(1.0f), - useSpacesAsTab(false) + dpiScale(rasterizer->GetDPIScale()) { this->samplerState.minFilter = state.minFilter; this->samplerState.magFilter = state.magFilter; @@ -354,6 +353,7 @@ const Font::Glyph& Font::AddGlyph(TextShaper::GlyphIndex glyphIndex) _glyph.sheet = sheetInfo.index; _glyph.texture = &this->textures[_glyph.sheet]; + _glyph.spacing = data->GetAdvance(); left = sheetInfo.left; top = sheetInfo.top; @@ -364,7 +364,7 @@ const Font::Glyph& Font::AddGlyph(TextShaper::GlyphIndex glyphIndex) if (width > 0 && height > 0) { - const auto color = Color(1, 1, 1, 1).array(); + const auto color = Color(Color::WHITE).array(); // clang-format off const std::array vertices = @@ -422,7 +422,7 @@ float Font::GetKerning(const std::string& left, const std::string& right) return this->shaper->GetKerning(left, right); } -static bool shouldAddCommand(const Font::DrawCommand& command, const Font::Glyph& glyph) +static bool shouldCreateCommand(const Font::DrawCommand& command, const Font::Glyph& glyph) { if (Console::Is(Console::CTR)) return command.sheet != glyph.sheet; @@ -436,8 +436,8 @@ std::vector Font::GenerateVertices(const ColoredCodepoints& c float extraSpacing, Vector2 offset, TextShaper::TextInfo* info) { - std::vector positions; - std::vector colors; + std::vector positions {}; + std::vector colors {}; this->shaper->ComputeGlyphPositions(codepoints, range, offset, extraSpacing, &positions, &colors, info); @@ -467,6 +467,7 @@ std::vector Font::GenerateVertices(const ColoredCodepoints& c vertices.resize(vertexStartSize); currentColorIndex = 0; currentColor = color; + continue; } if (currentColorIndex < colorCount && colors[currentColorIndex].index == index) @@ -488,7 +489,7 @@ std::vector Font::GenerateVertices(const ColoredCodepoints& c if (glyph.texture != nullptr) { - for (int j = 0; j < glyph.vertices.size(); j++) + for (int j = 0; j < (int)glyph.vertices.size(); j++) { vertices.push_back(glyph.vertices[j]); vertices.back().position[0] += info.position.x; @@ -496,13 +497,15 @@ std::vector Font::GenerateVertices(const ColoredCodepoints& c vertices.back().color = currentColor.array(); } - if (commands.empty() || shouldAddCommand(commands.back(), glyph)) + // check if a glyph texture or sheet has changed since last iteration + if (commands.empty() || shouldCreateCommand(commands.back(), glyph)) { DrawCommand command {}; command.start = (int)vertices.size() - 6; command.count = 0; command.texture = glyph.texture; command.sheet = glyph.sheet; + commands.push_back(command); } @@ -510,7 +513,7 @@ std::vector Font::GenerateVertices(const ColoredCodepoints& c } } - const auto drawSort = [](const DrawCommand& left, const DrawCommand& right) { + const auto drawSort = [](const DrawCommand& left, const DrawCommand& right) -> bool { if (Console::Is(Console::CTR)) return left.sheet < right.sheet; else @@ -528,6 +531,15 @@ std::vector Font::GenerateVertices(const ColoredCodepoints& c return commands; } +static inline bool isSimilarCommand(const Font::DrawCommand& previous, + std::vector::iterator current) +{ + if (Console::Is(Console::CTR)) + return previous.sheet == current->sheet; + + return previous.texture == current->texture; +} + std::vector Font::GenerateVerticesFormatted( const ColoredCodepoints& codepoints, const Color& color, float wrap, AlignMode align, std::vector& vertices, TextShaper::TextInfo* info) @@ -535,7 +547,8 @@ std::vector Font::GenerateVerticesFormatted( wrap = std::max(wrap, 0.0f); uint32_t cacheId = this->textureCacheID; - std::vector commands {}; + + std::vector drawCommands {}; vertices.reserve(codepoints.cps.size() * 6); std::vector ranges {}; @@ -557,7 +570,7 @@ std::vector Font::GenerateVerticesFormatted( } float width = widths[index]; - Vector2 offset(0, std::floor(y)); + Vector2 offset(0.0f, std::floor(y)); float extraSpacing = 0.0f; maxWidth = std::max(width, maxWidth); @@ -594,24 +607,26 @@ std::vector Font::GenerateVerticesFormatted( } auto newCommands = - this->GenerateVertices(codepoints, range, color, vertices, extraSpacing, offset, info); + this->GenerateVertices(codepoints, range, color, vertices, extraSpacing, offset); if (!newCommands.empty()) { auto firstCommand = newCommands.begin(); - if (!commands.empty()) + if (!drawCommands.empty()) { - auto prevCommand = commands.back(); - if (prevCommand.texture == firstCommand->texture && - (prevCommand.start + prevCommand.count) == firstCommand->start) + auto prevCommand = drawCommands.back(); + bool isSimilar = isSimilarCommand(prevCommand, firstCommand); + + if (isSimilar && (prevCommand.start + prevCommand.count) == firstCommand->start) { - commands.back().count += firstCommand->count; + drawCommands.back().count += firstCommand->count; ++firstCommand; } } - commands.insert(commands.end(), firstCommand, newCommands.end()); + /* append new commands to the built list */ + drawCommands.insert(drawCommands.end(), firstCommand, newCommands.end()); } y += this->GetHeight() * this->GetLineHeight(); @@ -625,20 +640,20 @@ std::vector Font::GenerateVerticesFormatted( if (cacheId != this->textureCacheID) { - commands.clear(); - commands = this->GenerateVerticesFormatted(codepoints, color, wrap, align, vertices, info); + vertices.clear(); + drawCommands = this->GenerateVerticesFormatted(codepoints, color, wrap, align, vertices); } - return commands; + return drawCommands; } -void Font::Printv(Graphics<>& graphics, const Matrix4& transform, +void Font::Printv(Graphics<>& graphics, const Matrix4& transform, const std::vector& commands, const std::vector& vertices) { if (vertices.empty() || commands.empty()) return; - Matrix4 matrix(graphics.GetTransform(), transform); + Matrix4 matrix(graphics.GetTransform(), transform); for (const auto& command : commands) { @@ -653,19 +668,19 @@ void Font::Printv(Graphics<>& graphics, const Matrix4& transform drawCommand.handles = { command.texture }; - matrix.TransformXYVert(drawCommand.Positions().get(), &vertices[command.start], - command.count); + matrix.TransformXY(std::span(drawCommand.Positions().get(), command.count), + std::span(&vertices[command.start], command.count)); drawCommand.FillVertices(&vertices[command.start]); Renderer::Instance().Render(drawCommand); } } -void Font::Print(Graphics<>& graphics, const ColoredStrings& text, - const Matrix4& matrix, const Color& color) +void Font::Print(Graphics<>& graphics, const ColoredStrings& text, const Matrix4& matrix, + const Color& color) { ColoredCodepoints codepoints {}; - GetCodepointsFromString(text, codepoints); + love::GetCodepointsFromString(text, codepoints); std::vector vertices {}; auto commands = this->GenerateVertices(codepoints, Range(), color, vertices); @@ -674,10 +689,10 @@ void Font::Print(Graphics<>& graphics, const ColoredStrings& text, } void Font::Printf(Graphics<>& graphics, const ColoredStrings& text, float wrap, AlignMode alignment, - const Matrix4& matrix, const Color& color) + const Matrix4& matrix, const Color& color) { ColoredCodepoints codepoints {}; - GetCodepointsFromString(text, codepoints); + love::GetCodepointsFromString(text, codepoints); std::vector vertices {}; auto commands = this->GenerateVerticesFormatted(codepoints, color, wrap, alignment, vertices); diff --git a/source/objects/font/wrap_font.cpp b/source/objects/font/wrap_font.cpp index 589bd17bd..27d8792fb 100644 --- a/source/objects/font/wrap_font.cpp +++ b/source/objects/font/wrap_font.cpp @@ -259,7 +259,7 @@ int Wrap_Font::GetWrap(lua_State* L) maxWidth = std::max(maxWidth, width); lua_pushinteger(L, maxWidth); - lua_createtable(L, lines.size(), 0); + lua_createtable(L, (int)lines.size(), 0); for (size_t index = 0; index < lines.size(); index++) { diff --git a/source/objects/mesh/mesh.cpp b/source/objects/mesh/mesh.cpp index 3070201bd..6203a0bc9 100644 --- a/source/objects/mesh/mesh.cpp +++ b/source/objects/mesh/mesh.cpp @@ -163,12 +163,12 @@ bool Mesh::GetDrawRange(int& start, int& count) const return true; } -void Mesh::Draw(Graphics& graphics, const Matrix4& matrix) +void Mesh::Draw(Graphics& graphics, const Matrix4& matrix) { this->DrawInternal(graphics, matrix, 1, nullptr, 0); } -void Mesh::DrawInternal(Graphics& graphics, const Matrix4& matrix, +void Mesh::DrawInternal(Graphics& graphics, const Matrix4& matrix, int instanceCount, std::vector* indirectArgs, int argsIndex) { if (this->vertexCount <= 0 || (instanceCount <= 0 && indirectArgs == nullptr)) @@ -179,8 +179,7 @@ void Mesh::DrawInternal(Graphics& graphics, const Matrix4mode == PRIMITIVE_TRIANGLE_FAN && this->useIndexBuffer && !this->indexBuffer.empty()) { @@ -206,8 +205,8 @@ void Mesh::DrawInternal(Graphics& graphics, const Matrix4 command(_range.getSize(), this->mode); command.FillVertices(this->buffer.data()); - transform.TransformXYPure(command.vertices.get(), &this->buffer[_range.getOffset()], - command.count); + transform.TransformXYPure(std::span(command.vertices.get(), command.count), + std::span(&this->buffer[_range.getOffset()], command.count)); if (this->texture.Get()) { @@ -238,4 +237,4 @@ void Mesh::DrawInternal(Graphics& graphics, const Matrix4 0) Renderer::Instance().Render(command); } -} \ No newline at end of file +} diff --git a/source/objects/spritebatch/spritebatch.cpp b/source/objects/spritebatch/spritebatch.cpp index f74cead85..9307efa9e 100644 --- a/source/objects/spritebatch/spritebatch.cpp +++ b/source/objects/spritebatch/spritebatch.cpp @@ -38,12 +38,12 @@ SpriteBatch::SpriteBatch(Texture* texture, int size) : SpriteBatch::~SpriteBatch() {} -int SpriteBatch::Add(const Matrix4& matrix, int index) +int SpriteBatch::Add(const Matrix4& matrix, int index) { return this->Add(this->texture->GetQuad(), matrix, index); } -int SpriteBatch::Add(Quad* quad, const Matrix4& matrix, int index) +int SpriteBatch::Add(Quad* quad, const Matrix4& matrix, int index) { /* todo: layers */ @@ -90,7 +90,7 @@ int SpriteBatch::Add(Quad* quad, const Matrix4& matrix, int inde }; // clang-format on - matrix.TransformXYVertPure(vertices, textureVertices.data(), textureVertices.size()); + matrix.TransformXY(std::span(vertices, textureVertices.size()), textureVertices); for (size_t index = 0; index < textureVertices.size(); index++) { @@ -109,12 +109,12 @@ int SpriteBatch::Add(Quad* quad, const Matrix4& matrix, int inde return index; } -int SpriteBatch::AddLayer(int layer, const Matrix4& matrix, int index) +int SpriteBatch::AddLayer(int layer, const Matrix4& matrix, int index) { return this->AddLayer(layer, this->texture->GetQuad(), matrix, index); } -int SpriteBatch::AddLayer(int layer, Quad* quad, const Matrix4& matrix, int index) +int SpriteBatch::AddLayer(int layer, Quad* quad, const Matrix4& matrix, int index) { if (index < -1 || index >= size) throw love::Exception("Invalid sprite index %d.", index); @@ -222,7 +222,7 @@ bool SpriteBatch::GetDrawRange(int& start, int& count) const return true; } -void SpriteBatch::Draw(Graphics& graphics, const Matrix4& matrix) +void SpriteBatch::Draw(Graphics& graphics, const Matrix4& matrix) { if (this->next == 0) return; @@ -254,7 +254,8 @@ void SpriteBatch::Draw(Graphics& graphics, const Matrix4texture }; #endif - transform.TransformXYPure(command.vertices.get(), &this->buffer[start], command.count); + transform.TransformXYPure(std::span(command.vertices.get(), command.count), + std::span(&this->buffer[start], command.count)); for (size_t index = 0; index < command.count; index++) { command.vertices[index].texcoord = this->buffer[start * 0x06 + index].texcoord; @@ -262,4 +263,4 @@ void SpriteBatch::Draw(Graphics& graphics, const Matrix4::Instance().Render(command); -} \ No newline at end of file +} diff --git a/source/objects/spritebatch/wrap_spritebatch.cpp b/source/objects/spritebatch/wrap_spritebatch.cpp index 455a1686e..f7bdd4cb5 100644 --- a/source/objects/spritebatch/wrap_spritebatch.cpp +++ b/source/objects/spritebatch/wrap_spritebatch.cpp @@ -23,7 +23,7 @@ static inline int addOrSet(lua_State* L, SpriteBatch* self, int start, int index else if (lua_isnil(L, start) && !lua_isnoneornil(L, start + 1)) return luax::TypeError(L, start, "Quad"); - Wrap_Graphics::CheckStandardTransform(L, start, [&](const Matrix4& matrix) { + Wrap_Graphics::CheckStandardTransform(L, start, [&](const Matrix4& matrix) { luax::CatchException(L, [&]() { if (quad) index = self->Add(quad, matrix, index); @@ -203,4 +203,4 @@ static constexpr luaL_Reg functions[] = int Wrap_SpriteBatch::Register(lua_State* L) { return luax::RegisterType(L, &SpriteBatch::type, functions); -} \ No newline at end of file +} diff --git a/source/objects/textbatch/textbatch.cpp b/source/objects/textbatch/textbatch.cpp index e93c45cbc..db5bd7987 100644 --- a/source/objects/textbatch/textbatch.cpp +++ b/source/objects/textbatch/textbatch.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -97,7 +97,7 @@ void TextBatch::AddTextData(const TextData& text) } if (text.useMatrix && !vertices.empty()) - text.matrix.TransformXYVertPure(vertices.data(), vertices.data(), (int)vertices.size()); + text.matrix.TransformXY(vertices, vertices); this->UploadVertices(vertices, vertexOffset); @@ -151,16 +151,16 @@ void TextBatch::Set(const ColoredStrings& strings, float wrap, Font::AlignMode a ColoredCodepoints codepoints {}; GetCodepointsFromString(strings, codepoints); - this->AddTextData({ codepoints, wrap, align, {}, false, false, Matrix4() }); + this->AddTextData({ codepoints, wrap, align, {}, false, false, Matrix4() }); } -int TextBatch::Add(const ColoredStrings& strings, const Matrix4& matrix) +int TextBatch::Add(const ColoredStrings& strings, const Matrix4& matrix) { return this->Addf(strings, -1.0f, Font::ALIGN_MAX_ENUM, matrix); } int TextBatch::Addf(const ColoredStrings& strings, float wrap, Font::AlignMode align, - const Matrix4& matrix) + const Matrix4& matrix) { ColoredCodepoints codepoints {}; GetCodepointsFromString(strings, codepoints); @@ -192,7 +192,7 @@ int TextBatch::GetHeight(int index) const return this->textData[index].textInfo.height; } -void TextBatch::Draw(Graphics& graphics, const Matrix4& matrix) +void TextBatch::Draw(Graphics& graphics, const Matrix4& matrix) { if (this->buffer.empty() || this->drawCommands.empty()) return; @@ -227,10 +227,10 @@ void TextBatch::Draw(Graphics& graphics, const Matrix4buffer[command.start], - command.count); + transform.TransformXY(std::span(drawCommand.Positions().get(), command.count), + std::span(&this->buffer[command.start], command.count)); drawCommand.FillVertices(&this->buffer[command.start]); Renderer::Instance().Render(drawCommand); } -} \ No newline at end of file +} diff --git a/source/objects/textbatch/wrap_textbatch.cpp b/source/objects/textbatch/wrap_textbatch.cpp index d2c101c00..f8751be8c 100644 --- a/source/objects/textbatch/wrap_textbatch.cpp +++ b/source/objects/textbatch/wrap_textbatch.cpp @@ -66,7 +66,7 @@ int Wrap_TextBatch::Add(lua_State* L) float kx = luaL_optnumber(L, 10, 0.0); float ky = luaL_optnumber(L, 11, 0.0); - Matrix4 matrix(x, y, a, sx, sy, ox, oy, kx, ky); + Matrix4 matrix(x, y, a, sx, sy, ox, oy, kx, ky); luax::CatchException(L, [&]() { index = self->Add(text, matrix); }); } @@ -110,7 +110,7 @@ int Wrap_TextBatch::Addf(lua_State* L) float kx = luaL_optnumber(L, 12, 0.0); float ky = luaL_optnumber(L, 13, 0.0); - Matrix4 matrix(x, y, a, sx, sy, ox, oy, kx, ky); + Matrix4 matrix(x, y, a, sx, sy, ox, oy, kx, ky); luax::CatchException(L, [&]() { index = self->Addf(text, wrap, *align, matrix); }); } diff --git a/source/objects/transform/transform.cpp b/source/objects/transform/transform.cpp index 2eff9ff76..bc3484574 100644 --- a/source/objects/transform/transform.cpp +++ b/source/objects/transform/transform.cpp @@ -7,10 +7,7 @@ Type Transform::type("Transform", &Object::type); Transform::Transform() : matrix(), inverseDirty(true), inverseMatrix() {} -Transform::Transform(const Matrix4& matrix) : - matrix(matrix), - inverseDirty(true), - inverseMatrix() +Transform::Transform(const Matrix4& matrix) : matrix(matrix), inverseDirty(true), inverseMatrix() {} Transform::Transform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, @@ -76,7 +73,7 @@ void Transform::SetTransformation(float x, float y, float a, float sx, float sy, Vector2 Transform::TransformPoint(Vector2 point) const { Vector2 result; - this->matrix.TransformXY(&result, &point, 1); + this->matrix.TransformXY(std::views::single(result), std::views::single(point)); return result; } @@ -84,17 +81,17 @@ Vector2 Transform::TransformPoint(Vector2 point) const Vector2 Transform::InverseTransformPoint(Vector2 point) { Vector2 result; - this->GetInverseMatrix().TransformXY(&result, &point, 1); + this->GetInverseMatrix().TransformXY(std::views::single(result), std::views::single(point)); return result; } -Matrix4& Transform::GetMatrix() +Matrix4& Transform::GetMatrix() { return this->matrix; } -void Transform::SetMatrix(const Matrix4& matrix) +void Transform::SetMatrix(const Matrix4& matrix) { this->matrix = matrix; this->inverseDirty = true; diff --git a/source/objects/transform/wrap_transform.cpp b/source/objects/transform/wrap_transform.cpp index eb39036f5..a245ccca6 100644 --- a/source/objects/transform/wrap_transform.cpp +++ b/source/objects/transform/wrap_transform.cpp @@ -137,7 +137,6 @@ int Wrap_Transform::SetTransformation(lua_State* L) return 1; } -/* todo */ int Wrap_Transform::SetMatrix(lua_State* L) { auto* self = Wrap_Transform::CheckTransform(L, 1); @@ -157,7 +156,7 @@ int Wrap_Transform::SetMatrix(lua_State* L) index++; } - auto& matrix = self->GetMatrix(); + float elements[16] { 0.0f }; if (lua_istable(L, index)) { @@ -177,7 +176,7 @@ int Wrap_Transform::SetMatrix(lua_State* L) for (int row = 0; row < 4; row++) { lua_rawgeti(L, -(row + 1), row + 1); - matrix.Set(row, column, luaL_checknumber(L, -1)); + elements[column * 4 + row] = luaL_checknumber(L, -1); } lua_pop(L, 4 + 1); @@ -192,7 +191,7 @@ int Wrap_Transform::SetMatrix(lua_State* L) for (int column = 0; column < 4; column++) { lua_rawgeti(L, -(column + 1), column + 1); - matrix.Set(row, column, luaL_checknumber(L, -1)); + elements[column * 4 + row] = luaL_checknumber(L, -1); } lua_pop(L, 4 + 1); @@ -208,7 +207,7 @@ int Wrap_Transform::SetMatrix(lua_State* L) for (int row = 0; row < 4; row++) { lua_rawgeti(L, index, column * 4 + row + 1); - matrix.Set(row, column, luaL_checknumber(L, -1)); + elements[column * 4 + row] = luaL_checknumber(L, -1); } } } @@ -219,7 +218,7 @@ int Wrap_Transform::SetMatrix(lua_State* L) for (int row = 0; row < 4; row++) { lua_rawgeti(L, index, row * 4 + column + 1); - matrix.Set(row, column, luaL_checknumber(L, -1)); + elements[column * 4 + row] = luaL_checknumber(L, -1); } } } @@ -231,25 +230,20 @@ int Wrap_Transform::SetMatrix(lua_State* L) { if (columnMajor) { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - matrix.Set(row, column, luaL_checknumber(L, column * 4 + row + index)); - } + for (int i = 0; i < 16; i++) + elements[i] = luaL_checknumber(L, index + i); } else { for (int column = 0; column < 4; column++) { for (int row = 0; row < 4; row++) - matrix.Set(row, column, luaL_checknumber(L, row * 4 + column + index)); + elements[column * 4 + row] = luaL_checknumber(L, row * 4 + column + index); } } } - if (columnMajor) - matrix.Transpose(); - + self->SetMatrix(Matrix4(elements)); lua_pushvalue(L, 1); return 1; @@ -258,12 +252,12 @@ int Wrap_Transform::SetMatrix(lua_State* L) int Wrap_Transform::GetMatrix(lua_State* L) { auto* self = Wrap_Transform::CheckTransform(L, 1); - const auto& elements = self->GetMatrix(); + const auto* elements = self->GetMatrix().GetElements(); for (int row = 0; row < 4; row++) { for (int column = 0; column < 4; column++) - lua_pushnumber(L, elements.Get(row, column)); + lua_pushnumber(L, elements[column * 4 + row]); } return 16; diff --git a/source/utilities/driver/renderer/polyline/polyline.cpp b/source/utilities/driver/renderer/polyline/polyline.cpp index 8ae6b014a..043ff4e60 100644 --- a/source/utilities/driver/renderer/polyline/polyline.cpp +++ b/source/utilities/driver/renderer/polyline/polyline.cpp @@ -48,7 +48,7 @@ void Polyline::render(const Vector2* coords, size_t count, size_t size_hint, flo Vector2 segment; if (!is_looping) // virtual starting point at second point mirrored on first point segment = coords[1] - coords[0]; - else // virtual starting point at last vertex + else // virtual starting point at last vertex segment = coords[0] - coords[count - 2]; float segmentLength = segment.getLength(); @@ -195,7 +195,8 @@ void Polyline::draw(Graphics* gfx) DrawCommand command(totalVertices, mode); if (is2D) - t.TransformXY(command.Positions().get(), verts, totalVertices); + t.TransformXY(std::span(command.Positions().get(), totalVertices), + std::span(verts, totalVertices)); Color colordata[totalVertices] {}; diff --git a/source/utilities/shaper/genericshaper.cpp b/source/utilities/shaper/genericshaper.cpp index e71b92dd5..d657abec6 100644 --- a/source/utilities/shaper/genericshaper.cpp +++ b/source/utilities/shaper/genericshaper.cpp @@ -14,7 +14,7 @@ void GenericShaper::ComputeGlyphPositions(const ColoredCodepoints& codepoints, R std::vector* positions, std::vector* colors, TextInfo* info) { - if (!range.isValid()) + if (!range.isValid() && !codepoints.cps.empty()) range = Range(0, codepoints.cps.size()); if (this->rasterizers[0]->GetDataType() == Rasterizer::DATA_TRUETYPE) @@ -61,6 +61,7 @@ void GenericShaper::ComputeGlyphPositions(const ColoredCodepoints& codepoints, R if (currentPosition.x > maxWidth) maxWidth = currentPosition.x; + /* wrap the newline, don't output a position for it */ currentPosition.y += std::floor(this->GetHeight() + this->GetLineHeight() + 0.5f); currentPosition.x = offset.x; previousGlyph = 0; @@ -88,7 +89,7 @@ void GenericShaper::ComputeGlyphPositions(const ColoredCodepoints& codepoints, R if (positions) { - Vector2 position { currentPosition.x, currentPosition.y }; + Vector2 position(currentPosition.x, currentPosition.y); positions->push_back({ position, glyphIndex }); } @@ -140,6 +141,7 @@ int GenericShaper::ComputeWordWrapIndex(const ColoredCodepoints& codepoints, Ran int advance = this->GetGlyphAdvance(glyph); float newWidth = currentWidth + this->GetKerning(previousGlyph, glyph) + advance; + /* don't count trailing spaces */ if (this->IsWhitespace(glyph)) { if (!this->IsWhitespace(previousGlyph)) @@ -150,8 +152,10 @@ int GenericShaper::ComputeWordWrapIndex(const ColoredCodepoints& codepoints, Ran if (this->IsWhitespace(previousGlyph)) firstIndexAfterSpace = index; + /* only wrap at non-space character */ if (newWidth > wrapLimit) { + /* if this is the first char, wrap the next one instead of current */ int wrapIndex = index > (int)range.first ? index : (int)range.first + 1; if (firstIndexAfterSpace != -1) @@ -176,5 +180,6 @@ int GenericShaper::ComputeWordWrapIndex(const ColoredCodepoints& codepoints, Ran if (width) *width = outWidth; + /* no wrap in the middle of the range */ return range.last + 1; -} \ No newline at end of file +} diff --git a/source/utilities/shaper/textshaper.cpp b/source/utilities/shaper/textshaper.cpp index 6c0a6eb5e..501286fa4 100644 --- a/source/utilities/shaper/textshaper.cpp +++ b/source/utilities/shaper/textshaper.cpp @@ -19,8 +19,8 @@ void love::GetCodepointsFromString(const std::string& string, std::vector& strings, IndexedColor c = { cstr.color, (int)codepoints.cps.size() }; codepoints.colors.push_back(c); - GetCodepointsFromString(cstr.str, codepoints.cps); + love::GetCodepointsFromString(cstr.str, codepoints.cps); } if (codepoints.colors.size() == 1) @@ -135,6 +135,9 @@ float TextShaper::GetBaseline() const float TextShaper::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) { + if (this->rasterizers[0]->GetDataType() == Rasterizer::DATA_BCFNT) + return 0.0f; + uint64_t packedGlyphs = ((uint64_t)leftGlyph << 32) | (uint64_t)rightGlyph; const auto iterator = this->kernings.find(packedGlyphs); @@ -146,9 +149,6 @@ float TextShaper::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) for (const auto& rasterizer : this->rasterizers) { - if (rasterizer->GetDataType() == Rasterizer::DATA_BCFNT) - return 0.0f; - if (rasterizer->HasGlyph(leftGlyph) && rasterizer->HasGlyph(rightGlyph)) { found = true; @@ -188,13 +188,14 @@ float TextShaper::GetKerning(const std::string& left, const std::string& right) return this->GetKerning(leftGlyph, rightGlyph); } -int TextShaper::GetGlyphAdvance(uint32_t glyph, GlyphIndex* index) +int TextShaper::GetGlyphAdvance(uint32_t glyph, GlyphIndex* glyphIndex) { const auto iterator = this->glyphAdvances.find(glyph); + if (iterator != this->glyphAdvances.end()) { - if (index) - *index = iterator->second.second; + if (glyphIndex) + *glyphIndex = iterator->second.second; return iterator->second.first; } @@ -209,7 +210,7 @@ int TextShaper::GetGlyphAdvance(uint32_t glyph, GlyphIndex* index) { if (this->rasterizers[index]->HasGlyph(realGlyph)) { - rasterizerIndex = index; + rasterizerIndex = (int)index; break; } } @@ -222,11 +223,11 @@ int TextShaper::GetGlyphAdvance(uint32_t glyph, GlyphIndex* index) if (glyph == '\t' && realGlyph == ' ') advance *= TextShaper::SPACES_PER_TAB; - GlyphIndex glyphIndex = { rasterizer->GetGlyphIndex(realGlyph), rasterizerIndex }; - this->glyphAdvances[glyph] = std::make_pair(advance, glyphIndex); + GlyphIndex _glyphIndex = { rasterizer->GetGlyphIndex(realGlyph), rasterizerIndex }; + this->glyphAdvances[glyph] = std::make_pair(advance, _glyphIndex); - if (index) - *index = glyphIndex; + if (glyphIndex) + *glyphIndex = _glyphIndex; return advance; } @@ -240,7 +241,8 @@ int TextShaper::GetWidth(const std::string& string) love::GetCodepointsFromString(string, codepoints.cps); TextInfo info {}; - this->ComputeGlyphPositions(codepoints, Range(), Vector2(), 0.0f, nullptr, nullptr, &info); + this->ComputeGlyphPositions(codepoints, Range(), Vector2(0.0f, 0.0f), 0.0f, nullptr, nullptr, + &info); return info.width; } @@ -261,11 +263,12 @@ void TextShaper::GetWrap(const ColoredCodepoints& codepoints, float wrapLimit, { size_t nextNewline = findNewLine(codepoints, 0); - for (size_t index = 0; index < codepoints.cps.size(); index++) + for (size_t index = 0; index < codepoints.cps.size();) { if (nextNewline < index) nextNewline = findNewLine(codepoints, index); + /* empty line */ if (nextNewline == index) { lineRanges.push_back(Range()); @@ -293,6 +296,7 @@ void TextShaper::GetWrap(const ColoredCodepoints& codepoints, float wrapLimit, index++; } + /* already handled the line, skip newline */ if (nextNewline == index) index++; @@ -353,4 +357,4 @@ void TextShaper::SetFallbacks(const std::vector& fallbacks) this->dpiScales.push_back(rasterizer->GetDPIScale()); } } -} \ No newline at end of file +}