1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 16:39:41 +00:00

lua - add swizzling to vector types

This commit is contained in:
Cody Glassman 2024-07-31 14:04:44 -07:00
parent 91d37c16af
commit 19c0cebb27
3 changed files with 95 additions and 10 deletions

View file

@ -49,6 +49,11 @@ namespace
EXPECT_TRUE(get<bool>(lua, "ediv0.x == math.huge and ediv0.y ~= ediv0.y"));
EXPECT_TRUE(get<bool>(lua, "util.vector2(1, 2):emul(util.vector2(3, 4)) == util.vector2(3, 8)"));
EXPECT_TRUE(get<bool>(lua, "util.vector2(4, 6):ediv(util.vector2(2, 3)) == util.vector2(2, 2)"));
lua.safe_script("swizzle = util.vector2(1, 2)");
EXPECT_TRUE(get<bool>(lua, "swizzle.xx == util.vector2(1, 1) and swizzle.yy == util.vector2(2, 2)"));
EXPECT_ERROR(lua.safe_script("v = util.vector2(1, 2).xp"), "unrecognized swizzle index");
EXPECT_ERROR(lua.safe_script("v = util.vector2(1, 2).xxxxx"), "invalid swizzle length");
EXPECT_ERROR(lua.safe_script("v = util.vector2(1, 2).zw"), "swizzle index out of range");
}
TEST(LuaUtilPackageTest, Vector3)
@ -82,6 +87,12 @@ namespace
EXPECT_TRUE(get<bool>(lua, "ediv0.z == math.huge"));
EXPECT_TRUE(get<bool>(lua, "util.vector3(1, 2, 3):emul(util.vector3(3, 4, 5)) == util.vector3(3, 8, 15)"));
EXPECT_TRUE(get<bool>(lua, "util.vector3(4, 6, 8):ediv(util.vector3(2, 3, 4)) == util.vector3(2, 2, 2)"));
lua.safe_script("swizzle = util.vector3(1, 2, 3)");
EXPECT_TRUE(get<bool>(lua, "swizzle.xxx == util.vector3(1, 1, 1)"));
EXPECT_TRUE(get<bool>(lua, "swizzle.xyz == swizzle.zyx.zyx"));
EXPECT_ERROR(lua.safe_script("v = util.vector3(1, 2, 3).xyp"), "unrecognized swizzle index");
EXPECT_ERROR(lua.safe_script("v = util.vector3(1, 2, 3).xxxxx"), "invalid swizzle length");
EXPECT_ERROR(lua.safe_script("v = util.vector3(1, 2, 3).xxxw"), "swizzle index out of range");
}
TEST(LuaUtilPackageTest, Vector4)
@ -116,6 +127,12 @@ namespace
get<bool>(lua, "util.vector4(1, 2, 3, 4):emul(util.vector4(3, 4, 5, 6)) == util.vector4(3, 8, 15, 24)"));
EXPECT_TRUE(
get<bool>(lua, "util.vector4(4, 6, 8, 9):ediv(util.vector4(2, 3, 4, 3)) == util.vector4(2, 2, 2, 3)"));
lua.safe_script("swizzle = util.vector4(1, 2, 3, 4)");
EXPECT_TRUE(get<bool>(lua, "swizzle.wwww == util.vector4(4, 4, 4, 4)"));
EXPECT_TRUE(get<bool>(lua, "swizzle.xyzw == util.vector4(1, 2, 3, 4)"));
EXPECT_TRUE(get<bool>(lua, "swizzle.xyzw == swizzle.wzyx.wzyx"));
EXPECT_ERROR(lua.safe_script("v = util.vector4(1, 2, 3, 4).xyp"), "unrecognized swizzle index");
EXPECT_ERROR(lua.safe_script("v = util.vector4(1, 2, 3, 4).xxxxx"), "invalid swizzle length");
}
TEST(LuaUtilPackageTest, Color)

View file

