diff --git a/source/lua/internal.hpp b/source/lua/internal.hpp new file mode 100644 index 0000000..485faff --- /dev/null +++ b/source/lua/internal.hpp @@ -0,0 +1,17 @@ +// +// Created by orange on 07.03.2026. +// +#pragma once +#ifdef OMATH_ENABLE_LUA +#include + +namespace omath::lua::detail +{ + void register_vec2(sol::table& omath_table); + void register_vec3(sol::table& omath_table); + void register_vec4(sol::table& omath_table); + void register_color(sol::table& omath_table); + void register_shared_types(sol::table& omath_table); + void register_engines(sol::table& omath_table); +} +#endif diff --git a/source/lua/lua.cpp b/source/lua/lua.cpp index 4f374b0..200aee1 100644 --- a/source/lua/lua.cpp +++ b/source/lua/lua.cpp @@ -3,428 +3,8 @@ // #ifdef OMATH_ENABLE_LUA #include "lua.hpp" +#include "internal.hpp" #include "omath/lua/lua.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -namespace -{ - void register_vec2(sol::table& omath_table) - { - using Vec2f = omath::Vector2; - - omath_table.new_usertype( - "Vec2", sol::constructors(), - - "x", &Vec2f::x, "y", &Vec2f::y, - - sol::meta_function::addition, sol::resolve(&Vec2f::operator+), - sol::meta_function::subtraction, sol::resolve(&Vec2f::operator-), - sol::meta_function::unary_minus, sol::resolve(&Vec2f::operator-), - sol::meta_function::equal_to, &Vec2f::operator==, - sol::meta_function::less_than, sol::resolve(&Vec2f::operator<), - sol::meta_function::less_than_or_equal_to, sol::resolve(&Vec2f::operator<=), - sol::meta_function::to_string, - [](const Vec2f& v) { return std::format("Vec2({}, {})", v.x, v.y); }, - - sol::meta_function::multiplication, - sol::overload(sol::resolve(&Vec2f::operator*), - [](const float s, const Vec2f& v) { return v * s; }), - - sol::meta_function::division, - sol::resolve(&Vec2f::operator/), - - "length", &Vec2f::length, - "length_sqr", &Vec2f::length_sqr, - "normalized", &Vec2f::normalized, - "dot", &Vec2f::dot, - "distance_to", &Vec2f::distance_to, - "distance_to_sqr", &Vec2f::distance_to_sqr, - "sum", &Vec2f::sum, - - "abs", - [](const Vec2f& v) - { - Vec2f copy = v; - copy.abs(); - return copy; - }); - } - - void register_vec4(sol::table& omath_table) - { - using Vec4f = omath::Vector4; - - omath_table.new_usertype( - "Vec4", sol::constructors(), - - "x", &Vec4f::x, "y", &Vec4f::y, "z", &Vec4f::z, "w", &Vec4f::w, - - sol::meta_function::addition, sol::resolve(&Vec4f::operator+), - sol::meta_function::subtraction, sol::resolve(&Vec4f::operator-), - sol::meta_function::unary_minus, sol::resolve(&Vec4f::operator-), - sol::meta_function::equal_to, &Vec4f::operator==, - sol::meta_function::less_than, sol::resolve(&Vec4f::operator<), - sol::meta_function::less_than_or_equal_to, sol::resolve(&Vec4f::operator<=), - sol::meta_function::to_string, - [](const Vec4f& v) { return std::format("Vec4({}, {}, {}, {})", v.x, v.y, v.z, v.w); }, - - sol::meta_function::multiplication, - sol::overload(sol::resolve(&Vec4f::operator*), - sol::resolve(&Vec4f::operator*), - [](const float s, const Vec4f& v) { return v * s; }), - - sol::meta_function::division, - sol::overload(sol::resolve(&Vec4f::operator/), - sol::resolve(&Vec4f::operator/)), - - "length", &Vec4f::length, - "length_sqr", &Vec4f::length_sqr, - "dot", &Vec4f::dot, - "sum", &Vec4f::sum, - - "abs", - [](const Vec4f& v) - { - Vec4f copy = v; - copy.abs(); - return copy; - }, - - "clamp", - [](Vec4f& v, float mn, float mx) - { - v.clamp(mn, mx); - return v; - }); - } - - void register_vec3(sol::table& omath_table) - { - using Vec3f = omath::Vector3; - - omath_table.new_usertype( - "Vec3", sol::constructors(), - - "x", &Vec3f::x, "y", &Vec3f::y, "z", &Vec3f::z, - - sol::meta_function::addition, sol::resolve(&Vec3f::operator+), - sol::meta_function::subtraction, sol::resolve(&Vec3f::operator-), - sol::meta_function::unary_minus, sol::resolve(&Vec3f::operator-), - sol::meta_function::equal_to, &Vec3f::operator==, sol::meta_function::less_than, - sol::resolve(&Vec3f::operator<), sol::meta_function::less_than_or_equal_to, - sol::resolve(&Vec3f::operator<=), sol::meta_function::to_string, - [](const Vec3f& v) { return std::format("Vec3({}, {}, {})", v.x, v.y, v.z); }, - - sol::meta_function::multiplication, - sol::overload(sol::resolve(&Vec3f::operator*), - sol::resolve(&Vec3f::operator*), - [](const float s, const Vec3f& v) { return v * s; }), - - sol::meta_function::division, - sol::overload(sol::resolve(&Vec3f::operator/), - sol::resolve(&Vec3f::operator/)), - - "length", &Vec3f::length, "length_2d", &Vec3f::length_2d, "length_sqr", &Vec3f::length_sqr, - "normalized", &Vec3f::normalized, "dot", &Vec3f::dot, "cross", &Vec3f::cross, "distance_to", - &Vec3f::distance_to, "distance_to_sqr", &Vec3f::distance_to_sqr, "sum", - sol::resolve(&Vec3f::sum), "sum_2d", &Vec3f::sum_2d, "point_to_same_direction", - &Vec3f::point_to_same_direction, "as_array", &Vec3f::as_array, - - "abs", - [](const Vec3f& v) - { - Vec3f copy = v; - copy.abs(); - return copy; - }, - - "angle_between", - [](const Vec3f& self, - const Vec3f& other) -> std::tuple, sol::optional> - { - auto result = self.angle_between(other); - if (result) - return std::make_tuple(sol::optional(result->as_degrees()), - sol::optional(sol::nullopt)); - return std::make_tuple(sol::optional(sol::nullopt), - sol::optional("impossible angle (zero-length vector)")); - }, - - "is_perpendicular", - [](const Vec3f& self, const Vec3f& other, sol::optional eps) - { return self.is_perpendicular(other, eps.value_or(0.0001f)); }, - - "as_table", - [](const Vec3f& v, sol::this_state s) -> sol::table - { - sol::state_view lua(s); - sol::table t = lua.create_table(); - t["x"] = v.x; - t["y"] = v.y; - t["z"] = v.z; - return t; - }); - } - static std::string projection_error_to_string(omath::projection::Error e) - { - switch (e) - { - case omath::projection::Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS: - return "world position is out of screen bounds"; - case omath::projection::Error::INV_VIEW_PROJ_MAT_DET_EQ_ZERO: - return "inverse view-projection matrix determinant is zero"; - } - return "unknown error"; - } - - void register_color(sol::table& omath_table) - { - omath_table.new_usertype( - "Color", - sol::factories( - [](float r, float g, float b, float a) { return omath::Color(r, g, b, a); }, - []() { return omath::Color(); }), - - "from_rgba", [](uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - return omath::Color::from_rgba(r, g, b, a); - }, - "from_hsv", sol::overload( - [](float h, float s, float v) { return omath::Color::from_hsv(h, s, v); }, - [](const omath::Hsv& hsv) { return omath::Color::from_hsv(hsv); }), - "red", []() { return omath::Color::red(); }, - "green", []() { return omath::Color::green(); }, - "blue", []() { return omath::Color::blue(); }, - - "r", sol::property([](const omath::Color& c) { return c.value().x; }), - "g", sol::property([](const omath::Color& c) { return c.value().y; }), - "b", sol::property([](const omath::Color& c) { return c.value().z; }), - "a", sol::property([](const omath::Color& c) { return c.value().w; }), - - "to_hsv", &omath::Color::to_hsv, - "set_hue", &omath::Color::set_hue, - "set_saturation", &omath::Color::set_saturation, - "set_value", &omath::Color::set_value, - "blend", &omath::Color::blend, - - sol::meta_function::to_string, &omath::Color::to_string); - - omath_table.new_usertype( - "Hsv", sol::constructors(), - "hue", &omath::Hsv::hue, - "saturation", &omath::Hsv::saturation, - "value", &omath::Hsv::value); - } - - template - void register_angle(sol::table& table, const char* name) - { - table.new_usertype( - name, sol::no_constructor, - "from_degrees", &AngleType::from_degrees, - "from_radians", &AngleType::from_radians, - "as_degrees", &AngleType::as_degrees, - "as_radians", &AngleType::as_radians, - "sin", &AngleType::sin, - "cos", &AngleType::cos, - "tan", &AngleType::tan, - "cot", &AngleType::cot, - sol::meta_function::addition, - [](const AngleType& a, const AngleType& b) - { return AngleType::from_degrees(a.as_degrees() + b.as_degrees()); }, - sol::meta_function::subtraction, - [](const AngleType& a, const AngleType& b) - { return AngleType::from_degrees(a.as_degrees() - b.as_degrees()); }, - sol::meta_function::unary_minus, - [](const AngleType& a) { return AngleType::from_degrees(-a.as_degrees()); }, - sol::meta_function::equal_to, - [](const AngleType& a, const AngleType& b) { return a == b; }, - sol::meta_function::to_string, - [](const AngleType& a) { return std::format("{}deg", a.as_degrees()); }); - } - - // ---- Canonical shared C++ type aliases ---------------------------------- - // Each unique template instantiation must be registered exactly once. - - using PitchAngle90 = omath::Angle; - using PitchAngle89 = omath::Angle; - using SharedYawRoll = omath::Angle; - using SharedFoV = omath::Angle; - using ViewAngles90 = omath::ViewAngles; - using ViewAngles89 = omath::ViewAngles; - - // Register every shared C++ type exactly once under omath._types - void register_shared_types(sol::table& omath_table) - { - auto t = omath_table["_types"].get_or_create(); - - register_angle(t, "PitchAngle90"); - register_angle(t, "PitchAngle89"); - register_angle(t, "YawRoll"); - register_angle(t, "FieldOfView"); - - t.new_usertype( - "ViewPort", - sol::factories([](float w, float h) { return omath::projection::ViewPort{w, h}; }), - "width", &omath::projection::ViewPort::m_width, - "height", &omath::projection::ViewPort::m_height, - "aspect_ratio", &omath::projection::ViewPort::aspect_ratio); - - t.new_usertype( - "ViewAngles90", - sol::factories([](PitchAngle90 p, SharedYawRoll y, SharedYawRoll r) - { return ViewAngles90{p, y, r}; }), - "pitch", &ViewAngles90::pitch, - "yaw", &ViewAngles90::yaw, - "roll", &ViewAngles90::roll); - - t.new_usertype( - "ViewAngles89", - sol::factories([](PitchAngle89 p, SharedYawRoll y, SharedYawRoll r) - { return ViewAngles89{p, y, r}; }), - "pitch", &ViewAngles89::pitch, - "yaw", &ViewAngles89::yaw, - "roll", &ViewAngles89::roll); - } - - // Set aliases in an engine subtable pointing to the already-registered shared types - template - void set_engine_aliases(sol::table& engine_table, sol::table& types) - { - if constexpr (std::is_same_v) - engine_table["PitchAngle"] = types["PitchAngle90"]; - else - engine_table["PitchAngle"] = types["PitchAngle89"]; - - engine_table["YawAngle"] = types["YawRoll"]; - engine_table["RollAngle"] = types["YawRoll"]; - engine_table["FieldOfView"] = types["FieldOfView"]; - engine_table["ViewPort"] = types["ViewPort"]; - - if constexpr (std::is_same_v) - engine_table["ViewAngles"] = types["ViewAngles90"]; - else - engine_table["ViewAngles"] = types["ViewAngles89"]; - } - - // Register an engine: alias shared types, register unique Camera - template - void register_engine(sol::table& omath_table, const char* subtable_name) - { - using PitchAngle = typename EngineTraits::PitchAngle; - using ViewAngles = typename EngineTraits::ViewAngles; - using Camera = typename EngineTraits::Camera; - - auto engine_table = omath_table[subtable_name].get_or_create(); - auto types = omath_table["_types"].get(); - - set_engine_aliases(engine_table, types); - - engine_table.new_usertype( - "Camera", - sol::constructors&, const ViewAngles&, - const omath::projection::ViewPort&, - const omath::projection::FieldOfView&, float, float)>(), - "look_at", &Camera::look_at, - "get_forward", &Camera::get_forward, - "get_right", &Camera::get_right, - "get_up", &Camera::get_up, - "get_origin", &Camera::get_origin, - "get_view_angles", &Camera::get_view_angles, - "get_near_plane", &Camera::get_near_plane, - "get_far_plane", &Camera::get_far_plane, - "get_field_of_view", &Camera::get_field_of_view, - "set_origin", &Camera::set_origin, - "set_view_angles", &Camera::set_view_angles, - "set_view_port", &Camera::set_view_port, - "set_field_of_view", &Camera::set_field_of_view, - "set_near_plane", &Camera::set_near_plane, - "set_far_plane", &Camera::set_far_plane, - - "world_to_screen", - [](const Camera& cam, const omath::Vector3& pos) - -> std::tuple>, sol::optional> - { - auto result = cam.world_to_screen(pos); - if (result) return {*result, sol::nullopt}; - return {sol::nullopt, projection_error_to_string(result.error())}; - }, - - "screen_to_world", - [](const Camera& cam, const omath::Vector3& pos) - -> std::tuple>, sol::optional> - { - auto result = cam.screen_to_world(pos); - if (result) return {*result, sol::nullopt}; - return {sol::nullopt, projection_error_to_string(result.error())}; - }); - } - - // ---- Engine trait structs ----------------------------------------------- - - struct OpenGLEngineTraits - { - using PitchAngle = omath::opengl_engine::PitchAngle; - using ViewAngles = omath::opengl_engine::ViewAngles; - using Camera = omath::opengl_engine::Camera; - }; - struct FrostbiteEngineTraits - { - using PitchAngle = omath::frostbite_engine::PitchAngle; - using ViewAngles = omath::frostbite_engine::ViewAngles; - using Camera = omath::frostbite_engine::Camera; - }; - struct IWEngineTraits - { - using PitchAngle = omath::iw_engine::PitchAngle; - using ViewAngles = omath::iw_engine::ViewAngles; - using Camera = omath::iw_engine::Camera; - }; - struct SourceEngineTraits - { - using PitchAngle = omath::source_engine::PitchAngle; - using ViewAngles = omath::source_engine::ViewAngles; - using Camera = omath::source_engine::Camera; - }; - struct UnityEngineTraits - { - using PitchAngle = omath::unity_engine::PitchAngle; - using ViewAngles = omath::unity_engine::ViewAngles; - using Camera = omath::unity_engine::Camera; - }; - struct UnrealEngineTraits - { - using PitchAngle = omath::unreal_engine::PitchAngle; - using ViewAngles = omath::unreal_engine::ViewAngles; - using Camera = omath::unreal_engine::Camera; - }; - struct CryEngineTraits - { - using PitchAngle = omath::cry_engine::PitchAngle; - using ViewAngles = omath::cry_engine::ViewAngles; - using Camera = omath::cry_engine::Camera; - }; -} // namespace namespace omath::lua { @@ -434,18 +14,12 @@ namespace omath::lua auto omath_table = lua["omath"].get_or_create(); - register_vec2(omath_table); - register_vec3(omath_table); - register_vec4(omath_table); - register_color(omath_table); - register_shared_types(omath_table); - register_engine(omath_table, "opengl"); - register_engine(omath_table, "frostbite"); - register_engine(omath_table, "iw"); - register_engine(omath_table, "source"); - register_engine(omath_table, "unity"); - register_engine(omath_table, "unreal"); - register_engine(omath_table, "cry"); + detail::register_vec2(omath_table); + detail::register_vec3(omath_table); + detail::register_vec4(omath_table); + detail::register_color(omath_table); + detail::register_shared_types(omath_table); + detail::register_engines(omath_table); } } // namespace omath::lua -#endif \ No newline at end of file +#endif diff --git a/source/lua/lua_color.cpp b/source/lua/lua_color.cpp new file mode 100644 index 0000000..1a408b2 --- /dev/null +++ b/source/lua/lua_color.cpp @@ -0,0 +1,48 @@ +// +// Created by orange on 07.03.2026. +// +#ifdef OMATH_ENABLE_LUA +#include "internal.hpp" +#include + +namespace omath::lua::detail +{ + void register_color(sol::table& omath_table) + { + omath_table.new_usertype( + "Color", + sol::factories( + [](float r, float g, float b, float a) { return omath::Color(r, g, b, a); }, + []() { return omath::Color(); }), + + "from_rgba", [](uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + return omath::Color::from_rgba(r, g, b, a); + }, + "from_hsv", sol::overload( + [](float h, float s, float v) { return omath::Color::from_hsv(h, s, v); }, + [](const omath::Hsv& hsv) { return omath::Color::from_hsv(hsv); }), + "red", []() { return omath::Color::red(); }, + "green", []() { return omath::Color::green(); }, + "blue", []() { return omath::Color::blue(); }, + + "r", sol::property([](const omath::Color& c) { return c.value().x; }), + "g", sol::property([](const omath::Color& c) { return c.value().y; }), + "b", sol::property([](const omath::Color& c) { return c.value().z; }), + "a", sol::property([](const omath::Color& c) { return c.value().w; }), + + "to_hsv", &omath::Color::to_hsv, + "set_hue", &omath::Color::set_hue, + "set_saturation", &omath::Color::set_saturation, + "set_value", &omath::Color::set_value, + "blend", &omath::Color::blend, + + sol::meta_function::to_string, &omath::Color::to_string); + + omath_table.new_usertype( + "Hsv", sol::constructors(), + "hue", &omath::Hsv::hue, + "saturation", &omath::Hsv::saturation, + "value", &omath::Hsv::value); + } +} // namespace omath::lua::detail +#endif diff --git a/source/lua/lua_engines.cpp b/source/lua/lua_engines.cpp new file mode 100644 index 0000000..8184fb7 --- /dev/null +++ b/source/lua/lua_engines.cpp @@ -0,0 +1,242 @@ +// +// Created by orange on 07.03.2026. +// +#ifdef OMATH_ENABLE_LUA +#include "internal.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + // ---- Canonical shared C++ type aliases ---------------------------------- + // Each unique template instantiation must be registered exactly once. + + using PitchAngle90 = omath::Angle; + using PitchAngle89 = omath::Angle; + using SharedYawRoll = omath::Angle; + using SharedFoV = omath::Angle; + using ViewAngles90 = omath::ViewAngles; + using ViewAngles89 = omath::ViewAngles; + + static std::string projection_error_to_string(omath::projection::Error e) + { + switch (e) + { + case omath::projection::Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS: + return "world position is out of screen bounds"; + case omath::projection::Error::INV_VIEW_PROJ_MAT_DET_EQ_ZERO: + return "inverse view-projection matrix determinant is zero"; + } + return "unknown error"; + } + + template + void register_angle(sol::table& table, const char* name) + { + table.new_usertype( + name, sol::no_constructor, + "from_degrees", &AngleType::from_degrees, + "from_radians", &AngleType::from_radians, + "as_degrees", &AngleType::as_degrees, + "as_radians", &AngleType::as_radians, + "sin", &AngleType::sin, + "cos", &AngleType::cos, + "tan", &AngleType::tan, + "cot", &AngleType::cot, + sol::meta_function::addition, + [](const AngleType& a, const AngleType& b) + { return AngleType::from_degrees(a.as_degrees() + b.as_degrees()); }, + sol::meta_function::subtraction, + [](const AngleType& a, const AngleType& b) + { return AngleType::from_degrees(a.as_degrees() - b.as_degrees()); }, + sol::meta_function::unary_minus, + [](const AngleType& a) { return AngleType::from_degrees(-a.as_degrees()); }, + sol::meta_function::equal_to, + [](const AngleType& a, const AngleType& b) { return a == b; }, + sol::meta_function::to_string, + [](const AngleType& a) { return std::format("{}deg", a.as_degrees()); }); + } + + // Set aliases in an engine subtable pointing to the already-registered shared types + template + void set_engine_aliases(sol::table& engine_table, sol::table& types) + { + if constexpr (std::is_same_v) + engine_table["PitchAngle"] = types["PitchAngle90"]; + else + engine_table["PitchAngle"] = types["PitchAngle89"]; + + engine_table["YawAngle"] = types["YawRoll"]; + engine_table["RollAngle"] = types["YawRoll"]; + engine_table["FieldOfView"] = types["FieldOfView"]; + engine_table["ViewPort"] = types["ViewPort"]; + + if constexpr (std::is_same_v) + engine_table["ViewAngles"] = types["ViewAngles90"]; + else + engine_table["ViewAngles"] = types["ViewAngles89"]; + } + + // Register an engine: alias shared types, register unique Camera + template + void register_engine(sol::table& omath_table, const char* subtable_name) + { + using PitchAngle = typename EngineTraits::PitchAngle; + using ViewAngles = typename EngineTraits::ViewAngles; + using Camera = typename EngineTraits::Camera; + + auto engine_table = omath_table[subtable_name].get_or_create(); + auto types = omath_table["_types"].get(); + + set_engine_aliases(engine_table, types); + + engine_table.new_usertype( + "Camera", + sol::constructors&, const ViewAngles&, + const omath::projection::ViewPort&, + const omath::projection::FieldOfView&, float, float)>(), + "look_at", &Camera::look_at, + "get_forward", &Camera::get_forward, + "get_right", &Camera::get_right, + "get_up", &Camera::get_up, + "get_origin", &Camera::get_origin, + "get_view_angles", &Camera::get_view_angles, + "get_near_plane", &Camera::get_near_plane, + "get_far_plane", &Camera::get_far_plane, + "get_field_of_view", &Camera::get_field_of_view, + "set_origin", &Camera::set_origin, + "set_view_angles", &Camera::set_view_angles, + "set_view_port", &Camera::set_view_port, + "set_field_of_view", &Camera::set_field_of_view, + "set_near_plane", &Camera::set_near_plane, + "set_far_plane", &Camera::set_far_plane, + + "world_to_screen", + [](const Camera& cam, const omath::Vector3& pos) + -> std::tuple>, sol::optional> + { + auto result = cam.world_to_screen(pos); + if (result) return {*result, sol::nullopt}; + return {sol::nullopt, projection_error_to_string(result.error())}; + }, + + "screen_to_world", + [](const Camera& cam, const omath::Vector3& pos) + -> std::tuple>, sol::optional> + { + auto result = cam.screen_to_world(pos); + if (result) return {*result, sol::nullopt}; + return {sol::nullopt, projection_error_to_string(result.error())}; + }); + } + + // ---- Engine trait structs ----------------------------------------------- + + struct OpenGLEngineTraits + { + using PitchAngle = omath::opengl_engine::PitchAngle; + using ViewAngles = omath::opengl_engine::ViewAngles; + using Camera = omath::opengl_engine::Camera; + }; + struct FrostbiteEngineTraits + { + using PitchAngle = omath::frostbite_engine::PitchAngle; + using ViewAngles = omath::frostbite_engine::ViewAngles; + using Camera = omath::frostbite_engine::Camera; + }; + struct IWEngineTraits + { + using PitchAngle = omath::iw_engine::PitchAngle; + using ViewAngles = omath::iw_engine::ViewAngles; + using Camera = omath::iw_engine::Camera; + }; + struct SourceEngineTraits + { + using PitchAngle = omath::source_engine::PitchAngle; + using ViewAngles = omath::source_engine::ViewAngles; + using Camera = omath::source_engine::Camera; + }; + struct UnityEngineTraits + { + using PitchAngle = omath::unity_engine::PitchAngle; + using ViewAngles = omath::unity_engine::ViewAngles; + using Camera = omath::unity_engine::Camera; + }; + struct UnrealEngineTraits + { + using PitchAngle = omath::unreal_engine::PitchAngle; + using ViewAngles = omath::unreal_engine::ViewAngles; + using Camera = omath::unreal_engine::Camera; + }; + struct CryEngineTraits + { + using PitchAngle = omath::cry_engine::PitchAngle; + using ViewAngles = omath::cry_engine::ViewAngles; + using Camera = omath::cry_engine::Camera; + }; +} // namespace + +namespace omath::lua::detail +{ + void register_shared_types(sol::table& omath_table) + { + auto t = omath_table["_types"].get_or_create(); + + register_angle(t, "PitchAngle90"); + register_angle(t, "PitchAngle89"); + register_angle(t, "YawRoll"); + register_angle(t, "FieldOfView"); + + t.new_usertype( + "ViewPort", + sol::factories([](float w, float h) { return omath::projection::ViewPort{w, h}; }), + "width", &omath::projection::ViewPort::m_width, + "height", &omath::projection::ViewPort::m_height, + "aspect_ratio", &omath::projection::ViewPort::aspect_ratio); + + t.new_usertype( + "ViewAngles90", + sol::factories([](PitchAngle90 p, SharedYawRoll y, SharedYawRoll r) + { return ViewAngles90{p, y, r}; }), + "pitch", &ViewAngles90::pitch, + "yaw", &ViewAngles90::yaw, + "roll", &ViewAngles90::roll); + + t.new_usertype( + "ViewAngles89", + sol::factories([](PitchAngle89 p, SharedYawRoll y, SharedYawRoll r) + { return ViewAngles89{p, y, r}; }), + "pitch", &ViewAngles89::pitch, + "yaw", &ViewAngles89::yaw, + "roll", &ViewAngles89::roll); + } + + void register_engines(sol::table& omath_table) + { + register_engine(omath_table, "opengl"); + register_engine(omath_table, "frostbite"); + register_engine(omath_table, "iw"); + register_engine(omath_table, "source"); + register_engine(omath_table, "unity"); + register_engine(omath_table, "unreal"); + register_engine(omath_table, "cry"); + } +} // namespace omath::lua::detail +#endif diff --git a/source/lua/lua_vec2.cpp b/source/lua/lua_vec2.cpp new file mode 100644 index 0000000..058090f --- /dev/null +++ b/source/lua/lua_vec2.cpp @@ -0,0 +1,52 @@ +// +// Created by orange on 07.03.2026. +// +#ifdef OMATH_ENABLE_LUA +#include "internal.hpp" +#include + +namespace omath::lua::detail +{ + void register_vec2(sol::table& omath_table) + { + using Vec2f = omath::Vector2; + + omath_table.new_usertype( + "Vec2", sol::constructors(), + + "x", &Vec2f::x, "y", &Vec2f::y, + + sol::meta_function::addition, sol::resolve(&Vec2f::operator+), + sol::meta_function::subtraction, sol::resolve(&Vec2f::operator-), + sol::meta_function::unary_minus, sol::resolve(&Vec2f::operator-), + sol::meta_function::equal_to, &Vec2f::operator==, + sol::meta_function::less_than, sol::resolve(&Vec2f::operator<), + sol::meta_function::less_than_or_equal_to, sol::resolve(&Vec2f::operator<=), + sol::meta_function::to_string, + [](const Vec2f& v) { return std::format("Vec2({}, {})", v.x, v.y); }, + + sol::meta_function::multiplication, + sol::overload(sol::resolve(&Vec2f::operator*), + [](const float s, const Vec2f& v) { return v * s; }), + + sol::meta_function::division, + sol::resolve(&Vec2f::operator/), + + "length", &Vec2f::length, + "length_sqr", &Vec2f::length_sqr, + "normalized", &Vec2f::normalized, + "dot", &Vec2f::dot, + "distance_to", &Vec2f::distance_to, + "distance_to_sqr", &Vec2f::distance_to_sqr, + "sum", &Vec2f::sum, + + "abs", + [](const Vec2f& v) + { + Vec2f copy = v; + copy.abs(); + return copy; + }); + } +} // namespace omath::lua::detail +#endif diff --git a/source/lua/lua_vec3.cpp b/source/lua/lua_vec3.cpp new file mode 100644 index 0000000..e6cc37d --- /dev/null +++ b/source/lua/lua_vec3.cpp @@ -0,0 +1,78 @@ +// +// Created by orange on 07.03.2026. +// +#ifdef OMATH_ENABLE_LUA +#include "internal.hpp" +#include + +namespace omath::lua::detail +{ + void register_vec3(sol::table& omath_table) + { + using Vec3f = omath::Vector3; + + omath_table.new_usertype( + "Vec3", sol::constructors(), + + "x", &Vec3f::x, "y", &Vec3f::y, "z", &Vec3f::z, + + sol::meta_function::addition, sol::resolve(&Vec3f::operator+), + sol::meta_function::subtraction, sol::resolve(&Vec3f::operator-), + sol::meta_function::unary_minus, sol::resolve(&Vec3f::operator-), + sol::meta_function::equal_to, &Vec3f::operator==, sol::meta_function::less_than, + sol::resolve(&Vec3f::operator<), sol::meta_function::less_than_or_equal_to, + sol::resolve(&Vec3f::operator<=), sol::meta_function::to_string, + [](const Vec3f& v) { return std::format("Vec3({}, {}, {})", v.x, v.y, v.z); }, + + sol::meta_function::multiplication, + sol::overload(sol::resolve(&Vec3f::operator*), + sol::resolve(&Vec3f::operator*), + [](const float s, const Vec3f& v) { return v * s; }), + + sol::meta_function::division, + sol::overload(sol::resolve(&Vec3f::operator/), + sol::resolve(&Vec3f::operator/)), + + "length", &Vec3f::length, "length_2d", &Vec3f::length_2d, "length_sqr", &Vec3f::length_sqr, + "normalized", &Vec3f::normalized, "dot", &Vec3f::dot, "cross", &Vec3f::cross, "distance_to", + &Vec3f::distance_to, "distance_to_sqr", &Vec3f::distance_to_sqr, "sum", + sol::resolve(&Vec3f::sum), "sum_2d", &Vec3f::sum_2d, "point_to_same_direction", + &Vec3f::point_to_same_direction, "as_array", &Vec3f::as_array, + + "abs", + [](const Vec3f& v) + { + Vec3f copy = v; + copy.abs(); + return copy; + }, + + "angle_between", + [](const Vec3f& self, + const Vec3f& other) -> std::tuple, sol::optional> + { + auto result = self.angle_between(other); + if (result) + return std::make_tuple(sol::optional(result->as_degrees()), + sol::optional(sol::nullopt)); + return std::make_tuple(sol::optional(sol::nullopt), + sol::optional("impossible angle (zero-length vector)")); + }, + + "is_perpendicular", + [](const Vec3f& self, const Vec3f& other, sol::optional eps) + { return self.is_perpendicular(other, eps.value_or(0.0001f)); }, + + "as_table", + [](const Vec3f& v, sol::this_state s) -> sol::table + { + sol::state_view lua(s); + sol::table t = lua.create_table(); + t["x"] = v.x; + t["y"] = v.y; + t["z"] = v.z; + return t; + }); + } +} // namespace omath::lua::detail +#endif diff --git a/source/lua/lua_vec4.cpp b/source/lua/lua_vec4.cpp new file mode 100644 index 0000000..4d26dd8 --- /dev/null +++ b/source/lua/lua_vec4.cpp @@ -0,0 +1,58 @@ +// +// Created by orange on 07.03.2026. +// +#ifdef OMATH_ENABLE_LUA +#include "internal.hpp" +#include + +namespace omath::lua::detail +{ + void register_vec4(sol::table& omath_table) + { + using Vec4f = omath::Vector4; + + omath_table.new_usertype( + "Vec4", sol::constructors(), + + "x", &Vec4f::x, "y", &Vec4f::y, "z", &Vec4f::z, "w", &Vec4f::w, + + sol::meta_function::addition, sol::resolve(&Vec4f::operator+), + sol::meta_function::subtraction, sol::resolve(&Vec4f::operator-), + sol::meta_function::unary_minus, sol::resolve(&Vec4f::operator-), + sol::meta_function::equal_to, &Vec4f::operator==, + sol::meta_function::less_than, sol::resolve(&Vec4f::operator<), + sol::meta_function::less_than_or_equal_to, sol::resolve(&Vec4f::operator<=), + sol::meta_function::to_string, + [](const Vec4f& v) { return std::format("Vec4({}, {}, {}, {})", v.x, v.y, v.z, v.w); }, + + sol::meta_function::multiplication, + sol::overload(sol::resolve(&Vec4f::operator*), + sol::resolve(&Vec4f::operator*), + [](const float s, const Vec4f& v) { return v * s; }), + + sol::meta_function::division, + sol::overload(sol::resolve(&Vec4f::operator/), + sol::resolve(&Vec4f::operator/)), + + "length", &Vec4f::length, + "length_sqr", &Vec4f::length_sqr, + "dot", &Vec4f::dot, + "sum", &Vec4f::sum, + + "abs", + [](const Vec4f& v) + { + Vec4f copy = v; + copy.abs(); + return copy; + }, + + "clamp", + [](Vec4f& v, float mn, float mx) + { + v.clamp(mn, mx); + return v; + }); + } +} // namespace omath::lua::detail +#endif