diff --git a/src/api/l_math.c b/src/api/l_math.c index 5b80ce28..48c6b533 100644 --- a/src/api/l_math.c +++ b/src/api/l_math.c @@ -15,6 +15,11 @@ int l_lovrVec3Set(lua_State* L); int l_lovrVec4Set(lua_State* L); int l_lovrQuatSet(lua_State* L); int l_lovrMat4Set(lua_State* L); +int l_lovrVec2__metaindex(lua_State* L); +int l_lovrVec3__metaindex(lua_State* L); +int l_lovrVec4__metaindex(lua_State* L); +int l_lovrQuat__metaindex(lua_State* L); +int l_lovrMat4__metaindex(lua_State* L); static int l_lovrMathVec2(lua_State* L); static int l_lovrMathVec3(lua_State* L); static int l_lovrMathVec4(lua_State* L); @@ -30,12 +35,12 @@ extern const luaL_Reg lovrMat4[]; static LOVR_THREAD_LOCAL Pool* pool; -static struct { const char* name; lua_CFunction constructor; const luaL_Reg* api; int metaref; } lovrVectorInfo[] = { - [V_VEC2] = { "vec2", l_lovrMathVec2, lovrVec2, LUA_REFNIL }, - [V_VEC3] = { "vec3", l_lovrMathVec3, lovrVec3, LUA_REFNIL }, - [V_VEC4] = { "vec4", l_lovrMathVec4, lovrVec4, LUA_REFNIL }, - [V_QUAT] = { "quat", l_lovrMathQuat, lovrQuat, LUA_REFNIL }, - [V_MAT4] = { "mat4", l_lovrMathMat4, lovrMat4, LUA_REFNIL } +static struct { const char* name; lua_CFunction constructor, indexer; const luaL_Reg* api; int metaref; } lovrVectorInfo[] = { + [V_VEC2] = { "vec2", l_lovrMathVec2, l_lovrVec2__metaindex, lovrVec2, LUA_REFNIL }, + [V_VEC3] = { "vec3", l_lovrMathVec3, l_lovrVec3__metaindex, lovrVec3, LUA_REFNIL }, + [V_VEC4] = { "vec4", l_lovrMathVec4, l_lovrVec4__metaindex, lovrVec4, LUA_REFNIL }, + [V_QUAT] = { "quat", l_lovrMathQuat, l_lovrQuat__metaindex, lovrQuat, LUA_REFNIL }, + [V_MAT4] = { "mat4", l_lovrMathMat4, l_lovrMat4__metaindex, lovrMat4, LUA_REFNIL } }; static void luax_destroypool(void) { @@ -353,6 +358,8 @@ int luaopen_lovr_math(lua_State* L) { lua_newtable(L); lua_pushcfunction(L, lovrVectorInfo[i].constructor); lua_setfield(L, -2, "__call"); + lua_pushcfunction(L, lovrVectorInfo[i].indexer); + lua_setfield(L, -2, "__index"); lua_setmetatable(L, -2); lua_pushstring(L, lovrVectorInfo[i].name); diff --git a/src/api/l_math_vectors.c b/src/api/l_math_vectors.c index 2360a06e..f7f41f48 100644 --- a/src/api/l_math_vectors.c +++ b/src/api/l_math_vectors.c @@ -524,6 +524,31 @@ static int l_lovrVec2__index(lua_State* L) { return luaL_error(L, "attempt to index field %s of vec2 (invalid property)", lua_tostring(L, -1)); } +int l_lovrVec2__metaindex(lua_State* L) { + if (lua_type(L, 2) != LUA_TSTRING) { + return 0; + } + + size_t length; + const char* key = lua_tolstring(L, 2, &length); + + static const struct { StringEntry name; float x, y; } properties[] = { + { ENTRY("one"), 1.f, 1.f }, + { ENTRY("zero"), 0.f, 0.f } + }; + + for (uint32_t i = 0; i < COUNTOF(properties); i++) { + if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) { + float* v = luax_newtempvector(L, V_VEC2); + v[0] = properties[i].x; + v[1] = properties[i].y; + return 1; + } + } + + return 0; +} + const luaL_Reg lovrVec2[] = { { "equals", l_lovrVec2Equals }, { "unpack", l_lovrVec2Unpack }, @@ -947,6 +972,36 @@ static int l_lovrVec3__index(lua_State* L) { return luaL_error(L, "attempt to index field %s of vec3 (invalid property)", lua_tostring(L, -1)); } +int l_lovrVec3__metaindex(lua_State* L) { + if (lua_type(L, 2) != LUA_TSTRING) { + return 0; + } + + size_t length; + const char* key = lua_tolstring(L, 2, &length); + + static const struct { StringEntry name; float x, y, z; } properties[] = { + { ENTRY("one"), 1.f, 1.f, 1.f }, + { ENTRY("zero"), 0.f, 0.f, 0.f }, + { ENTRY("left"), -1.f, 0.f, 0.f }, + { ENTRY("right"), 1.f, 0.f, 0.f }, + { ENTRY("up"), 0.f, 1.f, 0.f }, + { ENTRY("down"), 0.f, -1.f, 0.f }, + { ENTRY("back"), 0.f, 0.f, 1.f }, + { ENTRY("forward"), 0.f, 0.f, -1.f } + }; + + for (uint32_t i = 0; i < COUNTOF(properties); i++) { + if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) { + float* v = luax_newtempvector(L, V_VEC3); + vec3_set(v, properties[i].x, properties[i].y, properties[i].z); + return 1; + } + } + + return 0; +} + const luaL_Reg lovrVec3[] = { { "equals", l_lovrVec3Equals }, { "unpack", l_lovrVec3Unpack }, @@ -1426,6 +1481,33 @@ static int l_lovrVec4__index(lua_State* L) { return luaL_error(L, "attempt to index field %s of vec4 (invalid property)", lua_tostring(L, -1)); } +int l_lovrVec4__metaindex(lua_State* L) { + if (lua_type(L, 2) != LUA_TSTRING) { + return 0; + } + + size_t length; + const char* key = lua_tolstring(L, 2, &length); + + static const struct { StringEntry name; float x, y, z, w; } properties[] = { + { ENTRY("one"), 1.f, 1.f, 1.f, 1.f }, + { ENTRY("zero"), 0.f, 0.f, 0.f, 0.f } + }; + + for (uint32_t i = 0; i < COUNTOF(properties); i++) { + if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) { + float* v = luax_newtempvector(L, V_VEC4); + v[0] = properties[i].x; + v[1] = properties[i].y; + v[2] = properties[i].z; + v[3] = properties[i].w; + return 1; + } + } + + return 0; +} + const luaL_Reg lovrVec4[] = { { "equals", l_lovrVec4Equals }, { "unpack", l_lovrVec4Unpack }, @@ -1659,6 +1741,29 @@ static int l_lovrQuat__index(lua_State* L) { return luaL_error(L, "attempt to index field %s of quat (invalid property)", lua_tostring(L, -1)); } +int l_lovrQuat__metaindex(lua_State* L) { + if (lua_type(L, 2) != LUA_TSTRING) { + return 0; + } + + size_t length; + const char* key = lua_tolstring(L, 2, &length); + + static const struct { StringEntry name; float x, y, z, w; } properties[] = { + { ENTRY("identity"), 0.f, 0.f, 0.f, 1.f } + }; + + for (uint32_t i = 0; i < COUNTOF(properties); i++) { + if (length == properties[i].name.length && !memcmp(key, properties[i].name.string, length)) { + float* q = luax_newtempvector(L, V_QUAT); + quat_set(q, properties[i].x, properties[i].y, properties[i].z, properties[i].w); + return 1; + } + } + + return 0; +} + const luaL_Reg lovrQuat[] = { { "equals", l_lovrQuatEquals }, { "unpack", l_lovrQuatUnpack }, @@ -2018,6 +2123,10 @@ static int l_lovrMat4__index(lua_State* L) { return luaL_error(L, "attempt to index field %s of mat4 (invalid property)", lua_tostring(L, -1)); } +int l_lovrMat4__metaindex(lua_State* L) { + return 0; // No properties currently, 'identity' is already taken +} + const luaL_Reg lovrMat4[] = { { "equals", l_lovrMat4Equals }, { "unpack", l_lovrMat4Unpack }, diff --git a/src/core/maf.h b/src/core/maf.h index c1fed4de..715ca5e8 100644 --- a/src/core/maf.h +++ b/src/core/maf.h @@ -302,7 +302,7 @@ MAF quat quat_between(quat q, vec3 u, vec3 v) { // mat4 -#define MAT4_IDENTITY { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 } +#define MAT4_IDENTITY { 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f } #define mat4_init mat4_set MAF mat4 mat4_set(mat4 m, mat4 n) {