@ -14,6 +14,62 @@
#include "shapes/box.hpp"
namespace
{
int swizzleIndex(char c)
{
switch (c)
{
case 'x':
return 0;
case 'y':
return 1;
case 'z':
return 2;
case 'w':
return 3;
default:
throw std::runtime_error("unrecognized swizzle index");
}
}
template <class T>
sol::object swizzle(sol::state_view lua, const T& vec, std::string_view key)
{
if (key.length() <= 1 || key.length() > LuaUtil::Vec4::num_components)
{
throw std::runtime_error("invalid swizzle length");
}
std::array<float, 4> components;
size_t aindex = 0;
for (char c : key)
{
size_t sindex = swizzleIndex(c);
if (sindex >= T::num_components)
{
throw std::runtime_error("swizzle index out of range");
}
components[aindex++] = vec[sindex];
}
switch (key.length())
{
case 1:
return sol::make_object<float>(lua, components[0]);
case 2:
return sol::make_object<LuaUtil::Vec2>(lua, { components[0], components[1] });
case 3:
return sol::make_object<LuaUtil::Vec3>(lua, { components[0], components[1], components[2] });
case 4:
return sol::make_object<LuaUtil::Vec4>(
lua, { components[0], components[1], components[2], components[3] });
default:
throw std::runtime_error("fatal error");
}
}
}
namespace sol
{
template <>
@ -110,6 +166,8 @@ namespace LuaUtil
sol::usertype<Vec2> vec2Type = lua.new_usertype<Vec2>("Vec2");
vec2Type["x"] = sol::readonly_property([](const Vec2& v) -> float { return v.x(); });
vec2Type["y"] = sol::readonly_property([](const Vec2& v) -> float { return v.y(); });
vec2Type[sol::meta_function::index]
= [lua](const Vec2& v, std::string_view key) { return swizzle(lua, v, key); };
addVectorMethods<Vec2>(vec2Type);
vec2Type["rotate"] = &Misc::rotateVec2f;
@ -119,6 +177,8 @@ namespace LuaUtil
vec3Type["x"] = sol::readonly_property([](const Vec3& v) -> float { return v.x(); });
vec3Type["y"] = sol::readonly_property([](const Vec3& v) -> float { return v.y(); });
vec3Type["z"] = sol::readonly_property([](const Vec3& v) -> float { return v.z(); });
vec3Type[sol::meta_function::index]
= [lua](const Vec3& v, std::string_view key) { return swizzle(lua, v, key); };
addVectorMethods<Vec3>(vec3Type);
vec3Type[sol::meta_function::involution] = [](const Vec3& a, const Vec3& b) { return a ^ b; };
vec3Type["cross"] = [](const Vec3& a, const Vec3& b) { return a ^ b; };
@ -130,6 +190,8 @@ namespace LuaUtil
vec4Type["y"] = sol::readonly_property([](const Vec4& v) -> float { return v.y(); });
vec4Type["z"] = sol::readonly_property([](const Vec4& v) -> float { return v.z(); });
vec4Type["w"] = sol::readonly_property([](const Vec4& v) -> float { return v.w(); });
vec4Type[sol::meta_function::index]
= [lua](const Vec4& v, std::string_view key) { return swizzle(lua, v, key); };
addVectorMethods<Vec4>(vec4Type);
// Lua bindings for Box

View file

@ -94,6 +94,7 @@
-- @type Vector2
-- @field #number x
-- @field #number y
-- @field #string xy swizzle support, any combination of fields can be used to construct a new vector
-- @usage
-- v = util.vector2(3, 4)
-- v.x, v.y -- 3.0, 4.0
@ -108,6 +109,7 @@
-- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number
-- v1 / x -- division by a number
-- v1.xx, v1.xyx -- new vectors can be created with swizzles
---
-- Creates a new 2D vector. Vectors are immutable and can not be changed after creation.
@ -195,6 +197,7 @@
-- @field #number x
-- @field #number y
-- @field #number z
-- @field #string xyz swizzle support, any combination of fields can be used to construct a new vector
-- @usage
-- v = util.vector3(3, 4, 5)
-- v.x, v.y, v.z -- 3.0, 4.0, 5.0
@ -210,6 +213,7 @@
-- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number
-- v1 / x -- division by a number
-- v1.zyz, v1.yx -- new vectors can be created with swizzles
---
-- Creates a new 3D vector. Vectors are immutable and can not be changed after creation.
@ -304,19 +308,21 @@
-- @field #number y
-- @field #number z
-- @field #number w
-- @field #string xyzw swizzle support, any combination of fields can be used to construct a new vector
-- @usage
-- v = util.vector4(3, 4, 5, 6)
-- v.x, v.y, v.z, v.w -- 3.0, 4.0, 5.0, 6.0
-- str(v) -- "(3.0, 4.0, 5.0, 6.0)"
-- v:length() -- length
-- v:length2() -- square of the length
-- v:normalize() -- normalized vector
-- v1:dot(v2) -- dot product (returns a number)
-- v1 * v2 -- dot product (returns a number)
-- v1 + v2 -- vector addition
-- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number
-- v1 / x -- division by a number
-- str(v) -- "(3.0, 4.0, 5.0, 6.0)"
-- v:length() -- length
-- v:length2() -- square of the length
-- v:normalize() -- normalized vector
-- v1:dot(v2) -- dot product (returns a number)
-- v1 * v2 -- dot product (returns a number)
-- v1 + v2 -- vector addition
-- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number
-- v1 / x -- division by a number
-- v1.zzzz, v1.zyz -- new vectors can be created with swizzles
---
-- Creates a new 4D vector. Vectors are immutable and can not be changed after creation.