mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-08-03 23:36:59 -04:00
Merge branch 'cpputil2lua' into 'master'
Move some util to lua See merge request OpenMW/openmw!4750
This commit is contained in:
commit
c0276b6890
@ -9,22 +9,33 @@ namespace
|
|||||||
{
|
{
|
||||||
using namespace testing;
|
using namespace testing;
|
||||||
|
|
||||||
|
struct LuaUtilPackageTest : Test
|
||||||
|
{
|
||||||
|
LuaUtil::LuaState mLuaState{ nullptr, nullptr };
|
||||||
|
|
||||||
|
LuaUtilPackageTest()
|
||||||
|
{
|
||||||
|
mLuaState.addInternalLibSearchPath(
|
||||||
|
std::filesystem::path{ OPENMW_PROJECT_SOURCE_DIR } / "components" / "lua");
|
||||||
|
sol::state_view sol = mLuaState.unsafeState();
|
||||||
|
sol["util"] = LuaUtil::initUtilPackage(sol);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T get(sol::state& lua, const std::string& luaCode)
|
T get(sol::state_view& lua, const std::string& luaCode)
|
||||||
{
|
{
|
||||||
return lua.safe_script("return " + luaCode).get<T>();
|
return lua.safe_script("return " + luaCode).get<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getAsString(sol::state& lua, std::string luaCode)
|
std::string getAsString(sol::state_view& lua, std::string luaCode)
|
||||||
{
|
{
|
||||||
return LuaUtil::toString(lua.safe_script("return " + luaCode));
|
return LuaUtil::toString(lua.safe_script("return " + luaCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LuaUtilPackageTest, Vector2)
|
TEST_F(LuaUtilPackageTest, Vector2)
|
||||||
{
|
{
|
||||||
sol::state lua;
|
sol::state_view lua = mLuaState.unsafeState();
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string);
|
|
||||||
lua["util"] = LuaUtil::initUtilPackage(lua);
|
|
||||||
lua.safe_script("v = util.vector2(3, 4)");
|
lua.safe_script("v = util.vector2(3, 4)");
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), 3);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), 3);
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 4);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 4);
|
||||||
@ -55,11 +66,9 @@ namespace
|
|||||||
EXPECT_TRUE(get<bool>(lua, "swizzle['01'] == util.vector2(0, 1) and swizzle['0y'] == util.vector2(0, 2)"));
|
EXPECT_TRUE(get<bool>(lua, "swizzle['01'] == util.vector2(0, 1) and swizzle['0y'] == util.vector2(0, 2)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LuaUtilPackageTest, Vector3)
|
TEST_F(LuaUtilPackageTest, Vector3)
|
||||||
{
|
{
|
||||||
sol::state lua;
|
sol::state_view lua = mLuaState.unsafeState();
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string);
|
|
||||||
lua["util"] = LuaUtil::initUtilPackage(lua);
|
|
||||||
lua.safe_script("v = util.vector3(5, 12, 13)");
|
lua.safe_script("v = util.vector3(5, 12, 13)");
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), 5);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), 5);
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 12);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 12);
|
||||||
@ -94,11 +103,9 @@ namespace
|
|||||||
get<bool>(lua, "swizzle['001'] == util.vector3(0, 0, 1) and swizzle['0yx'] == util.vector3(0, 2, 1)"));
|
get<bool>(lua, "swizzle['001'] == util.vector3(0, 0, 1) and swizzle['0yx'] == util.vector3(0, 2, 1)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LuaUtilPackageTest, Vector4)
|
TEST_F(LuaUtilPackageTest, Vector4)
|
||||||
{
|
{
|
||||||
sol::state lua;
|
sol::state_view lua = mLuaState.unsafeState();
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string);
|
|
||||||
lua["util"] = LuaUtil::initUtilPackage(lua);
|
|
||||||
lua.safe_script("v = util.vector4(5, 12, 13, 15)");
|
lua.safe_script("v = util.vector4(5, 12, 13, 15)");
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), 5);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), 5);
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 12);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 12);
|
||||||
@ -136,11 +143,9 @@ namespace
|
|||||||
lua, "swizzle['0001'] == util.vector4(0, 0, 0, 1) and swizzle['0yx1'] == util.vector4(0, 2, 1, 1)"));
|
lua, "swizzle['0001'] == util.vector4(0, 0, 0, 1) and swizzle['0yx1'] == util.vector4(0, 2, 1, 1)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LuaUtilPackageTest, Color)
|
TEST_F(LuaUtilPackageTest, Color)
|
||||||
{
|
{
|
||||||
sol::state lua;
|
sol::state_view lua = mLuaState.unsafeState();
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string);
|
|
||||||
lua["util"] = LuaUtil::initUtilPackage(lua);
|
|
||||||
lua.safe_script("brown = util.color.rgba(0.75, 0.25, 0, 1)");
|
lua.safe_script("brown = util.color.rgba(0.75, 0.25, 0, 1)");
|
||||||
EXPECT_EQ(get<std::string>(lua, "tostring(brown)"), "(0.75, 0.25, 0, 1)");
|
EXPECT_EQ(get<std::string>(lua, "tostring(brown)"), "(0.75, 0.25, 0, 1)");
|
||||||
lua.safe_script("blue = util.color.rgb(0, 1, 0, 1)");
|
lua.safe_script("blue = util.color.rgb(0, 1, 0, 1)");
|
||||||
@ -155,11 +160,9 @@ namespace
|
|||||||
EXPECT_TRUE(get<bool>(lua, "red:asRgb() == util.vector3(1, 0, 0)"));
|
EXPECT_TRUE(get<bool>(lua, "red:asRgb() == util.vector3(1, 0, 0)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LuaUtilPackageTest, Transform)
|
TEST_F(LuaUtilPackageTest, Transform)
|
||||||
{
|
{
|
||||||
sol::state lua;
|
sol::state_view lua = mLuaState.unsafeState();
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string);
|
|
||||||
lua["util"] = LuaUtil::initUtilPackage(lua);
|
|
||||||
lua["T"] = lua["util"]["transform"];
|
lua["T"] = lua["util"]["transform"];
|
||||||
lua["v"] = lua["util"]["vector3"];
|
lua["v"] = lua["util"]["vector3"];
|
||||||
EXPECT_ERROR(lua.safe_script("T.identity = nil"), "attempt to index");
|
EXPECT_ERROR(lua.safe_script("T.identity = nil"), "attempt to index");
|
||||||
@ -191,11 +194,9 @@ namespace
|
|||||||
EXPECT_LT(get<float>(lua, "(rz_move_rx:inverse() * v(0, 1, 2) - v(1, 2, 3)):length()"), 1e-6);
|
EXPECT_LT(get<float>(lua, "(rz_move_rx:inverse() * v(0, 1, 2) - v(1, 2, 3)):length()"), 1e-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(LuaUtilPackageTest, UtilityFunctions)
|
TEST_F(LuaUtilPackageTest, UtilityFunctions)
|
||||||
{
|
{
|
||||||
sol::state lua;
|
sol::state_view lua = mLuaState.unsafeState();
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string);
|
|
||||||
lua["util"] = LuaUtil::initUtilPackage(lua);
|
|
||||||
lua.safe_script("v = util.vector2(1, 0):rotate(math.rad(120))");
|
lua.safe_script("v = util.vector2(1, 0):rotate(math.rad(120))");
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), -0.5f);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.x"), -0.5f);
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 0.86602539f);
|
EXPECT_FLOAT_EQ(get<float>(lua, "v.y"), 0.86602539f);
|
||||||
@ -203,6 +204,10 @@ namespace
|
|||||||
EXPECT_FLOAT_EQ(get<float>(lua, "util.clamp(0.1, 0, 1.5)"), 0.1f);
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.clamp(0.1, 0, 1.5)"), 0.1f);
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "util.clamp(-0.1, 0, 1.5)"), 0);
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.clamp(-0.1, 0, 1.5)"), 0);
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "util.clamp(2.1, 0, 1.5)"), 1.5f);
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.clamp(2.1, 0, 1.5)"), 1.5f);
|
||||||
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.round(2.1)"), 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.round(-2.1)"), -2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.remap(5, 0, 10, 0, 100)"), 50.0f);
|
||||||
|
EXPECT_FLOAT_EQ(get<float>(lua, "util.remap(-5, 0, 10, 0, 100)"), -50.0f);
|
||||||
lua.safe_script("t = util.makeReadOnly({x = 1})");
|
lua.safe_script("t = util.makeReadOnly({x = 1})");
|
||||||
EXPECT_FLOAT_EQ(get<float>(lua, "t.x"), 1);
|
EXPECT_FLOAT_EQ(get<float>(lua, "t.x"), 1);
|
||||||
EXPECT_ERROR(lua.safe_script("t.y = 2"), "userdata value");
|
EXPECT_ERROR(lua.safe_script("t.y = 2"), "userdata value");
|
||||||
|
@ -61,6 +61,7 @@ add_component_dir (lua
|
|||||||
luastate scriptscontainer asyncpackage utilpackage serialization configuration l10n storage utf8
|
luastate scriptscontainer asyncpackage utilpackage serialization configuration l10n storage utf8
|
||||||
shapes/box inputactions yamlloader scripttracker luastateptr
|
shapes/box inputactions yamlloader scripttracker luastateptr
|
||||||
)
|
)
|
||||||
|
copy_resource_file("lua/util.lua" "${OPENMW_RESOURCES_ROOT}" "resources/lua_libs/util.lua")
|
||||||
|
|
||||||
add_component_dir (l10n
|
add_component_dir (l10n
|
||||||
messagebundles manager
|
messagebundles manager
|
||||||
|
21
components/lua/util.lua
Normal file
21
components/lua/util.lua
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
function M.remap(value, min, max, newMin, newMax)
|
||||||
|
return newMin + (value - min) * (newMax - newMin) / (max - min)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.round(value)
|
||||||
|
return value >= 0 and math.floor(value + 0.5) or math.ceil(value - 0.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.clamp(value, low, high)
|
||||||
|
return value < low and low or (value > high and high or value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.normalizeAngle(angle)
|
||||||
|
local fullTurns = angle / (2 * math.pi) + 0.5
|
||||||
|
return (fullTurns - math.floor(fullTurns) - 0.5) * (2 * math.pi)
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
@ -352,16 +352,14 @@ namespace LuaUtil
|
|||||||
return std::make_tuple(angles.z(), angles.y(), angles.x());
|
return std::make_tuple(angles.z(), angles.y(), angles.x());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sol::function luaUtilLoader = lua["loadInternalLib"]("util");
|
||||||
|
sol::table utils = luaUtilLoader();
|
||||||
|
for (const auto& [key, value] : utils)
|
||||||
|
util[key.as<std::string>()] = value;
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
util["clamp"] = [](double value, double from, double to) { return std::clamp(value, from, to); };
|
|
||||||
// NOTE: `util["clamp"] = std::clamp<float>` causes error 'AddressSanitizer: stack-use-after-scope'
|
|
||||||
util["normalizeAngle"] = &Misc::normalizeAngle;
|
|
||||||
util["makeReadOnly"] = [](const sol::table& tbl) { return makeReadOnly(tbl, /*strictIndex=*/false); };
|
util["makeReadOnly"] = [](const sol::table& tbl) { return makeReadOnly(tbl, /*strictIndex=*/false); };
|
||||||
util["makeStrictReadOnly"] = [](const sol::table& tbl) { return makeReadOnly(tbl, /*strictIndex=*/true); };
|
util["makeStrictReadOnly"] = [](const sol::table& tbl) { return makeReadOnly(tbl, /*strictIndex=*/true); };
|
||||||
util["remap"] = [](double value, double min, double max, double newMin, double newMax) {
|
|
||||||
return newMin + (value - min) * (newMax - newMin) / (max - min);
|
|
||||||
};
|
|
||||||
util["round"] = [](double value) { return round(value); };
|
|
||||||
|
|
||||||
if (lua["bit32"] != sol::nil)
|
if (lua["bit32"] != sol::nil)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user