| #ifdef WITH_RIVE_SCRIPTING |
| #include "rive/math/mat2d.hpp" |
| #include "rive/lua/rive_lua_libs.hpp" |
| |
| using namespace rive; |
| |
| static ScriptedMat2D* lua_pushmat2d(lua_State* L, |
| float x1, |
| float y1, |
| float x2, |
| float y2, |
| float tx, |
| float ty) |
| { |
| return lua_newrive<ScriptedMat2D>(L, x1, y1, x2, y2, tx, ty); |
| } |
| |
| static ScriptedMat2D* lua_pushmat2d(lua_State* L, const Mat2D& mat) |
| { |
| return lua_newrive<ScriptedMat2D>(L, mat); |
| } |
| |
| static int mat2d_values(lua_State* L) |
| { |
| float m[6] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; |
| for (int i = 0; i < 6; i++) |
| { |
| m[i] = float(luaL_checknumber(L, 1 + i)); |
| } |
| |
| lua_pushmat2d(L, m[0], m[1], m[2], m[3], m[4], m[5]); |
| return 1; |
| } |
| |
| static int mat2d_identity(lua_State* L) |
| { |
| lua_pushmat2d(L, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); |
| return 1; |
| } |
| |
| static int mat2d_withTranslation(lua_State* L) |
| { |
| auto vec = lua_tovec2d(L, 1); |
| if (vec != nullptr) |
| { |
| lua_pushmat2d(L, Mat2D::fromTranslation(*vec)); |
| return 1; |
| } |
| |
| float x = float(luaL_checknumber(L, 1)); |
| float y = float(luaL_checknumber(L, 2)); |
| |
| lua_pushmat2d(L, Mat2D::fromTranslation(Vec2D(x, y))); |
| |
| return 1; |
| } |
| |
| static int mat2d_withRotation(lua_State* L) |
| { |
| float radians = float(luaL_checknumber(L, 1)); |
| |
| lua_pushmat2d(L, Mat2D::fromRotation(radians)); |
| |
| return 1; |
| } |
| |
| static int mat2d_withScale(lua_State* L) |
| { |
| auto scale = lua_tovec2d(L, 1); |
| if (scale != nullptr) |
| { |
| lua_pushmat2d(L, Mat2D::fromScale(scale->x, scale->y)); |
| return 1; |
| } |
| float scaleX = float(luaL_checknumber(L, 1)); |
| float scaleY = lua_isnumber(L, 2) ? float(luaL_checknumber(L, 2)) : scaleX; |
| |
| lua_pushmat2d(L, Mat2D::fromScale(scaleX, scaleY)); |
| |
| return 1; |
| } |
| |
| static int mat2d_withScaleAndTranslation(lua_State* L) |
| { |
| auto scale = lua_tovec2d(L, 1); |
| if (scale != nullptr) |
| { |
| auto translation = lua_checkvec2d(L, 2); |
| lua_pushmat2d(L, |
| Mat2D::fromScaleAndTranslation(scale->x, |
| scale->y, |
| translation->x, |
| translation->y)); |
| return 1; |
| } |
| float scaleX = float(luaL_checknumber(L, 1)); |
| float scaleY = float(luaL_checknumber(L, 2)); |
| float translationX = float(luaL_checknumber(L, 3)); |
| float translationY = float(luaL_checknumber(L, 4)); |
| |
| lua_pushmat2d(L, |
| Mat2D::fromScaleAndTranslation(scaleX, |
| scaleY, |
| translationX, |
| translationY)); |
| |
| return 1; |
| } |
| |
| static int mat2d_index(lua_State* L) |
| { |
| auto mat = lua_torive<ScriptedMat2D>(L, 1); |
| |
| size_t namelen = 0; |
| const char* name = luaL_checklstring(L, 2, &namelen); |
| switch (namelen) |
| { |
| case 2: |
| switch (name[0]) |
| { |
| case 'x': |
| switch (name[1]) |
| { |
| case 'x': |
| lua_pushnumber(L, mat->value.xx()); |
| return 1; |
| case 'y': |
| lua_pushnumber(L, mat->value.xy()); |
| return 1; |
| } |
| break; |
| case 'y': |
| switch (name[1]) |
| { |
| case 'x': |
| lua_pushnumber(L, mat->value.yx()); |
| return 1; |
| case 'y': |
| lua_pushnumber(L, mat->value.yy()); |
| return 1; |
| } |
| break; |
| case 't': |
| switch (name[1]) |
| { |
| case 'x': |
| lua_pushnumber(L, mat->value.tx()); |
| return 1; |
| case 'y': |
| lua_pushnumber(L, mat->value.ty()); |
| return 1; |
| } |
| return 1; |
| default: |
| break; |
| } |
| break; |
| case 1: |
| switch (name[0]) |
| { |
| case '1': |
| lua_pushnumber(L, mat->value.xx()); |
| return 1; |
| case '2': |
| lua_pushnumber(L, mat->value.xy()); |
| return 1; |
| case '3': |
| lua_pushnumber(L, mat->value.yx()); |
| return 1; |
| case '4': |
| lua_pushnumber(L, mat->value.yy()); |
| return 1; |
| case '5': |
| lua_pushnumber(L, mat->value.tx()); |
| return 1; |
| case '6': |
| lua_pushnumber(L, mat->value.ty()); |
| return 1; |
| default: |
| break; |
| } |
| break; |
| } |
| |
| luaL_error(L, |
| "'%s' is not a valid index of %s", |
| name, |
| ScriptedMat2D::luaName); |
| return 0; |
| } |
| |
| static int mat2d_mul(lua_State* L) |
| { |
| auto mat2d = lua_torive<ScriptedMat2D>(L, 1); |
| auto vec = lua_tovec2d(L, 2); |
| if (vec != nullptr) |
| { |
| lua_pushvec2d(L, mat2d->value * (*vec)); |
| return 1; |
| } |
| auto rhs = lua_torive<ScriptedMat2D>(L, 2); |
| |
| lua_pushmat2d(L, mat2d->value * rhs->value); |
| return 1; |
| } |
| |
| static int mat2d_invert(lua_State* L) |
| { |
| auto mat2d = lua_torive<ScriptedMat2D>(L, 1); |
| Mat2D result; |
| if (mat2d->value.invert(&result)) |
| { |
| lua_pushmat2d(L, result); |
| return 1; |
| } |
| lua_pushnil(L); |
| return 1; |
| } |
| |
| static int mat2d_isIdentity(lua_State* L) |
| { |
| auto mat2d = lua_torive<ScriptedMat2D>(L, 1); |
| lua_pushboolean(L, mat2d->value == Mat2D()); |
| return 1; |
| } |
| |
| static int mat2d_eq(lua_State* L) |
| { |
| auto lhs = lua_torive<ScriptedMat2D>(L, 1); |
| auto rhs = lua_torive<ScriptedMat2D>(L, 2); |
| lua_pushboolean(L, lhs->value == rhs->value); |
| return 1; |
| } |
| |
| static int mat2d_namecall(lua_State* L) |
| { |
| int atom; |
| if (lua_namecallatom(L, &atom)) |
| { |
| switch (atom) |
| { |
| case (int)LuaAtoms::invert: |
| return mat2d_invert(L); |
| case (int)LuaAtoms::isIdentity: |
| return mat2d_isIdentity(L); |
| } |
| } |
| |
| luaL_error(L, |
| "%s is not a valid method of %s", |
| luaL_checkstring(L, 1), |
| ScriptedMat2D::luaName); |
| return 0; |
| } |
| |
| static const luaL_Reg mat2dStaticMethods[] = { |
| {"withTranslation", mat2d_withTranslation}, |
| {"withRotation", mat2d_withRotation}, |
| {"withScale", mat2d_withScale}, |
| {"withScaleAndTranslation", mat2d_withScaleAndTranslation}, |
| {"identity", mat2d_identity}, |
| {"values", mat2d_values}, |
| {nullptr, nullptr}}; |
| |
| int luaopen_rive_mat2d(lua_State* L) |
| { |
| luaL_register(L, ScriptedMat2D::luaName, mat2dStaticMethods); |
| lua_register_rive<ScriptedMat2D>(L); |
| |
| lua_pushcfunction(L, mat2d_index, nullptr); |
| lua_setfield(L, -2, "__index"); |
| |
| lua_pushcfunction(L, mat2d_mul, nullptr); |
| lua_setfield(L, -2, "__mul"); |
| |
| lua_pushcfunction(L, mat2d_eq, nullptr); |
| lua_setfield(L, -2, "__eq"); |
| |
| lua_pushcfunction(L, mat2d_namecall, nullptr); |
| lua_setfield(L, -2, "__namecall"); |
| |
| lua_setreadonly(L, -1, true); |
| lua_pop(L, 1); // pop the metatable |
| return 1; |
| } |
| |
| #endif |