Merge branch 'swizzle_bop_boom_bazingle_v2' into 'master'

lua - add swizzling to vector types

See merge request OpenMW/openmw!4304
pull/3236/head
uramer 5 months ago
commit 2460b5f4ef

@ -49,6 +49,10 @@ namespace
EXPECT_TRUE(get<bool>(lua, "ediv0.x == math.huge and ediv0.y ~= ediv0.y")); 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(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)")); 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_TRUE(get<bool>(lua, "swizzle.y0 == util.vector2(2, 0) and swizzle.x1 == util.vector2(1, 1)"));
EXPECT_TRUE(get<bool>(lua, "swizzle['01'] == util.vector2(0, 1) and swizzle['0y'] == util.vector2(0, 2)"));
} }
TEST(LuaUtilPackageTest, Vector3) TEST(LuaUtilPackageTest, Vector3)
@ -82,6 +86,12 @@ namespace
EXPECT_TRUE(get<bool>(lua, "ediv0.z == math.huge")); 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(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)")); 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_TRUE(get<bool>(lua, "swizzle.xy0 == util.vector3(1, 2, 0) and swizzle.x11 == util.vector3(1, 1, 1)"));
EXPECT_TRUE(
get<bool>(lua, "swizzle['001'] == util.vector3(0, 0, 1) and swizzle['0yx'] == util.vector3(0, 2, 1)"));
} }
TEST(LuaUtilPackageTest, Vector4) TEST(LuaUtilPackageTest, Vector4)
@ -116,6 +126,14 @@ namespace
get<bool>(lua, "util.vector4(1, 2, 3, 4):emul(util.vector4(3, 4, 5, 6)) == util.vector4(3, 8, 15, 24)")); get<bool>(lua, "util.vector4(1, 2, 3, 4):emul(util.vector4(3, 4, 5, 6)) == util.vector4(3, 8, 15, 24)"));
EXPECT_TRUE( EXPECT_TRUE(
get<bool>(lua, "util.vector4(4, 6, 8, 9):ediv(util.vector4(2, 3, 4, 3)) == util.vector4(2, 2, 2, 3)")); 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_TRUE(
get<bool>(lua, "swizzle.xyz0 == util.vector4(1, 2, 3, 0) and swizzle.w110 == util.vector4(4, 1, 1, 0)"));
EXPECT_TRUE(get<bool>(
lua, "swizzle['0001'] == util.vector4(0, 0, 0, 1) and swizzle['0yx1'] == util.vector4(0, 2, 1, 1)"));
} }
TEST(LuaUtilPackageTest, Color) TEST(LuaUtilPackageTest, Color)

@ -56,6 +56,83 @@ namespace LuaUtil
{ {
namespace namespace
{ {
template <typename T>
float zero(const T& v)
{
return 0.f;
}
template <typename T>
float one(const T& v)
{
return 1.f;
}
template <typename T, std::size_t I>
float get(const T& v)
{
return v[I];
}
// Creates bindings for all possible permutations (repetition allowed) of x,y,z,w fields
template <typename T>
void addSwizzleFields(sol::usertype<T>& type)
{
// Generate mapping of swizzle characters to their getter functions
constexpr auto components = []() {
std::array<std::pair<char, float (*)(const T&)>, T::num_components + 2> arr;
// 0/1 Components
arr[T::num_components] = { '0', zero<T> };
arr[T::num_components + 1] = { '1', one<T> };
// x,y,z,w components
if constexpr (T::num_components > 1)
{
arr[0] = { 'x', get<T, 0> };
arr[1] = { 'y', get<T, 1> };
}
if constexpr (T::num_components > 2)
arr[2] = { 'z', get<T, 2> };
if constexpr (T::num_components > 3)
arr[3] = { 'w', get<T, 3> };
return arr;
}();
// Iterate over the permutations
for (const auto& comp1 : components)
{
// Single component swizzle
type[std::string{ comp1.first }] = sol::readonly_property([=](const T& v) { return comp1.second(v); });
for (const auto& comp2 : components)
{
// Two component swizzles
type[std::string{ comp1.first, comp2.first }]
= sol::readonly_property([=](const T& v) { return Vec2(comp1.second(v), comp2.second(v)); });
for (const auto& comp3 : components)
{
// Three component swizzles
type[std::string{ comp1.first, comp2.first, comp3.first }] = sol::readonly_property(
[=](const T& v) { return Vec3(comp1.second(v), comp2.second(v), comp3.second(v)); });
for (const auto& comp4 : components)
{
// Four component swizzles
type[std::string{ comp1.first, comp2.first, comp3.first, comp4.first }]
= sol::readonly_property([=](const T& v) {
return Vec4(comp1.second(v), comp2.second(v), comp3.second(v), comp4.second(v));
});
}
}
}
}
}
template <typename T> template <typename T>
void addVectorMethods(sol::usertype<T>& vectorType) void addVectorMethods(sol::usertype<T>& vectorType)
{ {
@ -97,6 +174,8 @@ namespace LuaUtil
ss << ")"; ss << ")";
return ss.str(); return ss.str();
}; };
addSwizzleFields(vectorType);
} }
} }
@ -108,17 +187,12 @@ namespace LuaUtil
// Lua bindings for Vec2 // Lua bindings for Vec2
util["vector2"] = [](float x, float y) { return Vec2(x, y); }; util["vector2"] = [](float x, float y) { return Vec2(x, y); };
sol::usertype<Vec2> vec2Type = lua.new_usertype<Vec2>("Vec2"); 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(); });
addVectorMethods<Vec2>(vec2Type); addVectorMethods<Vec2>(vec2Type);
vec2Type["rotate"] = &Misc::rotateVec2f; vec2Type["rotate"] = &Misc::rotateVec2f;
// Lua bindings for Vec3 // Lua bindings for Vec3
util["vector3"] = [](float x, float y, float z) { return Vec3(x, y, z); }; util["vector3"] = [](float x, float y, float z) { return Vec3(x, y, z); };
sol::usertype<Vec3> vec3Type = lua.new_usertype<Vec3>("Vec3"); sol::usertype<Vec3> vec3Type = lua.new_usertype<Vec3>("Vec3");
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(); });
addVectorMethods<Vec3>(vec3Type); addVectorMethods<Vec3>(vec3Type);
vec3Type[sol::meta_function::involution] = [](const Vec3& a, const Vec3& b) { return a ^ b; }; 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; }; vec3Type["cross"] = [](const Vec3& a, const Vec3& b) { return a ^ b; };
@ -126,10 +200,6 @@ namespace LuaUtil
// Lua bindings for Vec4 // Lua bindings for Vec4
util["vector4"] = [](float x, float y, float z, float w) { return Vec4(x, y, z, w); }; util["vector4"] = [](float x, float y, float z, float w) { return Vec4(x, y, z, w); };
sol::usertype<Vec4> vec4Type = lua.new_usertype<Vec4>("Vec4"); sol::usertype<Vec4> vec4Type = lua.new_usertype<Vec4>("Vec4");
vec4Type["x"] = sol::readonly_property([](const Vec4& v) -> float { return v.x(); });
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(); });
addVectorMethods<Vec4>(vec4Type); addVectorMethods<Vec4>(vec4Type);
// Lua bindings for Box // Lua bindings for Box
@ -334,5 +404,4 @@ namespace LuaUtil
return util; return util;
} }
} }

