diff --git a/plugins/lovr-http b/plugins/lovr-http index 69906e40..67d92ac4 160000 --- a/plugins/lovr-http +++ b/plugins/lovr-http @@ -1 +1 @@ -Subproject commit 69906e40f571bcbdda00fe2e6f504c3487f93d56 +Subproject commit 67d92ac4239d79a8ec44e6dea8c4eda9ae514628 diff --git a/src/api/api.c b/src/api/api.c index a6d0067c..9f0170d8 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -577,3 +577,13 @@ int luax_readmesh(lua_State* L, int index, float** vertices, uint32_t* vertexCou return luaL_argerror(L, index, "table, Mesh, or Model"); } + +void luax_readobjarr(lua_State* L, int index, int n, float* out, const char* name) { + lovrCheck(luax_len(L, index) >= n, "length of %s table must >= %i", name, n); + if (index < 0) index = lua_gettop(L) + index + 1; + for (int i = 0; i < n; i++) { + lua_rawgeti(L, index, i + 1); + out[i] = lua_tonumber(L, -1); + } + lua_pop(L, n); +} \ No newline at end of file diff --git a/src/api/api.h b/src/api/api.h index 527f4a6d..d5fdbb46 100644 --- a/src/api/api.h +++ b/src/api/api.h @@ -130,6 +130,7 @@ uint32_t _luax_optu32(lua_State* L, int index, uint32_t fallback); void luax_readcolor(lua_State* L, int index, float color[4]); void luax_optcolor(lua_State* L, int index, float color[4]); int luax_readmesh(lua_State* L, int index, float** vertices, uint32_t* vertexCount, uint32_t** indices, uint32_t* indexCount, bool* shouldFree); +void luax_readobjarr(lua_State* L, int index, int n, float* out, const char* name); // Module helpers diff --git a/src/api/l_graphics_buffer.c b/src/api/l_graphics_buffer.c index 3c75bf28..5ff54a1b 100644 --- a/src/api/l_graphics_buffer.c +++ b/src/api/l_graphics_buffer.c @@ -251,6 +251,8 @@ void luax_checkdatatuples(lua_State* L, int index, int start, uint32_t count, co const DataField* field = &format->fields[f]; if (lua_isuserdata(L, -1)) { luax_checkfieldv(L, -1, field->type, data + field->offset); + } else if (lua_istable(L, -1)) { + luax_checkfieldt(L, -1, field->type, data + field->offset); } else { while (n < (int) typeComponents[field->type]) { lua_rawgeti(L, -n - 1, subindex + n); diff --git a/src/api/l_math.c b/src/api/l_math.c index 460eb03d..6b1f5b94 100644 --- a/src/api/l_math.c +++ b/src/api/l_math.c @@ -33,12 +33,18 @@ extern const luaL_Reg lovrMat4[]; static LOVR_THREAD_LOCAL Pool* pool; -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 struct { + const char* name; + lua_CFunction constructor, indexer; + const luaL_Reg* api; + int metaref; + int components; +} lovrVectorInfo[] = { + [V_VEC2] = { "vec2", l_lovrMathVec2, l_lovrVec2__metaindex, lovrVec2, LUA_REFNIL, 2 }, + [V_VEC3] = { "vec3", l_lovrMathVec3, l_lovrVec3__metaindex, lovrVec3, LUA_REFNIL, 3 }, + [V_VEC4] = { "vec4", l_lovrMathVec4, l_lovrVec4__metaindex, lovrVec4, LUA_REFNIL, 4 }, + [V_QUAT] = { "quat", l_lovrMathQuat, l_lovrQuat__metaindex, lovrQuat, LUA_REFNIL, 4 }, + [V_MAT4] = { "mat4", l_lovrMathMat4, l_lovrMat4__metaindex, lovrMat4, LUA_REFNIL, 16 } }; static void luax_destroypool(void) { @@ -70,8 +76,18 @@ float* luax_tovector(lua_State* L, int index, VectorType* type) { float* luax_checkvector(lua_State* L, int index, VectorType type, const char* expected) { VectorType t; - float* p = luax_tovector(L, index, &t); - if (!p || t != type) luax_typeerror(L, index, expected ? expected : lovrVectorInfo[type].name); + float* p; + if (lua_istable(L, index)) { + lovrPoolAllocate(pool, type, &p); + luax_readobjarr(L, index, lovrVectorInfo[type].components, p, lovrVectorInfo[type].name); + return p; + } else { + p = luax_tovector(L, index, &t); + } + + if (!p || t != type) { + luax_typeerror(L, index, expected ? expected : lovrVectorInfo[type].name); + } return p; } diff --git a/src/api/l_math_vectors.c b/src/api/l_math_vectors.c index 4e1afaa6..c2e72a66 100644 --- a/src/api/l_math_vectors.c +++ b/src/api/l_math_vectors.c @@ -52,8 +52,11 @@ int luax_readvec2(lua_State* L, int index, vec2 v, const char* expected) { v[0] = luax_tofloat(L, index++); v[1] = luax_optfloat(L, index++, v[0]); return index; + case LUA_TTABLE: + luax_readobjarr(L, index, 2, v, "vec2"); + return index + 1; default: - vec2_init(v, luax_checkvector(L, index, V_VEC2, expected ? expected : "vec2 or number")); + vec2_init(v, luax_checkvector(L, index, V_VEC2, expected ? expected : "vec2, table or number")); return index + 1; } } @@ -69,8 +72,11 @@ int luax_readvec3(lua_State* L, int index, vec3 v, const char* expected) { v[1] = luax_optfloat(L, index++, v[0]); v[2] = luax_optfloat(L, index++, v[0]); return index; + case LUA_TTABLE: + luax_readobjarr(L, index, 3, v, "vec3"); + return index + 1; default: - vec3_init(v, luax_checkvector(L, index, V_VEC3, expected ? expected : "vec3 or number")); + vec3_init(v, luax_checkvector(L, index, V_VEC3, expected ? expected : "vec3, table or number")); return index + 1; } } @@ -87,13 +93,17 @@ int luax_readvec4(lua_State* L, int index, vec4 v, const char* expected) { v[2] = luax_optfloat(L, index++, v[0]); v[3] = luax_optfloat(L, index++, v[0]); return index; + case LUA_TTABLE: + luax_readobjarr(L, index, 4, v, "vec4"); + return index + 1; default: - vec4_init(v, luax_checkvector(L, index, V_VEC4, expected ? expected : "vec4 or number")); + vec4_init(v, luax_checkvector(L, index, V_VEC4, expected ? expected : "vec4, table or number")); return index + 1; } } int luax_readscale(lua_State* L, int index, vec3 v, int components, const char* expected) { + int tlen; switch (lua_type(L, index)) { case LUA_TNIL: case LUA_TNONE: @@ -112,6 +122,17 @@ int luax_readscale(lua_State* L, int index, vec3 v, int components, const char* } } return index; + case LUA_TTABLE: + tlen = luax_len(L, index); + if (tlen >= 3) { + luax_readobjarr(L, index, 3, v, "scale"); + } else if (tlen == 2) { + luax_readobjarr(L, index, 2, v, "scale"); + v[2] = 1.f; + } else { + return luax_typeerror(L, index, "table length must >= 2"); + } + return index + 1; default: { VectorType type; float* u = luax_tovector(L, index++, &type); @@ -122,7 +143,7 @@ int luax_readscale(lua_State* L, int index, vec3 v, int components, const char* } else if (type == V_VEC3) { vec3_init(v, u); } else { - return luax_typeerror(L, index, "vec2, vec3, or number"); + return luax_typeerror(L, index, "vec2, vec3, table or number"); } return index; } @@ -143,8 +164,11 @@ int luax_readquat(lua_State* L, int index, quat q, const char* expected) { az = luax_optfloat(L, index++, 0.f); quat_fromAngleAxis(q, angle, ax, ay, az); return index; + case LUA_TTABLE: + luax_readobjarr(L, index, 4, q, "quat"); + return index + 1; default: - quat_init(q, luax_checkvector(L, index++, V_QUAT, expected ? expected : "quat or number")); + quat_init(q, luax_checkvector(L, index++, V_QUAT, expected ? expected : "quat, table or number")); return index; } } @@ -167,11 +191,18 @@ int luax_readmat4(lua_State* L, int index, mat4 m, int scaleComponents) { } } // Fall through + case LUA_TTABLE: + if (lua_istable(L, index) && luax_len(L, index) >= 16) { + luax_readobjarr(L, index, 16, m, "mat4"); + return index + 1; + } + // Fall through + case LUA_TNUMBER: { float S[3]; float R[4]; mat4_identity(m); - index = luax_readvec3(L, index, m + 12, "mat4, vec3, or number"); + index = luax_readvec3(L, index, m + 12, "mat4, vec3, table or number"); index = luax_readscale(L, index, S, scaleComponents, NULL); index = luax_readquat(L, index, R, NULL); mat4_rotateQuat(m, R);