diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index 05c022f1..4a71f0c4 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -138,6 +138,32 @@ namespace imgui_desktop::gui ImGui::SliderFloat("Thick##skel", &m_skel_thickness, 0.5f, 5.f); } + if (ImGui::CollapsingHeader("Progress Ring")) + { + ImGui::Checkbox("Show##ring", &m_show_ring); + ImGui::ColorEdit4("Color##ring", reinterpret_cast(&m_ring_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("BG##ring", reinterpret_cast(&m_ring_bg), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Radius##ring", &m_ring_radius, 4.f, 30.f); + ImGui::SliderFloat("Value##ring", &m_ring_ratio, 0.f, 1.f); + ImGui::SliderFloat("Thick##ring", &m_ring_thickness, 0.5f, 6.f); + ImGui::SliderFloat("Offset##ring", &m_ring_offset, 0.f, 15.f); + } + + if (ImGui::CollapsingHeader("Scan Marker")) + { + ImGui::Checkbox("Show##scan", &m_show_scan); + ImGui::ColorEdit4("Fill##scan", reinterpret_cast(&m_scan_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("Outline##scan", reinterpret_cast(&m_scan_outline), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Thick##scan", &m_scan_outline_thickness, 0.5f, 5.f); + } + + if (ImGui::CollapsingHeader("Aim Dot")) + { + ImGui::Checkbox("Show##aim", &m_show_aim); + ImGui::ColorEdit4("Color##aim", reinterpret_cast(&m_aim_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Radius##aim", &m_aim_radius, 1.f, 10.f); + } + if (ImGui::CollapsingHeader("Snap Line")) { ImGui::Checkbox("Show##snap", &m_show_snap); @@ -166,7 +192,6 @@ namespace imgui_desktop::gui when(m_show_cornered_box, CorneredBox{omath::Color::from_rgba(255, 0, 255, 255), m_box_fill, m_corner_ratio, m_box_thickness}), when(m_show_dashed_box, DashedBox{m_dash_color, m_dash_len, m_dash_gap, m_dash_thickness}), - RightSide{ when(m_show_right_bar, bar), when(m_show_right_dashed_bar, dbar), @@ -176,6 +201,10 @@ namespace imgui_desktop::gui Label{{1.f, 0.f, 0.f, 1.f}, m_label_offset, m_outlined, "Shield: 125/125"}), when(m_show_right_labels, Label{{1.f, 0.f, 1.f, 1.f}, m_label_offset, m_outlined, "*LOCKED*"}), + + SpaceVertical{10}, + when(m_show_ring, ProgressRing{m_ring_color, m_ring_bg, m_ring_radius, m_ring_ratio, + m_ring_thickness, m_ring_offset}), }, LeftSide{ when(m_show_left_bar, bar), @@ -203,6 +232,8 @@ namespace imgui_desktop::gui when(m_show_bottom_labels, Label{omath::Color::from_rgba(200, 200, 0, 255), m_label_offset, m_outlined, "42m"}), }, + when(m_show_aim, AimDot{{m_entity_x, m_entity_top_y+40.f}, m_aim_color, m_aim_radius}), + when(m_show_scan, ScanMarker{m_scan_color, m_scan_outline, m_scan_outline_thickness}), when(m_show_skeleton, Skeleton{m_skel_color, m_skel_thickness}), when(m_show_snap, SnapLine{{vp->Size.x / 2.f, vp->Size.y}, m_snap_color, m_snap_width})); } diff --git a/examples/example_hud/gui/main_window.hpp b/examples/example_hud/gui/main_window.hpp index 6572bdf4..8b622bf2 100644 --- a/examples/example_hud/gui/main_window.hpp +++ b/examples/example_hud/gui/main_window.hpp @@ -61,6 +61,23 @@ namespace imgui_desktop::gui float m_skel_thickness = 1.f; bool m_show_skeleton = false; + // Progress ring + omath::Color m_ring_color = omath::Color::from_rgba(0, 200, 255, 255); + omath::Color m_ring_bg{0.3f, 0.3f, 0.3f, 0.5f}; + float m_ring_radius = 10.f, m_ring_ratio = 0.65f, m_ring_thickness = 2.5f, m_ring_offset = 5.f; + bool m_show_ring = false; + + // Scan marker + omath::Color m_scan_color = omath::Color::from_rgba(255, 200, 0, 150); + omath::Color m_scan_outline = omath::Color::from_rgba(255, 200, 0, 255); + float m_scan_outline_thickness = 2.f; + bool m_show_scan = false; + + // Aim dot + omath::Color m_aim_color = omath::Color::from_rgba(255, 0, 0, 255); + float m_aim_radius = 3.f; + bool m_show_aim = false; + // Snap line omath::Color m_snap_color = omath::Color::from_rgba(255, 50, 50, 255); float m_snap_width = 1.5f; diff --git a/include/omath/hud/entity_overlay.hpp b/include/omath/hud/entity_overlay.hpp index 2bfb873c..94d076c5 100644 --- a/include/omath/hud/entity_overlay.hpp +++ b/include/omath/hud/entity_overlay.hpp @@ -118,6 +118,36 @@ namespace omath::hud std::string_view{std::vformat(fmt.get(), std::make_format_args(args...))}); } + // ── Spacers ───────────────────────────────────────────────────── + EntityOverlay& add_right_space_vertical(float size); + EntityOverlay& add_right_space_horizontal(float size); + EntityOverlay& add_left_space_vertical(float size); + EntityOverlay& add_left_space_horizontal(float size); + EntityOverlay& add_top_space_vertical(float size); + EntityOverlay& add_top_space_horizontal(float size); + EntityOverlay& add_bottom_space_vertical(float size); + EntityOverlay& add_bottom_space_horizontal(float size); + + // ── Progress rings ────────────────────────────────────────────── + EntityOverlay& add_right_progress_ring(const Color& color, const Color& bg, float radius, float ratio, + float thickness = 2.f, float offset = 5.f, int segments = 0); + EntityOverlay& add_left_progress_ring(const Color& color, const Color& bg, float radius, float ratio, + float thickness = 2.f, float offset = 5.f, int segments = 0); + EntityOverlay& add_top_progress_ring(const Color& color, const Color& bg, float radius, float ratio, + float thickness = 2.f, float offset = 5.f, int segments = 0); + EntityOverlay& add_bottom_progress_ring(const Color& color, const Color& bg, float radius, float ratio, + float thickness = 2.f, float offset = 5.f, int segments = 0); + + // ── Icons ──────────────────────────────────────────────────────── + EntityOverlay& add_right_icon(const std::any& texture_id, float width, float height, + const Color& tint = Color{1.f, 1.f, 1.f, 1.f}, float offset = 5.f); + EntityOverlay& add_left_icon(const std::any& texture_id, float width, float height, + const Color& tint = Color{1.f, 1.f, 1.f, 1.f}, float offset = 5.f); + EntityOverlay& add_top_icon(const std::any& texture_id, float width, float height, + const Color& tint = Color{1.f, 1.f, 1.f, 1.f}, float offset = 5.f); + EntityOverlay& add_bottom_icon(const std::any& texture_id, float width, float height, + const Color& tint = Color{1.f, 1.f, 1.f, 1.f}, float offset = 5.f); + // ── Misc ───────────────────────────────────────────────────────── EntityOverlay& add_snap_line(const Vector2& start_pos, const Color& color, float width); @@ -151,6 +181,9 @@ namespace omath::hud void dispatch(const widget::BottomSide& bottom_side); void dispatch(const widget::Skeleton& skeleton); void dispatch(const widget::SnapLine& snap_line); + void dispatch(const widget::ScanMarker& scan_marker); + void dispatch(const widget::AimDot& aim_dot); + void draw_progress_ring(const Vector2& center, const widget::ProgressRing& ring); void draw_outlined_text(const Vector2& position, const Color& color, const std::string_view& text); void draw_dashed_line(const Vector2& from, const Vector2& to, const Color& color, float dash_len, float gap_len, float thickness) const; diff --git a/include/omath/hud/entity_overlay_widgets.hpp b/include/omath/hud/entity_overlay_widgets.hpp index 0a4b3e6a..52757bab 100644 --- a/include/omath/hud/entity_overlay_widgets.hpp +++ b/include/omath/hud/entity_overlay_widgets.hpp @@ -4,6 +4,7 @@ #pragma once #include "omath/linear_algebra/vector2.hpp" #include "omath/utility/color.hpp" +#include #include #include #include @@ -56,6 +57,21 @@ namespace omath::hud::widget float width; }; + struct ScanMarker + { + Color color; + Color outline{0.f, 0.f, 0.f, 0.f}; + float outline_thickness = 1.f; + }; + + /// Dot at an absolute screen position. + struct AimDot + { + Vector2 position; + Color color; + float radius = 3.f; + }; + // ── Side-agnostic widgets (used inside XxxSide containers) ──────────────── /// A filled bar. `size` is width for left/right sides, height for top/bottom. @@ -99,11 +115,44 @@ namespace omath::hud::widget template Centered(W) -> Centered; + /// Empty vertical gap that advances the Y cursor without drawing. + struct SpaceVertical + { + float size; + }; + + /// Empty horizontal gap that advances the X cursor without drawing. + struct SpaceHorizontal + { + float size; + }; + + struct ProgressRing + { + Color color; + Color bg{0.3f, 0.3f, 0.3f, 0.5f}; + float radius = 12.f; + float ratio; + float thickness = 2.f; + float offset = 5.f; + int segments = 32; + }; + + struct Icon + { + std::any texture_id; + float width; + float height; + Color tint{1.f, 1.f, 1.f, 1.f}; + float offset = 5.f; + }; + // ── Side widget variant ─────────────────────────────────────────────────── struct None { }; ///< No-op placeholder — used by widget::when for disabled elements. - using SideWidget = std::variant>; + using SideWidget = + std::variant, SpaceVertical, SpaceHorizontal, ProgressRing, Icon>; // ── Side containers ─────────────────────────────────────────────────────── // Storing std::initializer_list is safe here: the backing array diff --git a/include/omath/hud/hud_renderer_interface.hpp b/include/omath/hud/hud_renderer_interface.hpp index 8d625324..5a25e036 100644 --- a/include/omath/hud/hud_renderer_interface.hpp +++ b/include/omath/hud/hud_renderer_interface.hpp @@ -4,6 +4,7 @@ #pragma once #include "omath/linear_algebra/vector2.hpp" #include "omath/utility/color.hpp" +#include #include namespace omath::hud @@ -24,6 +25,20 @@ namespace omath::hud virtual void add_filled_rectangle(const Vector2& min, const Vector2& max, const Color& color) = 0; + virtual void add_circle(const Vector2& center, float radius, const Color& color, float thickness, + int segments = 0) = 0; + + virtual void add_filled_circle(const Vector2& center, float radius, const Color& color, + int segments = 0) = 0; + + /// Draw an arc (partial circle outline). Angles in radians, 0 = right (+X), counter-clockwise. + virtual void add_arc(const Vector2& center, float radius, float a_min, float a_max, const Color& color, + float thickness, int segments = 0) = 0; + + /// Draw a textured quad. texture_id is renderer-specific (e.g. ImTextureID for ImGui). + virtual void add_image(const std::any& texture_id, const Vector2& min, const Vector2& max, + const Color& tint = Color{1.f, 1.f, 1.f, 1.f}) = 0; + virtual void add_text(const Vector2& position, const Color& color, const std::string_view& text) = 0; [[nodiscard]] diff --git a/include/omath/hud/renderer_realizations/imgui_renderer.hpp b/include/omath/hud/renderer_realizations/imgui_renderer.hpp index 5645de2e..8b8190b4 100644 --- a/include/omath/hud/renderer_realizations/imgui_renderer.hpp +++ b/include/omath/hud/renderer_realizations/imgui_renderer.hpp @@ -17,6 +17,14 @@ namespace omath::hud void add_filled_polyline(const std::span>& vertexes, const Color& color) override; void add_rectangle(const Vector2& min, const Vector2& max, const Color& color) override; void add_filled_rectangle(const Vector2& min, const Vector2& max, const Color& color) override; + void add_circle(const Vector2& center, float radius, const Color& color, float thickness, + int segments = 0) override; + void add_filled_circle(const Vector2& center, float radius, const Color& color, + int segments = 0) override; + void add_arc(const Vector2& center, float radius, float a_min, float a_max, const Color& color, + float thickness, int segments = 0) override; + void add_image(const std::any& texture_id, const Vector2& min, const Vector2& max, + const Color& tint = Color{1.f, 1.f, 1.f, 1.f}) override; void add_text(const Vector2& position, const Color& color, const std::string_view& text) override; [[nodiscard]] virtual Vector2 calc_text_size(const std::string_view& text) override; diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index 11651368..c866427f 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -457,6 +457,137 @@ namespace omath::hud m_text_cursor_left(m_canvas.top_left_corner), m_renderer(renderer) { } + // ── Spacers ───────────────────────────────────────────────────────────────── + EntityOverlay& EntityOverlay::add_right_space_vertical(const float size) + { + m_text_cursor_right.y += size; + return *this; + } + + EntityOverlay& EntityOverlay::add_right_space_horizontal(const float size) + { + m_text_cursor_right.x += size; + return *this; + } + + EntityOverlay& EntityOverlay::add_left_space_vertical(const float size) + { + m_text_cursor_left.y += size; + return *this; + } + + EntityOverlay& EntityOverlay::add_left_space_horizontal(const float size) + { + m_text_cursor_left.x -= size; + return *this; + } + + EntityOverlay& EntityOverlay::add_top_space_vertical(const float size) + { + m_text_cursor_top.y -= size; + return *this; + } + + EntityOverlay& EntityOverlay::add_top_space_horizontal(const float size) + { + m_text_cursor_top.x += size; + return *this; + } + + EntityOverlay& EntityOverlay::add_bottom_space_vertical(const float size) + { + m_text_cursor_bottom.y += size; + return *this; + } + + EntityOverlay& EntityOverlay::add_bottom_space_horizontal(const float size) + { + m_text_cursor_bottom.x += size; + return *this; + } + + // ── Progress rings ────────────────────────────────────────────────────────── + EntityOverlay& EntityOverlay::add_right_progress_ring(const Color& color, const Color& bg, const float radius, + const float ratio, const float thickness, const float offset, + const int segments) + { + const auto cx = m_text_cursor_right.x + offset + radius; + const auto cy = m_text_cursor_right.y + radius; + draw_progress_ring({cx, cy}, widget::ProgressRing{color, bg, radius, ratio, thickness, offset, segments}); + m_text_cursor_right.y += radius * 2.f; + return *this; + } + + EntityOverlay& EntityOverlay::add_left_progress_ring(const Color& color, const Color& bg, const float radius, + const float ratio, const float thickness, const float offset, + const int segments) + { + const auto cx = m_text_cursor_left.x - offset - radius; + const auto cy = m_text_cursor_left.y + radius; + draw_progress_ring({cx, cy}, widget::ProgressRing{color, bg, radius, ratio, thickness, offset, segments}); + m_text_cursor_left.y += radius * 2.f; + return *this; + } + + EntityOverlay& EntityOverlay::add_top_progress_ring(const Color& color, const Color& bg, const float radius, + const float ratio, const float thickness, const float offset, + const int segments) + { + m_text_cursor_top.y -= radius * 2.f; + const auto cx = m_text_cursor_top.x + radius; + const auto cy = m_text_cursor_top.y - offset + radius; + draw_progress_ring({cx, cy}, widget::ProgressRing{color, bg, radius, ratio, thickness, offset, segments}); + return *this; + } + + EntityOverlay& EntityOverlay::add_bottom_progress_ring(const Color& color, const Color& bg, const float radius, + const float ratio, const float thickness, const float offset, + const int segments) + { + const auto cx = m_text_cursor_bottom.x + radius; + const auto cy = m_text_cursor_bottom.y + offset + radius; + draw_progress_ring({cx, cy}, widget::ProgressRing{color, bg, radius, ratio, thickness, offset, segments}); + m_text_cursor_bottom.y += radius * 2.f; + return *this; + } + + // ── Icons ──────────────────────────────────────────────────────────────────── + EntityOverlay& EntityOverlay::add_right_icon(const std::any& texture_id, const float width, const float height, + const Color& tint, const float offset) + { + const auto pos = m_text_cursor_right + Vector2{offset, 0.f}; + m_renderer->add_image(texture_id, pos, pos + Vector2{width, height}, tint); + m_text_cursor_right.y += height; + return *this; + } + + EntityOverlay& EntityOverlay::add_left_icon(const std::any& texture_id, const float width, const float height, + const Color& tint, const float offset) + { + const auto pos = m_text_cursor_left + Vector2{-(offset + width), 0.f}; + m_renderer->add_image(texture_id, pos, pos + Vector2{width, height}, tint); + m_text_cursor_left.y += height; + return *this; + } + + EntityOverlay& EntityOverlay::add_top_icon(const std::any& texture_id, const float width, const float height, + const Color& tint, const float offset) + { + m_text_cursor_top.y -= height; + const auto pos = m_text_cursor_top + Vector2{0.f, -offset}; + m_renderer->add_image(texture_id, pos, pos + Vector2{width, height}, tint); + return *this; + } + + EntityOverlay& EntityOverlay::add_bottom_icon(const std::any& texture_id, const float width, const float height, + const Color& tint, const float offset) + { + const auto pos = m_text_cursor_bottom + Vector2{0.f, offset}; + m_renderer->add_image(texture_id, pos, pos + Vector2{width, height}, tint); + m_text_cursor_bottom.y += height; + return *this; + } + // ── widget dispatch ─────────────────────────────────────────────────────── void EntityOverlay::dispatch(const widget::Box& box) { @@ -483,10 +614,53 @@ namespace omath::hud add_snap_line(snap_line.start, snap_line.color, snap_line.width); } + void EntityOverlay::dispatch(const widget::ScanMarker& scan_marker) + { + const auto box_width = std::abs(m_canvas.top_right_corner.x - m_canvas.top_left_corner.x); + const auto box_height = std::abs(m_canvas.bottom_left_corner.y - m_canvas.top_left_corner.y); + + const auto center_x = (m_canvas.top_left_corner.x + m_canvas.top_right_corner.x) / 2.f; + const auto center_y = m_canvas.top_left_corner.y + box_height * 0.44f; + + const auto side = std::min(box_width, box_height) * 0.5f; + const auto h = side * std::sqrt(3.f) / 2.f; + + const std::array, 3> tri = { + Vector2{center_x, center_y - h * 2.f / 3.f}, + Vector2{center_x - side / 2.f, center_y + h / 3.f}, + Vector2{center_x + side / 2.f, center_y + h / 3.f}, + }; + + m_renderer->add_filled_polyline({tri.data(), tri.size()}, scan_marker.color); + + if (scan_marker.outline.value().w > 0.f) + m_renderer->add_polyline({tri.data(), tri.size()}, scan_marker.outline, scan_marker.outline_thickness); + } + + void EntityOverlay::dispatch(const widget::AimDot& aim_dot) + { + m_renderer->add_filled_circle(aim_dot.position, aim_dot.radius, aim_dot.color); + } + + void EntityOverlay::draw_progress_ring(const Vector2& center, const widget::ProgressRing& ring) + { + constexpr auto pi = std::numbers::pi_v; + const float ratio = std::clamp(ring.ratio, 0.f, 1.f); + + m_renderer->add_circle(center, ring.radius, ring.bg, ring.thickness, ring.segments); + + if (ratio > 0.f) + { + const float a_min = -pi / 2.f; + const float a_max = a_min + ratio * 2.f * pi; + m_renderer->add_arc(center, ring.radius, a_min, a_max, ring.color, ring.thickness, ring.segments); + } + } + // ── Side container dispatch ─────────────────────────────────────────────── - void EntityOverlay::dispatch(const widget::RightSide& s) + void EntityOverlay::dispatch(const widget::RightSide& right_side) { - for (const auto& child : s.children) + for (const auto& child : right_side.children) std::visit( widget::Overloaded{ [](const widget::None&) @@ -509,13 +683,30 @@ namespace omath::hud { add_right_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); }, + [this](const widget::SpaceVertical& w) + { + add_right_space_vertical(w.size); + }, + [this](const widget::SpaceHorizontal& w) + { + add_right_space_horizontal(w.size); + }, + [this](const widget::ProgressRing& w) + { + add_right_progress_ring(w.color, w.bg, w.radius, w.ratio, w.thickness, w.offset, + w.segments); + }, + [this](const widget::Icon& w) + { + add_right_icon(w.texture_id, w.width, w.height, w.tint, w.offset); + }, }, child); } - void EntityOverlay::dispatch(const widget::LeftSide& s) + void EntityOverlay::dispatch(const widget::LeftSide& left_side) { - for (const auto& child : s.children) + for (const auto& child : left_side.children) std::visit( widget::Overloaded{ [](const widget::None&) @@ -538,6 +729,23 @@ namespace omath::hud { add_left_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); }, + [this](const widget::SpaceVertical& w) + { + add_left_space_vertical(w.size); + }, + [this](const widget::SpaceHorizontal& w) + { + add_left_space_horizontal(w.size); + }, + [this](const widget::ProgressRing& w) + { + add_left_progress_ring(w.color, w.bg, w.radius, w.ratio, w.thickness, w.offset, + w.segments); + }, + [this](const widget::Icon& w) + { + add_left_icon(w.texture_id, w.width, w.height, w.tint, w.offset); + }, }, child); } @@ -567,6 +775,23 @@ namespace omath::hud { add_centered_top_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); }, + [this](const widget::SpaceVertical& w) + { + add_top_space_vertical(w.size); + }, + [this](const widget::SpaceHorizontal& w) + { + add_top_space_horizontal(w.size); + }, + [this](const widget::ProgressRing& w) + { + add_top_progress_ring(w.color, w.bg, w.radius, w.ratio, w.thickness, w.offset, + w.segments); + }, + [this](const widget::Icon& w) + { + add_top_icon(w.texture_id, w.width, w.height, w.tint, w.offset); + }, }, child); } @@ -596,6 +821,23 @@ namespace omath::hud add_centered_bottom_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); }, + [this](const widget::SpaceVertical& w) + { + add_bottom_space_vertical(w.size); + }, + [this](const widget::SpaceHorizontal& w) + { + add_bottom_space_horizontal(w.size); + }, + [this](const widget::ProgressRing& w) + { + add_bottom_progress_ring(w.color, w.bg, w.radius, w.ratio, w.thickness, w.offset, + w.segments); + }, + [this](const widget::Icon& w) + { + add_bottom_icon(w.texture_id, w.width, w.height, w.tint, w.offset); + }, }, child); } diff --git a/source/hud/renderer_realizations/imgui_renderer.cpp b/source/hud/renderer_realizations/imgui_renderer.cpp index 5d397d4d..41943519 100644 --- a/source/hud/renderer_realizations/imgui_renderer.cpp +++ b/source/hud/renderer_realizations/imgui_renderer.cpp @@ -42,6 +42,32 @@ namespace omath::hud ImGui::GetBackgroundDrawList()->AddRectFilled(min.to_im_vec2(), max.to_im_vec2(), color.to_im_color()); } + void ImguiHudRenderer::add_circle(const Vector2& center, const float radius, const Color& color, + const float thickness, const int segments) + { + ImGui::GetBackgroundDrawList()->AddCircle(center.to_im_vec2(), radius, color.to_im_color(), segments, thickness); + } + + void ImguiHudRenderer::add_filled_circle(const Vector2& center, const float radius, const Color& color, + const int segments) + { + ImGui::GetBackgroundDrawList()->AddCircleFilled(center.to_im_vec2(), radius, color.to_im_color(), segments); + } + + void ImguiHudRenderer::add_arc(const Vector2& center, const float radius, const float a_min, const float a_max, + const Color& color, const float thickness, const int segments) + { + ImGui::GetBackgroundDrawList()->PathArcTo(center.to_im_vec2(), radius, a_min, a_max, segments); + ImGui::GetBackgroundDrawList()->PathStroke(color.to_im_color(), ImDrawFlags_None, thickness); + } + + void ImguiHudRenderer::add_image(const std::any& texture_id, const Vector2& min, const Vector2& max, + const Color& tint) + { + ImGui::GetBackgroundDrawList()->AddImage(std::any_cast(texture_id), min.to_im_vec2(), + max.to_im_vec2(), {0, 0}, {1, 1}, tint.to_im_color()); + } + void ImguiHudRenderer::add_text(const Vector2& position, const Color& color, const std::string_view& text) { ImGui::GetBackgroundDrawList()->AddText(position.to_im_vec2(), color.to_im_color(), text.data(),