From 21b71d02b5bb5f1c914da8d851294fe36ce70b81 Mon Sep 17 00:00:00 2001 From: Sasha Szpakowski Date: Sun, 24 Mar 2024 10:46:29 -0300 Subject: [PATCH] Add love.graphics.setCustomProjection. The active projection matrix is reset when changing canvases, and when the window is resized if no canvas is active at the time. --- src/modules/graphics/wrap_Graphics.cpp | 29 ++++ src/modules/math/wrap_Transform.cpp | 187 +++++++++++++------------ src/modules/math/wrap_Transform.h | 1 + 3 files changed, 125 insertions(+), 92 deletions(-) diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index eb9be70b9..b4f46fdb9 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3900,6 +3900,34 @@ int w_inverseTransformPoint(lua_State *L) return 2; } +int w_setCustomProjection(lua_State *L) +{ + math::Transform *transform = luax_totype(L, 1); + if (transform != nullptr) + { + instance()->setCustomProjection(transform->getMatrix()); + return 0; + } + + math::Transform::MatrixLayout layout = math::Transform::MATRIX_ROW_MAJOR; + + int idx = 1; + if (lua_type(L, idx) == LUA_TSTRING) + { + const char* layoutstr = lua_tostring(L, idx); + if (!math::Transform::getConstant(layoutstr, layout)) + return luax_enumerror(L, "matrix layout", math::Transform::getConstants(layout), layoutstr); + + idx++; + } + + float elements[16]; + love::math::luax_checkmatrix(L, idx, layout, elements); + + instance()->setCustomProjection(Matrix4(elements)); + return 0; +} + int w_resetProjection(lua_State */*L*/) { instance()->resetProjection(); @@ -4052,6 +4080,7 @@ static const luaL_Reg functions[] = { "transformPoint", w_transformPoint }, { "inverseTransformPoint", w_inverseTransformPoint }, + { "setCustomProjection", w_setCustomProjection }, { "resetProjection", w_resetProjection }, // Deprecated diff --git a/src/modules/math/wrap_Transform.cpp b/src/modules/math/wrap_Transform.cpp index b622e1dad..24e2aa45a 100644 --- a/src/modules/math/wrap_Transform.cpp +++ b/src/modules/math/wrap_Transform.cpp @@ -30,6 +30,99 @@ Transform *luax_checktransform(lua_State *L, int idx) return luax_checktype(L, idx, Transform::type); } +void luax_checkmatrix(lua_State *L, int idx, Transform::MatrixLayout layout, float elements[16]) +{ + bool columnmajor = layout == Transform::MATRIX_COLUMN_MAJOR; + + if (lua_istable(L, idx)) + { + lua_rawgeti(L, idx, 1); + bool tableoftables = lua_istable(L, -1); + lua_pop(L, 1); + + if (tableoftables) + { + if (columnmajor) + { + for (int column = 0; column < 4; column++) + { + lua_rawgeti(L, idx, column + 1); + + for (int row = 0; row < 4; row++) + { + lua_rawgeti(L, -(row + 1), row + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + + lua_pop(L, 4 + 1); + } + } + else + { + for (int row = 0; row < 4; row++) + { + lua_rawgeti(L, idx, row + 1); + + for (int column = 0; column < 4; column++) + { + // The table has the matrix elements laid out in row-major + // order, but we need to store them column-major in memory. + lua_rawgeti(L, -(column + 1), column + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + + lua_pop(L, 4 + 1); + } + } + } + else + { + if (columnmajor) + { + for (int column = 0; column < 4; column++) + { + for (int row = 0; row < 4; row++) + { + lua_rawgeti(L, idx, column * 4 + row + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + } + } + else + { + for (int column = 0; column < 4; column++) + { + for (int row = 0; row < 4; row++) + { + // The table has the matrix elements laid out in row-major + // order, but we need to store them column-major in memory. + lua_rawgeti(L, idx, row * 4 + column + 1); + elements[column * 4 + row] = (float) luaL_checknumber(L, -1); + } + } + } + + lua_pop(L, 16); + } + } + else + { + if (columnmajor) + { + for (int i = 0; i < 16; i++) + elements[i] = (float) luaL_checknumber(L, idx + i); + } + else + { + for (int column = 0; column < 4; column++) + { + for (int row = 0; row < 4; row++) + elements[column * 4 + row] = (float) luaL_checknumber(L, row * 4 + column + idx); + } + } + } +} + int w_Transform_clone(lua_State *L) { Transform *t = luax_checktransform(L, 1); @@ -131,110 +224,20 @@ int w_Transform_setTransformation(lua_State *L) int w_Transform_setMatrix(lua_State *L) { Transform *t = luax_checktransform(L, 1); - - bool columnmajor = false; + Transform::MatrixLayout layout = Transform::MATRIX_ROW_MAJOR; int idx = 2; if (lua_type(L, idx) == LUA_TSTRING) { const char *layoutstr = lua_tostring(L, idx); - Transform::MatrixLayout layout; if (!Transform::getConstant(layoutstr, layout)) return luax_enumerror(L, "matrix layout", Transform::getConstants(layout), layoutstr); - columnmajor = (layout == Transform::MATRIX_COLUMN_MAJOR); idx++; } float elements[16]; - - if (lua_istable(L, idx)) - { - lua_rawgeti(L, idx, 1); - bool tableoftables = lua_istable(L, -1); - lua_pop(L, 1); - - if (tableoftables) - { - if (columnmajor) - { - for (int column = 0; column < 4; column++) - { - lua_rawgeti(L, idx, column + 1); - - for (int row = 0; row < 4; row++) - { - lua_rawgeti(L, -(row + 1), row + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - - lua_pop(L, 4 + 1); - } - } - else - { - for (int row = 0; row < 4; row++) - { - lua_rawgeti(L, idx, row + 1); - - for (int column = 0; column < 4; column++) - { - // The table has the matrix elements laid out in row-major - // order, but we need to store them column-major in memory. - lua_rawgeti(L, -(column + 1), column + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - - lua_pop(L, 4 + 1); - } - } - } - else - { - if (columnmajor) - { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - { - lua_rawgeti(L, idx, column * 4 + row + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - } - } - else - { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - { - // The table has the matrix elements laid out in row-major - // order, but we need to store them column-major in memory. - lua_rawgeti(L, idx, row * 4 + column + 1); - elements[column * 4 + row] = (float) luaL_checknumber(L, -1); - } - } - } - - lua_pop(L, 16); - } - } - else - { - if (columnmajor) - { - for (int i = 0; i < 16; i++) - elements[i] = (float) luaL_checknumber(L, idx + i); - } - else - { - for (int column = 0; column < 4; column++) - { - for (int row = 0; row < 4; row++) - elements[column * 4 + row] = (float) luaL_checknumber(L, row * 4 + column + idx); - } - } - } + luax_checkmatrix(L, idx, layout, elements); t->setMatrix(Matrix4(elements)); lua_pushvalue(L, 1); diff --git a/src/modules/math/wrap_Transform.h b/src/modules/math/wrap_Transform.h index 80f3a1e15..53feb3b7a 100644 --- a/src/modules/math/wrap_Transform.h +++ b/src/modules/math/wrap_Transform.h @@ -30,6 +30,7 @@ namespace math { Transform *luax_checktransform(lua_State *L, int idx); +void luax_checkmatrix(lua_State *L, int idx, Transform::MatrixLayout layout, float elements[16]); extern "C" int luaopen_transform(lua_State *L); } // math