blob: 29622ce4ab951f23836733c8b8c10a5fdb7e4135 [file] [log] [blame] [edit]
#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