diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c65282a..bd34f3b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -597,8 +597,10 @@ set(luavrlib_SOURCES "") list(APPEND luavrlib_SOURCES "lua-api/lib/src/ScriptContext.cpp" "lua-api/lib/src/ScriptState.cpp" + "lua-api/lib/src/datatypes/Vector.cpp" "lua-api/lib/include/ScriptContext.hpp" "lua-api/lib/include/ScriptState.hpp" + "lua-api/lib/include/datatypes/Vector.hpp" ) list(APPEND luavrlib_SOURCES @@ -633,6 +635,7 @@ target_link_libraries(luavrlib PUBLIC lua sol2 kananlib + glm ) unset(CMKR_TARGET) diff --git a/cmake.toml b/cmake.toml index 45a8f819..e4b4b1d0 100644 --- a/cmake.toml +++ b/cmake.toml @@ -202,7 +202,8 @@ headers = ["lua-api/lib/**.hpp", "lua-api/lib/**.h"] link-libraries = [ "lua", "sol2", - "kananlib" + "kananlib", + "glm" ] [target.LuaVR] diff --git a/lua-api/lib/include/ScriptContext.hpp b/lua-api/lib/include/ScriptContext.hpp index ebe18e07..9827a137 100644 --- a/lua-api/lib/include/ScriptContext.hpp +++ b/lua-api/lib/include/ScriptContext.hpp @@ -43,7 +43,6 @@ class ScriptContext : public std::enable_shared_from_this { } static void log(const std::string& message); - static void test_function(); template void add_callback(T1&& adder, T2&& cb) { diff --git a/lua-api/lib/include/datatypes/Vector.hpp b/lua-api/lib/include/datatypes/Vector.hpp new file mode 100644 index 00000000..40640e15 --- /dev/null +++ b/lua-api/lib/include/datatypes/Vector.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace lua::datatypes { + using Vector2f = glm::vec2; + using Vector2d = glm::dvec2; + using Vector3f = glm::vec3; + using Vector3d = glm::dvec3; + using Vector4f = glm::vec4; + using Vector4d = glm::dvec4; + + void bind_vectors(sol::state_view& lua); +} \ No newline at end of file diff --git a/lua-api/lib/src/ScriptContext.cpp b/lua-api/lib/src/ScriptContext.cpp index 53195066..f2658993 100644 --- a/lua-api/lib/src/ScriptContext.cpp +++ b/lua-api/lib/src/ScriptContext.cpp @@ -6,6 +6,8 @@ #include +#include "datatypes/Vector.hpp" + #include "ScriptContext.hpp" namespace uevr { @@ -91,10 +93,6 @@ void ScriptContext::log(const std::string& message) { API::get()->log_info("[LuaVR] %s", message.c_str()); } -void ScriptContext::test_function() { - log("Test function called!"); -} - void ScriptContext::setup_callback_bindings() { std::scoped_lock _{ m_mtx }; @@ -159,6 +157,31 @@ void ScriptContext::setup_callback_bindings() { sol::object call_function(sol::this_state s, uevr::API::UObject* self, uevr::API::UFunction* fn, sol::variadic_args args); +uevr::API::UScriptStruct* get_vector_struct() { + static auto vector_struct = []() { + const auto modern_class = uevr::API::get()->find_uobject(L"ScriptStruct /Script/CoreUObject.Vector"); + const auto old_class = modern_class == nullptr ? uevr::API::get()->find_uobject(L"ScriptStruct /Script/CoreUObject.Object.Vector") : nullptr; + + return modern_class != nullptr ? modern_class : old_class; + }(); + + return vector_struct; +} + +bool is_ue5() { + static auto cached_result = []() { + const auto c = get_vector_struct(); + + if (c == nullptr) { + return false; + } + + return c->get_struct_size() == sizeof(glm::dvec3); + }(); + + return cached_result; +} + sol::object prop_to_object(sol::this_state s, void* self, uevr::API::FProperty* desc) { const auto propc = desc->get_class(); @@ -198,6 +221,37 @@ sol::object prop_to_object(sol::this_state s, void* self, uevr::API::FProperty* } return sol::make_object(s, *(uevr::API::UClass**)((uintptr_t)self + offset)); + case L"StructProperty"_fnv: + { + const auto struct_data = (void*)((uintptr_t)self + offset); + const auto struct_desc = ((uevr::API::FStructProperty*)desc)->get_struct(); + + if (struct_desc == nullptr) { + return sol::make_object(s, sol::lua_nil); + } + + /*const auto struct_name_hash = utility::hash(struct_desc->get_fname()->to_string()); + + switch (struct_name_hash) { + case L"Vector"_fnv: + if (is_ue5()) { + return sol::make_object(s, (lua::datatypes::Vector3f*)struct_data); + } + + return sol::make_object(s, (lua::datatypes::Vector3f*)struct_data); + };*/ + + if (struct_desc == get_vector_struct()) { + if (is_ue5()) { + return sol::make_object(s, (lua::datatypes::Vector3d*)struct_data); + } + + return sol::make_object(s, (lua::datatypes::Vector3f*)struct_data); + } + + // TODO: Return a reflected struct + return sol::make_object(s, sol::lua_nil); + } case L"ArrayProperty"_fnv: { const auto inner_prop = ((uevr::API::FArrayProperty*)desc)->get_inner(); @@ -510,7 +564,7 @@ sol::object call_function(sol::this_state s, uevr::API::UObject* self, const std int ScriptContext::setup_bindings() { m_lua.registry()["uevr_context"] = this; - m_lua.set_function("test_function", ScriptContext::test_function); + lua::datatypes::bind_vectors(m_lua); m_lua.new_usertype("UEVR_PluginInitializeParam", "uevr_module", &UEVR_PluginInitializeParam::uevr_module, diff --git a/lua-api/lib/src/datatypes/Vector.cpp b/lua-api/lib/src/datatypes/Vector.cpp new file mode 100644 index 00000000..7ace25df --- /dev/null +++ b/lua-api/lib/src/datatypes/Vector.cpp @@ -0,0 +1,38 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +#include + +namespace lua::datatypes { + void bind_vectors(sol::state_view& lua) { + #define BIND_VECTOR3_LIKE(name, datatype) \ + lua.new_usertype(#name, \ + "clone", [](name& v) -> name { return v; }, \ + "x", &name::x, \ + "y", &name::y, \ + "z", &name::z, \ + "dot", [](name& v1, name& v2) { return glm::dot(v1, v2); }, \ + "cross", [](name& v1, name& v2) { return glm::cross(v1, v2); }, \ + "length", [](name& v) { return glm::length(v); }, \ + "normalize", [](name& v) { v = glm::normalize(v); }, \ + "normalized", [](name& v) { return glm::normalize(v); }, \ + "reflect", [](name& v, name& normal) { return glm::reflect(v, normal); }, \ + "refract", [](name& v, name& normal, datatype eta) { return glm::refract(v, normal, eta); }, \ + "lerp", [](name& v1, name& v2, datatype t) { return glm::lerp(v1, v2, t); }, \ + sol::meta_function::addition, [](name& lhs, name& rhs) { return lhs + rhs; }, \ + sol::meta_function::subtraction, [](name& lhs, name& rhs) { return lhs - rhs; }, \ + sol::meta_function::multiplication, [](name& lhs, datatype scalar) { return lhs * scalar; } + + #define BIND_VECTOR3_LIKE_END() \ + ); + + BIND_VECTOR3_LIKE(Vector3f, float), + sol::meta_function::construct, sol::constructors() + BIND_VECTOR3_LIKE_END(); + + BIND_VECTOR3_LIKE(Vector3d, double), + sol::meta_function::construct, sol::constructors() + BIND_VECTOR3_LIKE_END(); + } +} \ No newline at end of file