added more lua stuff

This commit is contained in:
2026-05-16 10:33:06 +03:00
parent 7f88bf8b21
commit a4fac65b7c
17 changed files with 2201 additions and 1 deletions
+5
View File
@@ -17,8 +17,13 @@ namespace omath::lua
register_vec2(omath_table);
register_vec3(omath_table);
register_vec4(omath_table);
register_matrices(omath_table);
register_quaternion(omath_table);
register_color(omath_table);
register_hud(omath_table);
register_triangle(omath_table);
register_3d_primitives(omath_table);
register_collision(omath_table);
register_shared_types(omath_table);
register_engines(omath_table);
register_pattern_scan(omath_table);
+287
View File
@@ -0,0 +1,287 @@
//
// Created by orange on 07.03.2026.
//
#ifdef OMATH_ENABLE_LUA
#include "omath/lua/lua.hpp"
#include <omath/3d_primitives/aabb.hpp>
#include <omath/3d_primitives/obb.hpp>
#include <omath/collision/collider_interface.hpp>
#include <omath/collision/epa_algorithm.hpp>
#include <omath/collision/gjk_algorithm.hpp>
#include <omath/collision/line_tracer.hpp>
#include <omath/linear_algebra/triangle.hpp>
#include <omath/linear_algebra/vector3.hpp>
#include <sol/sol.hpp>
#include <algorithm>
#include <stdexcept>
#include <vector>
namespace
{
using Vec3f = omath::Vector3<float>;
using Triangle3f = omath::Triangle<Vec3f>;
using Ray3f = omath::collision::Ray<Vec3f>;
using LineTracer3f = omath::collision::LineTracer<Ray3f>;
using Aabbf = omath::primitives::Aabb<float>;
using Obbf = omath::primitives::Obb<float>;
class LuaConvexCollider final : public omath::collision::ColliderInterface<Vec3f>
{
public:
using VectorType = Vec3f;
explicit LuaConvexCollider(std::vector<Vec3f> vertices, const Vec3f& origin = {})
: m_vertices(std::move(vertices)), m_origin(origin)
{
if (m_vertices.empty())
throw std::invalid_argument("convex collider must contain at least one vertex");
}
[[nodiscard]]
Vec3f find_abs_furthest_vertex_position(const Vec3f& direction) const override
{
const auto furthest = std::ranges::max_element(
m_vertices,
[&direction](const Vec3f& first, const Vec3f& second)
{
return first.dot(direction) < second.dot(direction);
});
return m_origin + *furthest;
}
[[nodiscard]]
const Vec3f& get_origin() const override
{
return m_origin;
}
void set_origin(const Vec3f& new_origin) override
{
m_origin = new_origin;
}
[[nodiscard]]
std::size_t vertex_count() const noexcept
{
return m_vertices.size();
}
[[nodiscard]]
const std::vector<Vec3f>& vertices() const noexcept
{
return m_vertices;
}
private:
std::vector<Vec3f> m_vertices;
Vec3f m_origin;
};
std::vector<Vec3f> vec3_table_to_vector(const sol::table& points)
{
std::vector<Vec3f> result;
for (std::size_t i = 1;; ++i)
{
const auto point = points[i].get<sol::optional<Vec3f>>();
if (!point)
break;
result.push_back(*point);
}
return result;
}
sol::table vec3_array_to_table(const auto& points, sol::this_state state)
{
sol::state_view lua(state);
sol::table result = lua.create_table(static_cast<int>(points.size()), 0);
for (std::size_t i = 0; i < points.size(); ++i)
result[i + 1] = points[i];
return result;
}
Vec3f aabb_top(const Aabbf& aabb, const omath::primitives::UpAxis axis)
{
switch (axis)
{
case omath::primitives::UpAxis::X:
return aabb.top<omath::primitives::UpAxis::X>();
case omath::primitives::UpAxis::Y:
return aabb.top<omath::primitives::UpAxis::Y>();
case omath::primitives::UpAxis::Z:
return aabb.top<omath::primitives::UpAxis::Z>();
}
std::unreachable();
}
Vec3f aabb_bottom(const Aabbf& aabb, const omath::primitives::UpAxis axis)
{
switch (axis)
{
case omath::primitives::UpAxis::X:
return aabb.bottom<omath::primitives::UpAxis::X>();
case omath::primitives::UpAxis::Y:
return aabb.bottom<omath::primitives::UpAxis::Y>();
case omath::primitives::UpAxis::Z:
return aabb.bottom<omath::primitives::UpAxis::Z>();
}
std::unreachable();
}
bool ray_hits_triangle(const Ray3f& ray, const Triangle3f& triangle)
{
return !(LineTracer3f::get_ray_hit_point(ray, triangle) == ray.end);
}
bool ray_hits_aabb(const Ray3f& ray, const Aabbf& aabb)
{
return !(LineTracer3f::get_ray_hit_point(ray, aabb) == ray.end);
}
bool ray_hits_obb(const Ray3f& ray, const Obbf& obb)
{
return !(LineTracer3f::get_ray_hit_point(ray, obb) == ray.end);
}
} // namespace
namespace omath::lua
{
void LuaInterpreter::register_3d_primitives(sol::table& omath_table)
{
auto primitives_table = omath_table["primitives"].get_or_create<sol::table>();
primitives_table.new_enum("UpAxis", "X", omath::primitives::UpAxis::X, "Y", omath::primitives::UpAxis::Y, "Z",
omath::primitives::UpAxis::Z);
primitives_table.new_usertype<Aabbf>(
"Aabb",
sol::factories([]() { return Aabbf{}; },
[](const Vec3f& min, const Vec3f& max) { return Aabbf{min, max}; }),
"min", &Aabbf::min, "max", &Aabbf::max, "center", &Aabbf::center, "extents", &Aabbf::extents,
"top",
[](const Aabbf& aabb, sol::optional<omath::primitives::UpAxis> axis)
{
return aabb_top(aabb, axis.value_or(omath::primitives::UpAxis::Y));
},
"bottom",
[](const Aabbf& aabb, sol::optional<omath::primitives::UpAxis> axis)
{
return aabb_bottom(aabb, axis.value_or(omath::primitives::UpAxis::Y));
},
"is_collide", &Aabbf::is_collide,
"as_table",
[](const Aabbf& aabb, sol::this_state state) -> sol::table
{
sol::state_view lua(state);
sol::table result = lua.create_table();
result["min"] = aabb.min;
result["max"] = aabb.max;
return result;
});
primitives_table.new_usertype<Obbf>(
"Obb",
sol::factories(
[]()
{
return Obbf{};
},
[](const Vec3f& center, const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z,
const Vec3f& half_extents)
{
return Obbf{center, axis_x, axis_y, axis_z, half_extents};
}),
"center", &Obbf::center, "axis_x", &Obbf::axis_x, "axis_y", &Obbf::axis_y, "axis_z", &Obbf::axis_z,
"half_extents", &Obbf::half_extents,
"vertices",
[](const Obbf& obb, sol::this_state state)
{
return vec3_array_to_table(obb.vertices(), state);
});
}
void LuaInterpreter::register_collision(sol::table& omath_table)
{
auto collision_table = omath_table["collision"].get_or_create<sol::table>();
collision_table.new_usertype<Ray3f>(
"Ray",
sol::factories([]() { return Ray3f{}; },
[](const Vec3f& start, const Vec3f& end) { return Ray3f{start, end}; },
[](const Vec3f& start, const Vec3f& end, const bool infinite_length)
{ return Ray3f{start, end, infinite_length}; }),
"start", &Ray3f::start, "end", &Ray3f::end, "infinite_length", &Ray3f::infinite_length,
"direction_vector", &Ray3f::direction_vector, "direction_vector_normalized",
&Ray3f::direction_vector_normalized);
collision_table.new_usertype<LuaConvexCollider>(
"ConvexCollider",
sol::factories([](const sol::table& vertices) { return LuaConvexCollider(vec3_table_to_vector(vertices)); },
[](const sol::table& vertices, const Vec3f& origin)
{ return LuaConvexCollider(vec3_table_to_vector(vertices), origin); }),
"find_abs_furthest_vertex_position", &LuaConvexCollider::find_abs_furthest_vertex_position,
"get_origin", &LuaConvexCollider::get_origin, "set_origin", &LuaConvexCollider::set_origin,
"vertex_count", &LuaConvexCollider::vertex_count,
"vertices",
[](const LuaConvexCollider& collider, sol::this_state state)
{
return vec3_array_to_table(collider.vertices(), state);
});
collision_table.new_usertype<LineTracer3f>(
"LineTracer", sol::no_constructor, "can_trace_line", &LineTracer3f::can_trace_line,
"get_ray_hit_point",
sol::overload(
[](const Ray3f& ray, const Triangle3f& triangle)
{
return LineTracer3f::get_ray_hit_point(ray, triangle);
},
[](const Ray3f& ray, const Aabbf& aabb)
{
return LineTracer3f::get_ray_hit_point(ray, aabb);
},
[](const Ray3f& ray, const Obbf& obb)
{
return LineTracer3f::get_ray_hit_point(ray, obb);
}),
"ray_hits_triangle", &ray_hits_triangle, "ray_hits_aabb", &ray_hits_aabb, "ray_hits_obb",
&ray_hits_obb);
collision_table["gjk_support_vertex"] =
[](const LuaConvexCollider& collider_a, const LuaConvexCollider& collider_b, const Vec3f& direction)
{ return omath::collision::GjkAlgorithm<LuaConvexCollider>::find_support_vertex(collider_a, collider_b, direction); };
collision_table["gjk_collide"] = [](const LuaConvexCollider& collider_a, const LuaConvexCollider& collider_b)
{ return omath::collision::GjkAlgorithm<LuaConvexCollider>::is_collide(collider_a, collider_b); };
collision_table["epa_solve"] = [](const LuaConvexCollider& collider_a, const LuaConvexCollider& collider_b,
sol::this_state state) -> sol::object
{
using Gjk = omath::collision::GjkAlgorithm<LuaConvexCollider>;
using Epa = omath::collision::Epa<LuaConvexCollider>;
sol::state_view lua(state);
const auto gjk = Gjk::is_collide_with_simplex_info(collider_a, collider_b);
if (!gjk.hit)
return sol::nil;
const auto epa = Epa::solve(collider_a, collider_b, gjk.simplex);
if (!epa)
return sol::nil;
sol::table result = lua.create_table();
result["normal"] = epa->normal;
result["penetration_vector"] = epa->penetration_vector;
result["depth"] = epa->depth;
result["iterations"] = epa->iterations;
result["num_vertices"] = epa->num_vertices;
result["num_faces"] = epa->num_faces;
return sol::make_object(lua, result);
};
}
} // namespace omath::lua
#endif
+27
View File
@@ -14,6 +14,8 @@
#include <omath/engines/unreal_engine/camera.hpp>
#include <sol/sol.hpp>
#include <string_view>
#include <type_traits>
#include <utility>
namespace
{
@@ -85,6 +87,7 @@ namespace
using PitchAngle = typename EngineTraits::PitchAngle;
using ViewAngles = typename EngineTraits::ViewAngles;
using Camera = typename EngineTraits::Camera;
using Mat4X4 = std::remove_cvref_t<decltype(std::declval<const Camera&>().get_view_matrix())>;
auto engine_table = omath_table[subtable_name].get_or_create<sol::table>();
auto types = omath_table["_types"].get<sol::table>();
@@ -104,6 +107,30 @@ namespace
&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,
"get_view_matrix",
[](const Camera& cam) -> Mat4X4
{
return cam.get_view_matrix();
},
"get_projection_matrix",
[](const Camera& cam) -> Mat4X4
{
return cam.get_projection_matrix();
},
"get_view_projection_matrix",
[](const Camera& cam) -> Mat4X4
{
return cam.get_view_projection_matrix();
},
"extract_projection_params",
[](const Mat4X4& projection_matrix)
{
const auto params = Camera::extract_projection_params(projection_matrix);
return std::make_tuple(params.fov, params.aspect_ratio);
},
"calc_view_angles_from_view_matrix", &Camera::calc_view_angles_from_view_matrix,
"calc_origin_from_view_matrix", &Camera::calc_origin_from_view_matrix,
"world_to_screen",
[](const Camera& cam, const omath::Vector3<ArithmeticType>& pos)
-> std::tuple<sol::optional<omath::Vector3<ArithmeticType>>, sol::optional<std::string>>
+495
View File
@@ -0,0 +1,495 @@
//
// Created by orange on 07.03.2026.
//
#ifdef OMATH_ENABLE_LUA
#include "omath/lua/lua.hpp"
#include <omath/hud/canvas_box.hpp>
#include <omath/hud/entity_overlay.hpp>
#include <sol/sol.hpp>
#include <any>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
namespace
{
class LuaHudRenderer final : public omath::hud::HudRendererInterface
{
public:
explicit LuaHudRenderer(sol::table callbacks): m_callbacks(std::move(callbacks))
{
}
void add_line(const omath::Vector2<float>& line_start, const omath::Vector2<float>& line_end,
const omath::Color& color, const float thickness) override
{
call_optional("add_line", line_start, line_end, color, thickness);
}
void add_polyline(const std::span<const omath::Vector2<float>>& vertexes, const omath::Color& color,
const float thickness) override
{
call_optional("add_polyline", make_points_table(vertexes), color, thickness);
}
void add_filled_polyline(const std::span<const omath::Vector2<float>>& vertexes,
const omath::Color& color) override
{
call_optional("add_filled_polyline", make_points_table(vertexes), color);
}
void add_rectangle(const omath::Vector2<float>& min, const omath::Vector2<float>& max,
const omath::Color& color) override
{
call_optional("add_rectangle", min, max, color);
}
void add_filled_rectangle(const omath::Vector2<float>& min, const omath::Vector2<float>& max,
const omath::Color& color) override
{
call_optional("add_filled_rectangle", min, max, color);
}
void add_circle(const omath::Vector2<float>& center, const float radius, const omath::Color& color,
const float thickness, const int segments) override
{
call_optional("add_circle", center, radius, color, thickness, segments);
}
void add_filled_circle(const omath::Vector2<float>& center, const float radius, const omath::Color& color,
const int segments) override
{
call_optional("add_filled_circle", center, radius, color, segments);
}
void add_arc(const omath::Vector2<float>& center, const float radius, const float a_min, const float a_max,
const omath::Color& color, const float thickness, const int segments) override
{
call_optional("add_arc", center, radius, a_min, a_max, color, thickness, segments);
}
void add_image(const std::any& texture_id, const omath::Vector2<float>& min, const omath::Vector2<float>& max,
const omath::Color& tint) override
{
const auto callback = callback_for("add_image");
if (!callback)
return;
sol::object texture = sol::nil;
if (const auto lua_object = std::any_cast<sol::object>(&texture_id))
texture = *lua_object;
auto result = (*callback)(texture, min, max, tint);
if (!result.valid())
throw sol::error(result);
}
void add_text(const omath::Vector2<float>& position, const omath::Color& color,
const std::string_view& text) override
{
call_optional("add_text", position, color, std::string{text});
}
[[nodiscard]]
omath::Vector2<float> calc_text_size(const std::string_view& text) override
{
const auto callback = callback_for("calc_text_size");
if (!callback)
return {};
auto result = (*callback)(std::string{text});
if (!result.valid())
throw sol::error(result);
return result.get<omath::Vector2<float>>();
}
private:
sol::main_table m_callbacks;
[[nodiscard]]
sol::optional<sol::protected_function> callback_for(const char* name) const
{
const sol::object callback = m_callbacks[name];
if (!callback.valid() || callback == sol::nil)
return sol::nullopt;
return callback.as<sol::protected_function>();
}
template<class... Args>
void call_optional(const char* name, Args&&... args) const
{
const auto callback = callback_for(name);
if (!callback)
return;
auto result = (*callback)(std::forward<Args>(args)...);
if (!result.valid())
throw sol::error(result);
}
[[nodiscard]]
sol::table make_points_table(const std::span<const omath::Vector2<float>>& vertexes) const
{
sol::state_view lua(m_callbacks.lua_state());
sol::table points = lua.create_table(static_cast<int>(vertexes.size()), 0);
for (std::size_t i = 0; i < vertexes.size(); ++i)
points[i + 1] = vertexes[i];
return points;
}
};
[[nodiscard]]
omath::Color transparent_black()
{
return {0.f, 0.f, 0.f, 0.f};
}
[[nodiscard]]
omath::Color opaque_white()
{
return {1.f, 1.f, 1.f, 1.f};
}
[[nodiscard]]
omath::hud::EntityOverlay make_overlay(const omath::Vector2<float>& top, const omath::Vector2<float>& bottom,
const std::shared_ptr<LuaHudRenderer>& renderer)
{
if (!renderer)
throw std::invalid_argument("hud renderer must not be nil");
return {top, bottom, renderer};
}
[[nodiscard]]
std::any texture_id_from_lua_object(const sol::object& texture_id)
{
return texture_id;
}
std::vector<omath::Vector2<float>> points_from_table(const sol::table& points)
{
std::vector<omath::Vector2<float>> result;
for (std::size_t i = 1;; ++i)
{
const auto point = points[i].get<sol::optional<omath::Vector2<float>>>();
if (!point)
break;
result.push_back(*point);
}
return result;
}
} // namespace
namespace omath::lua
{
void LuaInterpreter::register_hud(sol::table& omath_table)
{
auto hud_table = omath_table["hud"].get_or_create<sol::table>();
hud_table.new_usertype<omath::hud::CanvasBox>(
"CanvasBox",
sol::factories([](const omath::Vector2<float>& top, const omath::Vector2<float>& bottom)
{ return omath::hud::CanvasBox(top, bottom); },
[](const omath::Vector2<float>& top, const omath::Vector2<float>& bottom,
const float ratio) { return omath::hud::CanvasBox(top, bottom, ratio); }),
"top_left_corner", &omath::hud::CanvasBox::top_left_corner, "top_right_corner",
&omath::hud::CanvasBox::top_right_corner, "bottom_left_corner",
&omath::hud::CanvasBox::bottom_left_corner, "bottom_right_corner",
&omath::hud::CanvasBox::bottom_right_corner,
"as_table",
[](const omath::hud::CanvasBox& box, sol::this_state s) -> sol::table
{
sol::state_view lua(s);
sol::table t = lua.create_table(4, 0);
const auto points = box.as_array();
for (std::size_t i = 0; i < points.size(); ++i)
t[i + 1] = points[i];
return t;
});
hud_table.new_usertype<LuaHudRenderer>(
"Renderer",
sol::factories([](const sol::table& callbacks)
{ return std::make_shared<LuaHudRenderer>(callbacks); }),
"add_line", &LuaHudRenderer::add_line,
"add_polyline",
[](LuaHudRenderer& renderer, const sol::table& points, const omath::Color& color,
const float thickness)
{
const auto vertices = points_from_table(points);
renderer.add_polyline({vertices.data(), vertices.size()}, color, thickness);
},
"add_filled_polyline",
[](LuaHudRenderer& renderer, const sol::table& points, const omath::Color& color)
{
const auto vertices = points_from_table(points);
renderer.add_filled_polyline({vertices.data(), vertices.size()}, color);
},
"add_rectangle", &LuaHudRenderer::add_rectangle, "add_filled_rectangle",
&LuaHudRenderer::add_filled_rectangle, "add_circle",
[](LuaHudRenderer& renderer, const omath::Vector2<float>& center, const float radius,
const omath::Color& color, const float thickness, sol::optional<int> segments)
{
renderer.add_circle(center, radius, color, thickness, segments.value_or(0));
},
"add_filled_circle",
[](LuaHudRenderer& renderer, const omath::Vector2<float>& center, const float radius,
const omath::Color& color, sol::optional<int> segments)
{
renderer.add_filled_circle(center, radius, color, segments.value_or(0));
},
"add_arc",
[](LuaHudRenderer& renderer, const omath::Vector2<float>& center, const float radius,
const float a_min, const float a_max, const omath::Color& color, const float thickness,
sol::optional<int> segments)
{
renderer.add_arc(center, radius, a_min, a_max, color, thickness, segments.value_or(0));
},
"add_image",
[](LuaHudRenderer& renderer, const sol::object& texture_id, const omath::Vector2<float>& min,
const omath::Vector2<float>& max, sol::optional<omath::Color> tint)
{
renderer.add_image(texture_id_from_lua_object(texture_id), min, max,
tint.value_or(opaque_white()));
},
"add_text", &LuaHudRenderer::add_text, "calc_text_size", &LuaHudRenderer::calc_text_size);
hud_table.new_usertype<omath::hud::EntityOverlay>(
"EntityOverlay",
sol::factories(&make_overlay),
"add_2d_box",
[](omath::hud::EntityOverlay& overlay, const omath::Color& box_color,
sol::optional<omath::Color> fill_color, sol::optional<float> thickness) -> omath::hud::EntityOverlay&
{
return overlay.add_2d_box(box_color, fill_color.value_or(transparent_black()),
thickness.value_or(1.f));
},
"add_cornered_2d_box",
[](omath::hud::EntityOverlay& overlay, const omath::Color& box_color,
sol::optional<omath::Color> fill_color, sol::optional<float> corner_ratio_len,
sol::optional<float> thickness) -> omath::hud::EntityOverlay&
{
return overlay.add_cornered_2d_box(box_color, fill_color.value_or(transparent_black()),
corner_ratio_len.value_or(0.2f), thickness.value_or(1.f));
},
"add_dashed_box",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, sol::optional<float> dash_len,
sol::optional<float> gap_len, sol::optional<float> thickness) -> omath::hud::EntityOverlay&
{
return overlay.add_dashed_box(color, dash_len.value_or(8.f), gap_len.value_or(5.f),
thickness.value_or(1.f));
},
"add_right_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float width, const float ratio,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_right_bar(color, outline_color, bg_color, width, ratio, offset.value_or(5.f));
},
"add_left_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float width, const float ratio,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_left_bar(color, outline_color, bg_color, width, ratio, offset.value_or(5.f));
},
"add_top_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float height, const float ratio,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_top_bar(color, outline_color, bg_color, height, ratio, offset.value_or(5.f));
},
"add_bottom_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float height, const float ratio,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_bottom_bar(color, outline_color, bg_color, height, ratio, offset.value_or(5.f));
},
"add_right_dashed_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float width, const float ratio, const float dash_len,
const float gap_len, sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_right_dashed_bar(color, outline_color, bg_color, width, ratio, dash_len, gap_len,
offset.value_or(5.f));
},
"add_left_dashed_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float width, const float ratio, const float dash_len,
const float gap_len, sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_left_dashed_bar(color, outline_color, bg_color, width, ratio, dash_len, gap_len,
offset.value_or(5.f));
},
"add_top_dashed_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float height, const float ratio, const float dash_len,
const float gap_len, sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_top_dashed_bar(color, outline_color, bg_color, height, ratio, dash_len, gap_len,
offset.value_or(5.f));
},
"add_bottom_dashed_bar",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& outline_color,
const omath::Color& bg_color, const float height, const float ratio, const float dash_len,
const float gap_len, sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_bottom_dashed_bar(color, outline_color, bg_color, height, ratio, dash_len,
gap_len, offset.value_or(5.f));
},
"add_right_label",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
{
return overlay.add_right_label(color, offset, outlined, text);
},
"add_left_label",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
{
return overlay.add_left_label(color, offset, outlined, text);
},
"add_top_label",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
{
return overlay.add_top_label(color, offset, outlined, text);
},
"add_bottom_label",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
{
return overlay.add_bottom_label(color, offset, outlined, text);
},
"add_centered_top_label",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
{
return overlay.add_centered_top_label(color, offset, outlined, text);
},
"add_centered_bottom_label",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const float offset,
const bool outlined, const std::string& text) -> omath::hud::EntityOverlay&
{
return overlay.add_centered_bottom_label(color, offset, outlined, text);
},
"add_right_space_vertical", &omath::hud::EntityOverlay::add_right_space_vertical,
"add_right_space_horizontal", &omath::hud::EntityOverlay::add_right_space_horizontal,
"add_left_space_vertical", &omath::hud::EntityOverlay::add_left_space_vertical,
"add_left_space_horizontal", &omath::hud::EntityOverlay::add_left_space_horizontal,
"add_top_space_vertical", &omath::hud::EntityOverlay::add_top_space_vertical,
"add_top_space_horizontal", &omath::hud::EntityOverlay::add_top_space_horizontal,
"add_bottom_space_vertical", &omath::hud::EntityOverlay::add_bottom_space_vertical,
"add_bottom_space_horizontal", &omath::hud::EntityOverlay::add_bottom_space_horizontal,
"add_right_progress_ring",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& bg,
const float radius, const float ratio, sol::optional<float> thickness, sol::optional<float> offset,
sol::optional<int> segments) -> omath::hud::EntityOverlay&
{
return overlay.add_right_progress_ring(color, bg, radius, ratio, thickness.value_or(2.f),
offset.value_or(5.f), segments.value_or(0));
},
"add_left_progress_ring",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& bg,
const float radius, const float ratio, sol::optional<float> thickness, sol::optional<float> offset,
sol::optional<int> segments) -> omath::hud::EntityOverlay&
{
return overlay.add_left_progress_ring(color, bg, radius, ratio, thickness.value_or(2.f),
offset.value_or(5.f), segments.value_or(0));
},
"add_top_progress_ring",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& bg,
const float radius, const float ratio, sol::optional<float> thickness, sol::optional<float> offset,
sol::optional<int> segments) -> omath::hud::EntityOverlay&
{
return overlay.add_top_progress_ring(color, bg, radius, ratio, thickness.value_or(2.f),
offset.value_or(5.f), segments.value_or(0));
},
"add_bottom_progress_ring",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color, const omath::Color& bg,
const float radius, const float ratio, sol::optional<float> thickness, sol::optional<float> offset,
sol::optional<int> segments) -> omath::hud::EntityOverlay&
{
return overlay.add_bottom_progress_ring(color, bg, radius, ratio, thickness.value_or(2.f),
offset.value_or(5.f), segments.value_or(0));
},
"add_right_icon",
[](omath::hud::EntityOverlay& overlay, const sol::object& texture_id, const float width,
const float height, sol::optional<omath::Color> tint,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_right_icon(texture_id_from_lua_object(texture_id), width, height,
tint.value_or(opaque_white()), offset.value_or(5.f));
},
"add_left_icon",
[](omath::hud::EntityOverlay& overlay, const sol::object& texture_id, const float width,
const float height, sol::optional<omath::Color> tint,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_left_icon(texture_id_from_lua_object(texture_id), width, height,
tint.value_or(opaque_white()), offset.value_or(5.f));
},
"add_top_icon",
[](omath::hud::EntityOverlay& overlay, const sol::object& texture_id, const float width,
const float height, sol::optional<omath::Color> tint,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_top_icon(texture_id_from_lua_object(texture_id), width, height,
tint.value_or(opaque_white()), offset.value_or(5.f));
},
"add_bottom_icon",
[](omath::hud::EntityOverlay& overlay, const sol::object& texture_id, const float width,
const float height, sol::optional<omath::Color> tint,
sol::optional<float> offset) -> omath::hud::EntityOverlay&
{
return overlay.add_bottom_icon(texture_id_from_lua_object(texture_id), width, height,
tint.value_or(opaque_white()), offset.value_or(5.f));
},
"add_snap_line", &omath::hud::EntityOverlay::add_snap_line, "add_skeleton",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color,
sol::optional<float> thickness) -> omath::hud::EntityOverlay&
{
return overlay.add_skeleton(color, thickness.value_or(1.f));
},
"add_scan_marker",
[](omath::hud::EntityOverlay& overlay, const omath::Color& color,
sol::optional<omath::Color> outline, sol::optional<float> outline_thickness)
-> omath::hud::EntityOverlay&
{
return overlay.contents(omath::hud::widget::ScanMarker{
color, outline.value_or(transparent_black()), outline_thickness.value_or(1.f)});
},
"add_aim_dot",
[](omath::hud::EntityOverlay& overlay, const omath::Vector2<float>& position,
const omath::Color& color, sol::optional<float> radius) -> omath::hud::EntityOverlay&
{
return overlay.contents(omath::hud::widget::AimDot{position, color, radius.value_or(3.f)});
},
"add_projectile_aim",
[](omath::hud::EntityOverlay& overlay, const omath::Vector2<float>& position,
const omath::Color& color, sol::optional<float> size, sol::optional<float> line_size,
sol::optional<omath::hud::widget::ProjectileAim::Figure> figure) -> omath::hud::EntityOverlay&
{
return overlay.contents(omath::hud::widget::ProjectileAim{
position, color, size.value_or(3.f), line_size.value_or(1.f),
figure.value_or(omath::hud::widget::ProjectileAim::Figure::SQUARE)});
});
hud_table.new_enum("ProjectileAimFigure", "CIRCLE", omath::hud::widget::ProjectileAim::Figure::CIRCLE,
"SQUARE", omath::hud::widget::ProjectileAim::Figure::SQUARE);
}
} // namespace omath::lua
#endif
+156
View File
@@ -0,0 +1,156 @@
//
// Created by orange on 07.03.2026.
//
#ifdef OMATH_ENABLE_LUA
#include "omath/lua/lua.hpp"
#include <omath/linear_algebra/mat.hpp>
#include <sol/sol.hpp>
#include <stdexcept>
namespace
{
template<std::size_t Limit>
std::size_t checked_index(const int index)
{
if (index < 0 || index >= static_cast<int>(Limit))
throw std::out_of_range("matrix index is out of range");
return static_cast<std::size_t>(index);
}
template<std::size_t Rows, std::size_t Columns, class Type, omath::MatStoreType StoreType>
omath::Mat<Rows, Columns, Type, StoreType> mat_from_rows(const sol::table& rows)
{
omath::Mat<Rows, Columns, Type, StoreType> result;
for (std::size_t row = 0; row < Rows; ++row)
{
const auto row_table = rows[row + 1].get<sol::optional<sol::table>>();
if (!row_table)
throw std::invalid_argument("matrix rows must be tables");
for (std::size_t column = 0; column < Columns; ++column)
{
const auto value = (*row_table)[column + 1].get<sol::optional<Type>>();
if (!value)
throw std::invalid_argument("matrix row has missing value");
result.at(row, column) = *value;
}
}
return result;
}
template<std::size_t Rows, std::size_t Columns, class Type, omath::MatStoreType StoreType>
sol::table mat_as_table(const omath::Mat<Rows, Columns, Type, StoreType>& mat, sol::this_state state)
{
sol::state_view lua(state);
sol::table rows = lua.create_table();
for (std::size_t row = 0; row < Rows; ++row)
{
sol::table row_table = lua.create_table();
for (std::size_t column = 0; column < Columns; ++column)
row_table[column + 1] = mat.at(row, column);
rows[row + 1] = row_table;
}
return rows;
}
template<std::size_t Size, class Type, omath::MatStoreType StoreType, bool RegisterMat4Helpers = false>
void register_square_mat(sol::table& omath_table, const char* name)
{
using MatType = omath::Mat<Size, Size, Type, StoreType>;
auto type = omath_table.new_usertype<MatType>(
name, sol::constructors<MatType()>(),
"from_rows", &mat_from_rows<Size, Size, Type, StoreType>, "row_count",
[]()
{
return Size;
},
"columns_count",
[]()
{
return Size;
},
"at",
[](const MatType& mat, const int row, const int column)
{
return mat.at(checked_index<Size>(row), checked_index<Size>(column));
},
"set_at",
[](MatType& mat, const int row, const int column, const Type value)
{
mat.at(checked_index<Size>(row), checked_index<Size>(column)) = value;
return mat;
},
sol::meta_function::multiplication,
sol::overload(
[](const MatType& lhs, const MatType& rhs)
{
return lhs * rhs;
},
[](const MatType& mat, const Type scalar)
{
return mat * scalar;
},
[](const Type scalar, const MatType& mat)
{
return mat * scalar;
}),
sol::meta_function::division,
[](const MatType& mat, const Type scalar)
{
return mat / scalar;
},
sol::meta_function::equal_to, &MatType::operator==, sol::meta_function::to_string, &MatType::to_string,
"transposed", &MatType::transposed, "determinant", &MatType::determinant, "sum", &MatType::sum, "clear",
&MatType::clear, "set", &MatType::set, "inverted",
[](const MatType& mat) -> sol::optional<MatType>
{
auto result = mat.inverted();
if (!result)
return sol::nullopt;
return *result;
},
"as_table", &mat_as_table<Size, Size, Type, StoreType>);
if constexpr (RegisterMat4Helpers)
{
type["to_screen_mat"] = [](const Type screen_width, const Type screen_height)
{
return MatType{
{screen_width / Type{2}, Type{0}, Type{0}, Type{0}},
{Type{0}, -screen_height / Type{2}, Type{0}, Type{0}},
{Type{0}, Type{0}, Type{1}, Type{0}},
{screen_width / Type{2}, screen_height / Type{2}, Type{0}, Type{1}},
};
};
type["translation"] = &omath::mat_translation<Type, StoreType>;
type["scale"] = &omath::mat_scale<Type, StoreType>;
type["look_at_left_handed"] = &omath::mat_look_at_left_handed<Type, StoreType>;
type["look_at_right_handed"] = &omath::mat_look_at_right_handed<Type, StoreType>;
type["perspective_left_handed_vertical_fov"] =
&omath::mat_perspective_left_handed_vertical_fov<Type, StoreType>;
type["perspective_right_handed_vertical_fov"] =
&omath::mat_perspective_right_handed_vertical_fov<Type, StoreType>;
}
}
} // namespace
namespace omath::lua
{
void LuaInterpreter::register_matrices(sol::table& omath_table)
{
register_square_mat<3, float, omath::MatStoreType::ROW_MAJOR>(omath_table, "Mat3");
register_square_mat<4, float, omath::MatStoreType::ROW_MAJOR, true>(omath_table, "Mat4");
register_square_mat<4, float, omath::MatStoreType::COLUMN_MAJOR, true>(omath_table, "Mat4ColumnMajor");
register_square_mat<4, double, omath::MatStoreType::ROW_MAJOR>(omath_table, "Mat4d");
}
} // namespace omath::lua
#endif
+95
View File
@@ -0,0 +1,95 @@
//
// Created by orange on 07.03.2026.
//
#ifdef OMATH_ENABLE_LUA
#include "omath/lua/lua.hpp"
#include <omath/linear_algebra/quaternion.hpp>
#include <sol/sol.hpp>
namespace omath::lua
{
void LuaInterpreter::register_quaternion(sol::table& omath_table)
{
using Quatf = omath::Quaternion<float>;
using Vec3f = omath::Vector3<float>;
omath_table.new_usertype<Quatf>(
"Quaternion", sol::constructors<Quatf(), Quatf(float, float, float, float)>(),
"from_axis_angle", &Quatf::from_axis_angle,
"x",
sol::property(
[](const Quatf& q)
{
return q.x;
},
[](Quatf& q, float val)
{
q.x = val;
}),
"y",
sol::property(
[](const Quatf& q)
{
return q.y;
},
[](Quatf& q, float val)
{
q.y = val;
}),
"z",
sol::property(
[](const Quatf& q)
{
return q.z;
},
[](Quatf& q, float val)
{
q.z = val;
}),
"w",
sol::property(
[](const Quatf& q)
{
return q.w;
},
[](Quatf& q, float val)
{
q.w = val;
}),
sol::meta_function::addition, sol::resolve<Quatf(const Quatf&) const>(&Quatf::operator+),
sol::meta_function::multiplication,
sol::overload(sol::resolve<Quatf(const Quatf&) const>(&Quatf::operator*),
sol::resolve<Quatf(const float&) const>(&Quatf::operator*),
[](float s, const Quatf& q)
{
return q * s;
}),
sol::meta_function::unary_minus, sol::resolve<Quatf() const>(&Quatf::operator-),
sol::meta_function::equal_to, &Quatf::operator==, sol::meta_function::to_string,
[](const Quatf& q)
{
return std::format("Quaternion({}, {}, {}, {})", q.x, q.y, q.z, q.w);
},
"conjugate", &Quatf::conjugate, "dot", &Quatf::dot, "length", &Quatf::length, "length_sqr",
&Quatf::length_sqr, "normalized", &Quatf::normalized, "inverse", &Quatf::inverse, "rotate",
sol::resolve<Vec3f(const Vec3f&) const>(&Quatf::rotate), "to_rotation_matrix3",
&Quatf::to_rotation_matrix3, "to_rotation_matrix4", &Quatf::to_rotation_matrix4,
"as_table",
[](const Quatf& q, sol::this_state s) -> sol::table
{
sol::state_view lua(s);
sol::table t = lua.create_table();
t["x"] = q.x;
t["y"] = q.y;
t["z"] = q.z;
t["w"] = q.w;
return t;
});
}
} // namespace omath::lua
#endif