@ -94,6 +94,7 @@
-- @type Vector2 -- @type Vector2
-- @field #number x -- @field #number x
-- @field #number y -- @field #number y
-- @field #string xy01 swizzle support, any combination of fields can be used to construct a new vector including the 0/1 constants
-- @usage -- @usage
-- v = util.vector2(3, 4) -- v = util.vector2(3, 4)
-- v.x, v.y -- 3.0, 4.0 -- v.x, v.y -- 3.0, 4.0
@ -108,6 +109,9 @@
-- v1 - v2 -- vector subtraction -- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number -- v1 * x -- multiplication by a number
-- v1 / x -- division by a number -- v1 / x -- division by a number
-- v1.xx, v1.xyx -- swizzle with standard fields
-- v1.y1y, v1.x00 -- swizzle with 0/1 constant
-- v1['0xy'] -- swizzle with 0/1 constant starting with 0 or 1
--- ---
-- Creates a new 2D vector. Vectors are immutable and can not be changed after creation. -- Creates a new 2D vector. Vectors are immutable and can not be changed after creation.
@ -195,6 +199,7 @@
-- @field #number x -- @field #number x
-- @field #number y -- @field #number y
-- @field #number z -- @field #number z
-- @field #string xyz01 swizzle support, any combination of fields can be used to construct a new vector including the 0/1 constants
-- @usage -- @usage
-- v = util.vector3(3, 4, 5) -- v = util.vector3(3, 4, 5)
-- v.x, v.y, v.z -- 3.0, 4.0, 5.0 -- v.x, v.y, v.z -- 3.0, 4.0, 5.0
@ -210,6 +215,9 @@
-- v1 - v2 -- vector subtraction -- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number -- v1 * x -- multiplication by a number
-- v1 / x -- division by a number -- v1 / x -- division by a number
-- v1.zyz, v1.yx -- swizzle with standard fields
-- v1.w1y, v1.z0z -- swizzle with 0/1 constant
-- v1['0xy'] -- swizzle with 0/1 constant starting with 0 or 1
--- ---
-- Creates a new 3D vector. Vectors are immutable and can not be changed after creation. -- Creates a new 3D vector. Vectors are immutable and can not be changed after creation.
@ -304,19 +312,23 @@
-- @field #number y -- @field #number y
-- @field #number z -- @field #number z
-- @field #number w -- @field #number w
-- @field #string xyzw01 swizzle support, any combination of fields can be used to construct a new vector including the 0/1 constants
-- @usage -- @usage
-- v = util.vector4(3, 4, 5, 6) -- v = util.vector4(3, 4, 5, 6)
-- v.x, v.y, v.z, v.w -- 3.0, 4.0, 5.0, 6.0 -- 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)" -- str(v) -- "(3.0, 4.0, 5.0, 6.0)"
-- v:length() -- length -- v:length() -- length
-- v:length2() -- square of the length -- v:length2() -- square of the length
-- v:normalize() -- normalized vector -- v:normalize() -- normalized vector
-- v1:dot(v2) -- dot product (returns a number) -- v1:dot(v2) -- dot product (returns a number)
-- v1 * v2 -- dot product (returns a number) -- v1 * v2 -- dot product (returns a number)
-- v1 + v2 -- vector addition -- v1 + v2 -- vector addition
-- v1 - v2 -- vector subtraction -- v1 - v2 -- vector subtraction
-- v1 * x -- multiplication by a number -- v1 * x -- multiplication by a number
-- v1 / x -- division by a number -- v1 / x -- division by a number
-- v1.zyz, v1.wwwx -- swizzle with standard fields
-- v1.w1, v1.z000 -- swizzle with 0/1 constant
-- v1['000w'] -- swizzle with 0/1 constant starting with 0 or 1
--- ---
-- Creates a new 4D vector. Vectors are immutable and can not be changed after creation. -- Creates a new 4D vector. Vectors are immutable and can not be changed after creation.

Loading…
Cancel
Save