219 lines
5.1 KiB
C
219 lines
5.1 KiB
C
// BLANKART
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2025 by LJ Sonic
|
|
//
|
|
// This program is free software distributed under the
|
|
// terms of the GNU General Public License, version 2.
|
|
// See the 'LICENSE' file for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file lua_vectorlib.c
|
|
/// \brief vector library for Lua scripting
|
|
|
|
#include "m_fixed.h"
|
|
#include "lua_script.h"
|
|
#include "lua_libs.h"
|
|
|
|
// shared by both Vector2D and Vector3D
|
|
enum vectorfield_e {
|
|
vectorfield_clone = 0,
|
|
vectorfield_opposite,
|
|
vectorfield_x,
|
|
vectorfield_y,
|
|
vectorfield_z,
|
|
vectorfield_length,
|
|
vectorfield_normalized,
|
|
};
|
|
|
|
static const char *const vectorfield_opt[] = {
|
|
"vector_clone",
|
|
"vector_opposite",
|
|
"x",
|
|
"y",
|
|
"z",
|
|
"vector_length",
|
|
"vector_normalized",
|
|
NULL};
|
|
|
|
////////////////////////////
|
|
// VECTOR2 STATIC MEMBERS //
|
|
////////////////////////////
|
|
|
|
/////////////////////
|
|
// VECTOR2 MEMBERS //
|
|
/////////////////////
|
|
|
|
static int vector2d_get(lua_State *L)
|
|
{
|
|
vector2_t *vec = luaL_checkudata(L, 1, META_VECTOR2);
|
|
enum vectorfield_e field = luaL_checkoption(L, 2, vectorfield_opt[0], vectorfield_opt);
|
|
|
|
switch(field)
|
|
{
|
|
case vectorfield_x: lua_pushfixed(L, vec->x); return 1;
|
|
case vectorfield_y: lua_pushfixed(L, vec->y); return 1;
|
|
default: break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/////////////
|
|
// VECTOR3 //
|
|
/////////////
|
|
|
|
static vector3_t *NewVector3(lua_State *L)
|
|
{
|
|
vector3_t *vec = lua_newuserdata(L, sizeof(*vec));
|
|
luaL_getmetatable(L, META_VECTOR3);
|
|
lua_setmetatable(L, -2);
|
|
return vec;
|
|
}
|
|
|
|
////////////////////////////
|
|
// VECTOR3 STATIC MEMBERS //
|
|
////////////////////////////
|
|
|
|
static int vector3d_new(lua_State *L)
|
|
{
|
|
fixed_t x = luaL_checkfixed(L, 1);
|
|
fixed_t y = luaL_checkfixed(L, 2);
|
|
fixed_t z = luaL_optfixed(L, 3, 0);
|
|
|
|
FV3_Load(NewVector3(L), x, y, z);
|
|
return 1;
|
|
}
|
|
|
|
static luaL_Reg vector3d[] = {
|
|
{"new", vector3d_new},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
/////////////////////
|
|
// VECTOR3 MEMBERS //
|
|
/////////////////////
|
|
|
|
static int vector3d_clone(lua_State *L)
|
|
{
|
|
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
|
FV3_Copy(NewVector3(L), vec);
|
|
return 1;
|
|
}
|
|
|
|
static int vector3d_opposite(lua_State *L)
|
|
{
|
|
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
|
FV3_NegateEx(vec, NewVector3(L));
|
|
return 1;
|
|
}
|
|
|
|
static int vector3d_get(lua_State *L)
|
|
{
|
|
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
|
enum vectorfield_e field = luaL_checkoption(L, 2, vectorfield_opt[0], vectorfield_opt);
|
|
|
|
if (!vec)
|
|
return luaL_error(L, "accessed vector3_t doesn't exist anymore.");
|
|
|
|
vector3_t unit = { 0, 0, 0 };
|
|
switch(field)
|
|
{
|
|
case vectorfield_clone: lua_pushcfunction(L, vector3d_clone); return 1;
|
|
case vectorfield_opposite: lua_pushcfunction(L, vector3d_opposite); return 1;
|
|
|
|
case vectorfield_x: lua_pushfixed(L, vec->x); return 1;
|
|
case vectorfield_y: lua_pushfixed(L, vec->y); return 1;
|
|
case vectorfield_z: lua_pushfixed(L, vec->z); return 1;
|
|
case vectorfield_length: lua_pushfixed(L, FV3_Distance(&unit, vec)); return 1;
|
|
case vectorfield_normalized: FV3_NormalizeEx(vec, NewVector3(L)); return 1;
|
|
|
|
default: break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
///////////////////////
|
|
// VECTOR3 OPERATORS //
|
|
///////////////////////
|
|
|
|
static int vector3d_eq(lua_State *L)
|
|
{
|
|
vector3_t *vec1 = luaL_checkudata(L, 1, META_VECTOR3);
|
|
vector3_t *vec2 = luaL_checkudata(L, 2, META_VECTOR3);
|
|
lua_pushboolean(L, FV3_Equal(vec1, vec2));
|
|
return 1;
|
|
}
|
|
|
|
static int vector3d_op(
|
|
lua_State *L,
|
|
vector3_t *(*opvector)(const vector3_t*, const vector3_t*, vector3_t*)
|
|
)
|
|
{
|
|
if (lua_isnumber(L, 1) && (opvector == FV3_AddEx || opvector == FV3_MulEx))
|
|
{
|
|
fixed_t n1 = lua_tofixed(L, 1);
|
|
vector3_t vec1 = { n1, n1, n1 };
|
|
vector3_t *vec2 = luaL_checkudata(L, 2, META_VECTOR3);
|
|
opvector(NewVector3(L), vec2, &vec1);
|
|
}
|
|
else if (lua_isnumber(L, 2))
|
|
{
|
|
vector3_t *vec1 = luaL_checkudata(L, 1, META_VECTOR3);
|
|
fixed_t n2 = lua_tofixed(L, 2);
|
|
vector3_t vec2 = { n2, n2, n2 };
|
|
opvector(NewVector3(L), vec1, &vec2);
|
|
}
|
|
else
|
|
{
|
|
vector3_t *vec1 = luaL_checkudata(L, 1, META_VECTOR3);
|
|
vector3_t *vec2 = luaL_checkudata(L, 2, META_VECTOR3);
|
|
opvector(NewVector3(L), vec1, vec2);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int vector3d_add(lua_State *L)
|
|
{
|
|
return vector3d_op(L, FV3_AddEx);
|
|
}
|
|
|
|
static int vector3d_sub(lua_State *L)
|
|
{
|
|
return vector3d_op(L, FV3_SubEx);
|
|
}
|
|
|
|
static int vector3d_mul(lua_State *L)
|
|
{
|
|
return vector3d_op(L, FV3_MulEx);
|
|
}
|
|
|
|
static int vector3d_div(lua_State *L)
|
|
{
|
|
return vector3d_op(L, FV3_DivideEx);
|
|
}
|
|
|
|
static int vector3d_unm(lua_State *L)
|
|
{
|
|
vector3_t *vec = luaL_checkudata(L, 1, META_VECTOR3);
|
|
FV3_NegateEx(vec, NewVector3(L));
|
|
return 1;
|
|
}
|
|
|
|
int LUA_VectorLib(lua_State *L)
|
|
{
|
|
LUA_RegisterUserdataMetatable(L, META_VECTOR2, vector2d_get, NULL, NULL);
|
|
|
|
luaL_newmetatable(L, META_VECTOR3);
|
|
LUA_SetCFunctionField(L, "__index", vector3d_get);
|
|
LUA_SetCFunctionField(L, "__eq", vector3d_eq);
|
|
LUA_SetCFunctionField(L, "__add", vector3d_add);
|
|
LUA_SetCFunctionField(L, "__sub", vector3d_sub);
|
|
LUA_SetCFunctionField(L, "__mul", vector3d_mul);
|
|
LUA_SetCFunctionField(L, "__div", vector3d_div);
|
|
LUA_SetCFunctionField(L, "__unm", vector3d_unm);
|
|
lua_pop(L, 1);
|
|
|
|
luaL_register(L, "Vector3D", vector3d);
|
|
return 0;
|
|
}
|