From d31ea6ed4d8fe37d410d594e178d1824b002b2ad Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:17:30 +0300 Subject: [PATCH 1/9] added more stuff --- include/omath/hud/entity_overlay.hpp | 37 ++++++++++- source/hud/entity_overlay.cpp | 64 ++++++++++++++++++- .../renderer_realizations/imgui_renderer.cpp | 4 +- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/include/omath/hud/entity_overlay.hpp b/include/omath/hud/entity_overlay.hpp index 026d2b55..3d868d6b 100644 --- a/include/omath/hud/entity_overlay.hpp +++ b/include/omath/hud/entity_overlay.hpp @@ -26,7 +26,7 @@ namespace omath::hud float ratio, float offset = 5.f); void add_left_bar(const Color& color, const Color& outline_color, const Color& bg_color, float width, - float ratio, float offset = 5.f) const; + float ratio, float offset = 5.f); template void add_right_label(const Color& color, const float offset, const bool outlined, @@ -55,12 +55,47 @@ namespace omath::hud void add_snap_line(const Vector2& start_pos, const Color& color, float width); + void add_bottom_bar(const Color& color, const Color& outline_color, const Color& bg_color, float height, + float ratio, float offset = 5.f); + + template + void add_bottom_label(const Color& color, const float offset, const bool outlined, + std::format_string fmt, Args&&... args) + { + const std::string label = std::vformat(fmt.get(), std::make_format_args(args...)); + add_bottom_label(color, offset, outlined, std::string_view{label}); + } + + void add_bottom_label(const Color& color, float offset, bool outlined, std::string_view text); + + template + void add_left_label(const Color& color, const float offset, const bool outlined, + std::format_string fmt, Args&&... args) + { + const std::string label = std::vformat(fmt.get(), std::make_format_args(args...)); + add_left_label(color, offset, outlined, std::string_view{label}); + } + + void add_left_label(const Color& color, float offset, bool outlined, const std::string_view& text); + + template + void add_centered_label(const Color& color, const float offset, const bool outlined, + std::format_string fmt, Args&&... args) + { + const std::string label = std::vformat(fmt.get(), std::make_format_args(args...)); + add_centered_label(color, offset, outlined, std::string_view{label}); + } + + void add_centered_label(const Color& color, float offset, bool outlined, const std::string_view& text); + private: void draw_outlined_text(const Vector2& position, const Color& color, const std::string_view& text); CanvasBox m_canvas; Vector2 m_text_cursor_right; Vector2 m_text_cursor_top; + Vector2 m_text_cursor_bottom; + Vector2 m_text_cursor_left; std::shared_ptr m_renderer; }; } // namespace omath::hud \ No newline at end of file diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index c560195f..bb06b23d 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -65,7 +65,7 @@ namespace omath::hud m_text_cursor_right.x += offset + width; } void EntityOverlay::add_left_bar(const Color& color, const Color& outline_color, const Color& bg_color, - const float width, float ratio, const float offset) const + const float width, float ratio, const float offset) { ratio = std::clamp(ratio, 0.f, 1.f); const auto max_bar_height = std::abs(m_canvas.top_left_corner.y - m_canvas.bottom_right_corner.y); @@ -76,6 +76,8 @@ namespace omath::hud m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(width, -max_bar_height * ratio), color); m_renderer->add_rectangle(bar_start - Vector2(1.f, 0.f), bar_start + Vector2(width, -max_bar_height), outline_color); + + m_text_cursor_left.x -= offset + width; } void EntityOverlay::add_right_label(const Color& color, const float offset, const bool outlined, const std::string_view& text) @@ -129,10 +131,68 @@ namespace omath::hud m_renderer->add_text(position + outline_offset, Color{0.f, 0.f, 0.f, 1.f}, text.data()); m_renderer->add_text(position, color, text.data()); } + void EntityOverlay::add_bottom_bar(const Color& color, const Color& outline_color, const Color& bg_color, + const float height, float ratio, const float offset) + { + ratio = std::clamp(ratio, 0.f, 1.f); + const auto max_bar_width = std::abs(m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x); + + const auto bar_start = m_canvas.bottom_left_corner + Vector2{0.f, offset}; + m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(max_bar_width, height), bg_color); + m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(max_bar_width * ratio, height), color); + m_renderer->add_rectangle(bar_start, bar_start + Vector2(max_bar_width, height), outline_color); + + m_text_cursor_bottom.y += offset + height; + } + + void EntityOverlay::add_bottom_label(const Color& color, const float offset, const bool outlined, + const std::string_view text) + { + const auto text_size = m_renderer->calc_text_size(text); + + if (outlined) + draw_outlined_text(m_text_cursor_bottom + Vector2{0.f, offset}, color, text); + else + m_renderer->add_text(m_text_cursor_bottom + Vector2{0.f, offset}, color, text); + + m_text_cursor_bottom.y += text_size.y; + } + + void EntityOverlay::add_left_label(const Color& color, const float offset, const bool outlined, + const std::string_view& text) + { + const auto text_size = m_renderer->calc_text_size(text); + const auto pos = m_text_cursor_left + Vector2{-(offset + text_size.x), 0.f}; + + if (outlined) + draw_outlined_text(pos, color, text); + else + m_renderer->add_text(pos, color, text); + + m_text_cursor_left.y += text_size.y; + } + + void EntityOverlay::add_centered_label(const Color& color, const float offset, const bool outlined, + const std::string_view& text) + { + const auto text_size = m_renderer->calc_text_size(text); + const auto box_center_x = m_canvas.bottom_left_corner.x + + (m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x) / 2.f; + const auto pos = Vector2{box_center_x - text_size.x / 2.f, m_text_cursor_bottom.y + offset}; + + if (outlined) + draw_outlined_text(pos, color, text); + else + m_renderer->add_text(pos, color, text); + + m_text_cursor_bottom.y += text_size.y; + } + EntityOverlay::EntityOverlay(const Vector2& top, const Vector2& bottom, const std::shared_ptr& renderer) : m_canvas(top, bottom), m_text_cursor_right(m_canvas.top_right_corner), - m_text_cursor_top(m_canvas.top_left_corner), m_renderer(renderer) + m_text_cursor_top(m_canvas.top_left_corner), m_text_cursor_bottom(m_canvas.bottom_left_corner), + m_text_cursor_left(m_canvas.top_left_corner), m_renderer(renderer) { } } // namespace omath::hud \ No newline at end of file diff --git a/source/hud/renderer_realizations/imgui_renderer.cpp b/source/hud/renderer_realizations/imgui_renderer.cpp index 8c664916..ac5cadd9 100644 --- a/source/hud/renderer_realizations/imgui_renderer.cpp +++ b/source/hud/renderer_realizations/imgui_renderer.cpp @@ -22,7 +22,7 @@ namespace omath::hud { ImGui::GetBackgroundDrawList()->AddPolyline(reinterpret_cast(vertexes.data()), static_cast(vertexes.size()), color.to_im_color(), - ImDrawFlags_None, thickness); + ImDrawFlags_Closed, thickness); } void ImguiHudRenderer::add_filled_polyline(const std::span>& vertexes, const Color& color, @@ -50,7 +50,7 @@ namespace omath::hud text.data() + text.size()); } [[nodiscard]] - Vector2 calc_text_size(const std::string_view& text) + Vector2 ImguiHudRenderer::calc_text_size(const std::string_view& text) { return Vector2::from_im_vec2(ImGui::CalcTextSize(text.data())); } From 19d796cd4e66f32eff5d695288d31297979e2af9 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:23:07 +0300 Subject: [PATCH 2/9] improvement --- include/omath/hud/entity_overlay.hpp | 18 ++++++++++++++---- source/hud/entity_overlay.cpp | 20 ++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/include/omath/hud/entity_overlay.hpp b/include/omath/hud/entity_overlay.hpp index 3d868d6b..b06fd621 100644 --- a/include/omath/hud/entity_overlay.hpp +++ b/include/omath/hud/entity_overlay.hpp @@ -79,14 +79,24 @@ namespace omath::hud void add_left_label(const Color& color, float offset, bool outlined, const std::string_view& text); template - void add_centered_label(const Color& color, const float offset, const bool outlined, - std::format_string fmt, Args&&... args) + void add_centered_bottom_label(const Color& color, const float offset, const bool outlined, + std::format_string fmt, Args&&... args) { const std::string label = std::vformat(fmt.get(), std::make_format_args(args...)); - add_centered_label(color, offset, outlined, std::string_view{label}); + add_centered_bottom_label(color, offset, outlined, std::string_view{label}); } - void add_centered_label(const Color& color, float offset, bool outlined, const std::string_view& text); + void add_centered_bottom_label(const Color& color, float offset, bool outlined, const std::string_view& text); + + template + void add_centered_top_label(const Color& color, const float offset, const bool outlined, + std::format_string fmt, Args&&... args) + { + const std::string label = std::vformat(fmt.get(), std::make_format_args(args...)); + add_centered_top_label(color, offset, outlined, std::string_view{label}); + } + + void add_centered_top_label(const Color& color, float offset, bool outlined, const std::string_view& text); private: void draw_outlined_text(const Vector2& position, const Color& color, diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index bb06b23d..70495081 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -172,8 +172,8 @@ namespace omath::hud m_text_cursor_left.y += text_size.y; } - void EntityOverlay::add_centered_label(const Color& color, const float offset, const bool outlined, - const std::string_view& text) + void EntityOverlay::add_centered_bottom_label(const Color& color, const float offset, const bool outlined, + const std::string_view& text) { const auto text_size = m_renderer->calc_text_size(text); const auto box_center_x = m_canvas.bottom_left_corner.x @@ -188,6 +188,22 @@ namespace omath::hud m_text_cursor_bottom.y += text_size.y; } + void EntityOverlay::add_centered_top_label(const Color& color, const float offset, const bool outlined, + const std::string_view& text) + { + const auto text_size = m_renderer->calc_text_size(text); + const auto box_center_x = m_canvas.top_left_corner.x + + (m_canvas.top_right_corner.x - m_canvas.top_left_corner.x) / 2.f; + + m_text_cursor_top.y -= text_size.y; + const auto pos = Vector2{box_center_x - text_size.x / 2.f, m_text_cursor_top.y - offset}; + + if (outlined) + draw_outlined_text(pos, color, text); + else + m_renderer->add_text(pos, color, text); + } + EntityOverlay::EntityOverlay(const Vector2& top, const Vector2& bottom, const std::shared_ptr& renderer) : m_canvas(top, bottom), m_text_cursor_right(m_canvas.top_right_corner), From 55304c5df15b8940e5db7c16493c84a8b648c009 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:28:56 +0300 Subject: [PATCH 3/9] fixed bug --- include/omath/hud/hud_renderer_interface.hpp | 3 +-- .../hud/renderer_realizations/imgui_renderer.hpp | 2 +- source/hud/entity_overlay.cpp | 14 ++++++++------ .../hud/renderer_realizations/imgui_renderer.cpp | 8 +++----- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/omath/hud/hud_renderer_interface.hpp b/include/omath/hud/hud_renderer_interface.hpp index 117cb7d6..8d625324 100644 --- a/include/omath/hud/hud_renderer_interface.hpp +++ b/include/omath/hud/hud_renderer_interface.hpp @@ -18,8 +18,7 @@ namespace omath::hud virtual void add_polyline(const std::span>& vertexes, const Color& color, float thickness) = 0; - virtual void add_filled_polyline(const std::span>& vertexes, const Color& color, - float thickness) = 0; + virtual void add_filled_polyline(const std::span>& vertexes, const Color& color) = 0; virtual void add_rectangle(const Vector2& min, const Vector2& max, const Color& color) = 0; diff --git a/include/omath/hud/renderer_realizations/imgui_renderer.hpp b/include/omath/hud/renderer_realizations/imgui_renderer.hpp index cd4dbbe8..5645de2e 100644 --- a/include/omath/hud/renderer_realizations/imgui_renderer.hpp +++ b/include/omath/hud/renderer_realizations/imgui_renderer.hpp @@ -14,7 +14,7 @@ namespace omath::hud void add_line(const Vector2& line_start, const Vector2& line_end, const Color& color, float thickness) override; void add_polyline(const std::span>& vertexes, const Color& color, float thickness) override; - void add_filled_polyline(const std::span>& vertexes, const Color& color, float thickness) override; + 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_text(const Vector2& position, const Color& color, const std::string_view& text) override; diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index 70495081..073fffd3 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -10,7 +10,9 @@ namespace omath::hud const auto points = m_canvas.as_array(); m_renderer->add_polyline({points.data(), points.size()}, box_color, thickness); - m_renderer->add_filled_polyline({points.data(), points.size()}, fill_color, thickness); + + if (fill_color.value().w > 0.f) + m_renderer->add_filled_polyline({points.data(), points.size()}, fill_color); } void EntityOverlay::add_cornered_2d_box(const Color& box_color, const Color& fill_color, const float corner_ratio_len, const float thickness) const @@ -173,11 +175,11 @@ namespace omath::hud } void EntityOverlay::add_centered_bottom_label(const Color& color, const float offset, const bool outlined, - const std::string_view& text) + const std::string_view& text) { const auto text_size = m_renderer->calc_text_size(text); - const auto box_center_x = m_canvas.bottom_left_corner.x - + (m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x) / 2.f; + const auto box_center_x = + m_canvas.bottom_left_corner.x + (m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x) / 2.f; const auto pos = Vector2{box_center_x - text_size.x / 2.f, m_text_cursor_bottom.y + offset}; if (outlined) @@ -192,8 +194,8 @@ namespace omath::hud const std::string_view& text) { const auto text_size = m_renderer->calc_text_size(text); - const auto box_center_x = m_canvas.top_left_corner.x - + (m_canvas.top_right_corner.x - m_canvas.top_left_corner.x) / 2.f; + const auto box_center_x = + m_canvas.top_left_corner.x + (m_canvas.top_right_corner.x - m_canvas.top_left_corner.x) / 2.f; m_text_cursor_top.y -= text_size.y; const auto pos = Vector2{box_center_x - text_size.x / 2.f, m_text_cursor_top.y - offset}; diff --git a/source/hud/renderer_realizations/imgui_renderer.cpp b/source/hud/renderer_realizations/imgui_renderer.cpp index ac5cadd9..5d397d4d 100644 --- a/source/hud/renderer_realizations/imgui_renderer.cpp +++ b/source/hud/renderer_realizations/imgui_renderer.cpp @@ -25,12 +25,10 @@ namespace omath::hud ImDrawFlags_Closed, thickness); } - void ImguiHudRenderer::add_filled_polyline(const std::span>& vertexes, const Color& color, - const float thickness) + void ImguiHudRenderer::add_filled_polyline(const std::span>& vertexes, const Color& color) { - ImGui::GetBackgroundDrawList()->AddPolyline(reinterpret_cast(vertexes.data()), - static_cast(vertexes.size()), color.to_im_color(), - ImDrawFlags_Closed, thickness); + ImGui::GetBackgroundDrawList()->AddConvexPolyFilled(reinterpret_cast(vertexes.data()), + static_cast(vertexes.size()), color.to_im_color()); } void ImguiHudRenderer::add_rectangle(const Vector2& min, const Vector2& max, const Color& color) From 69bdfc330713e2ed71d3dcd80cf0050479c78448 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:43:19 +0300 Subject: [PATCH 4/9] improved example --- examples/example_hud/gui/main_window.cpp | 185 +++++++++++++++++------ 1 file changed, 140 insertions(+), 45 deletions(-) diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index ff6c8a5b..5624c3e4 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -5,7 +5,6 @@ #include "main_window.hpp" #include "omath/hud/renderer_realizations/imgui_renderer.hpp" #include -#include #include #include #include @@ -20,6 +19,10 @@ namespace imgui_desktop::gui if (!glfwInit()) std::exit(EXIT_FAILURE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, true); m_window = glfwCreateWindow(width, height, caption.data(), nullptr, nullptr); @@ -28,24 +31,45 @@ namespace imgui_desktop::gui ImGui::CreateContext(); ImGui::StyleColorsDark(); - ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = {0.f, 0.f, 0.f, 0.f}; - + ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = {0.05f, 0.05f, 0.05f, 0.92f}; ImGui::GetStyle().AntiAliasedLines = false; ImGui::GetStyle().AntiAliasedFill = false; - ImGui_ImplGlfw_InitForOpenGL(m_window, true); - ImGui_ImplOpenGL3_Init("#version 130"); + ImGui_ImplOpenGL3_Init("#version 150"); } void MainWindow::Run() { - omath::Color box_color = {0.f, 0.f, 0.f, 1.f}; - omath::Color box_fill = {0.f, 0.f, 0.f, 0.f}; - omath::Color bar_color = {0.f, 1.f, 0.f, 1.f}; - omath::Color bar_bg_color = {0.f, 0.f, 0.f, 0.0f}; + // Entity position + float entity_x = 550.f, entity_top_y = 150.f, entity_bottom_y = 450.f; + float box_ratio = 4.f; + + // Box + omath::Color box_color = {1.f, 1.f, 1.f, 1.f}; + omath::Color box_fill = {0.f, 0.f, 0.f, 0.f}; + float box_thickness = 1.f; + float corner_ratio = 0.2f; + bool show_box = true, show_cornered_box = true; + + // Bars + omath::Color bar_color = {0.f, 1.f, 0.f, 1.f}; + omath::Color bar_bg_color = {0.f, 0.f, 0.f, 0.5f}; omath::Color bar_outline_color = {0.f, 0.f, 0.f, 1.f}; - float bar_width = 3.f; - float bar_value = 1.f; + float bar_width = 4.f, bar_value = 0.75f, bar_offset = 5.f; + bool show_right_bar = true, show_left_bar = true; + bool show_top_bar = true, show_bottom_bar = true; + + // Labels + float label_offset = 3.f; + bool outlined = true; + bool show_right_labels = true, show_left_labels = true; + bool show_top_labels = true, show_bottom_labels = true; + bool show_centered_top = true, show_centered_bottom = true; + + // Snap line + omath::Color snap_color = omath::Color::from_rgba(255, 50, 50, 255); + float snap_width = 1.5f; + bool show_snap = true; while (!glfwWindowShouldClose(m_window) && m_opened) { @@ -55,50 +79,122 @@ namespace imgui_desktop::gui ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); - ImGui::GetBackgroundDrawList()->AddRectFilled({}, ImGui::GetMainViewport()->Size, ImColor(40, 40, 40, 200)); + const auto* viewport = ImGui::GetMainViewport(); + ImGui::GetBackgroundDrawList()->AddRectFilled({}, viewport->Size, ImColor(30, 30, 30, 220)); + + // ── Side panel ────────────────────────────────────────────── + constexpr float panel_w = 280.f; + ImGui::SetNextWindowPos({0.f, 0.f}); + ImGui::SetNextWindowSize({panel_w, viewport->Size.y}); + ImGui::Begin("Controls", &m_opened, + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + + ImGui::PushItemWidth(160.f); + + if (ImGui::CollapsingHeader("Entity", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::SliderFloat("X##ent", &entity_x, 100.f, viewport->Size.x - 100.f); + ImGui::SliderFloat("Top Y", &entity_top_y, 20.f, entity_bottom_y - 20.f); + ImGui::SliderFloat("Bottom Y", &entity_bottom_y, entity_top_y + 20.f, viewport->Size.y - 20.f); + ImGui::SliderFloat("Aspect ratio", &box_ratio, 1.f, 10.f); + } + + if (ImGui::CollapsingHeader("Box", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Checkbox("Show box", &show_box); + ImGui::Checkbox("Show cornered box", &show_cornered_box); + ImGui::ColorEdit4("Color##box", reinterpret_cast(&box_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("Fill##box", reinterpret_cast(&box_fill), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Thickness", &box_thickness, 0.5f, 5.f); + ImGui::SliderFloat("Corner ratio", &corner_ratio, 0.05f, 0.5f); + } + + if (ImGui::CollapsingHeader("Bars", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::ColorEdit4("Color##bar", reinterpret_cast(&bar_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("BG##bar", reinterpret_cast(&bar_bg_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("Outline##bar", reinterpret_cast(&bar_outline_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Width##bar", &bar_width, 1.f, 20.f); + ImGui::SliderFloat("Value##bar", &bar_value, 0.f, 1.f); + ImGui::SliderFloat("Offset##bar", &bar_offset, 1.f, 20.f); + ImGui::Checkbox("Right bar", &show_right_bar); ImGui::SameLine(); + ImGui::Checkbox("Left bar", &show_left_bar); + ImGui::Checkbox("Top bar", &show_top_bar); ImGui::SameLine(); + ImGui::Checkbox("Bottom bar", &show_bottom_bar); + } + + if (ImGui::CollapsingHeader("Labels", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Checkbox("Outlined", &outlined); + ImGui::SliderFloat("Offset##lbl", &label_offset, 0.f, 15.f); + ImGui::Checkbox("Right##lbl", &show_right_labels); ImGui::SameLine(); + ImGui::Checkbox("Left##lbl", &show_left_labels); + ImGui::Checkbox("Top##lbl", &show_top_labels); ImGui::SameLine(); + ImGui::Checkbox("Bottom##lbl", &show_bottom_labels); + ImGui::Checkbox("Centered top##lbl", &show_centered_top); ImGui::SameLine(); + ImGui::Checkbox("Centered bot##lbl", &show_centered_bottom); + } - ImGui::Begin("OHUD Showcase", &m_opened, - ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDecoration); + if (ImGui::CollapsingHeader("Snap Line")) { - ImGui::SetWindowPos({}); - ImGui::SetWindowSize(ImGui::GetMainViewport()->Size); - - ImGui::ColorEdit4("Box", reinterpret_cast(&box_color), ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("Box fill", reinterpret_cast(&box_fill), ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("Bar", reinterpret_cast(&bar_color), ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("Bar Background", reinterpret_cast(&bar_bg_color), - ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("Bar Outline", reinterpret_cast(&bar_outline_color), - ImGuiColorEditFlags_NoInputs); - - ImGui::PushItemWidth(100.f); - ImGui::SliderFloat("Bar Width", &bar_width, 1.f, 20.f); - ImGui::SliderFloat("Bar Value", &bar_value, 0.f, 1.f); - ImGui::PopItemWidth(); - ImGui::End(); + ImGui::Checkbox("Show##snap", &show_snap); + ImGui::ColorEdit4("Color##snap", reinterpret_cast(&snap_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Width##snap", &snap_width, 0.5f, 5.f); } - omath::hud::EntityOverlay ent({400.f, 100.f}, {400.f, 400.f}, std::make_shared()); + ImGui::PopItemWidth(); + ImGui::End(); + + // ── Entity overlay ─────────────────────────────────────────── + omath::hud::EntityOverlay ent( + {entity_x, entity_top_y}, {entity_x, entity_bottom_y}, + std::make_shared()); + + if (show_box) + ent.add_2d_box(box_color, box_fill, box_thickness); + if (show_cornered_box) + ent.add_cornered_2d_box(omath::Color::from_rgba(255, 0, 255, 255), box_fill, corner_ratio, box_thickness); + + if (show_right_bar) + ent.add_right_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); + if (show_left_bar) + ent.add_left_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); + if (show_top_bar) + ent.add_top_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); + if (show_bottom_bar) + ent.add_bottom_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); + + if (show_right_labels) + { + ent.add_right_label({0.f, 1.f, 0.f, 1.f}, label_offset, outlined, "Health: {}/100", 100); + ent.add_right_label({1.f, 0.f, 0.f, 1.f}, label_offset, outlined, "Shield: {}/125", 125); + ent.add_right_label({1.f, 0.f, 1.f, 1.f}, label_offset, outlined, "*LOCKED*"); + } + if (show_left_labels) + { + ent.add_left_label(omath::Color::from_rgba(255, 128, 0, 255), label_offset, outlined, "Armor: 75"); + ent.add_left_label(omath::Color::from_rgba(0, 200, 255, 255), label_offset, outlined, "Level: 42"); + } + if (show_top_labels) + { + ent.add_top_label(omath::Color::from_rgba(255, 255, 0, 255), label_offset, outlined, "*SCOPED*"); + ent.add_top_label(omath::Color::from_rgba(255, 0, 0, 255), label_offset, outlined, "*BLEEDING*"); + } + if (show_centered_top) + ent.add_centered_top_label(omath::Color::from_rgba(0, 255, 255, 255), label_offset, outlined, "*VISIBLE*"); + if (show_centered_bottom) + ent.add_centered_bottom_label(omath::Color::from_rgba(255, 255, 255, 255), label_offset, outlined, "PlayerName"); + if (show_bottom_labels) + ent.add_bottom_label(omath::Color::from_rgba(200, 200, 0, 255), label_offset, outlined, "42m"); - ent.add_2d_box(box_color, box_fill, 1.f); - ent.add_cornered_2d_box(omath::Color::from_rgba(255, 0, 255, 255), box_fill); - ent.add_right_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value); - ent.add_left_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value); - ent.add_top_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value); - ent.add_right_label({0.f, 1.f, 0.f, 1.f}, 3, true, "Health: {}/100", 100); - ent.add_right_label({1.f, 0.f, 0.f, 1.f}, 3, true, "Shield: {}/125", 125); - ent.add_right_label({1.f, 0.f, 1.f, 1.f}, 3, true, "*LOCKED*"); + if (show_snap) + ent.add_snap_line({viewport->Size.x / 2.f, viewport->Size.y}, snap_color, snap_width); - ent.add_top_label(omath::Color::from_rgba(255, 255, 0, 255), 3, true, "*SCOPED*"); - ent.add_top_label(omath::Color::from_rgba(255, 0, 0, 255), 3, true, "*BLEEDING*"); - ent.add_snap_line(omath::Vector2{400, 600}, omath::Color::from_rgba(255, 0, 0, 255), 2.f); ImGui::Render(); int display_w, display_h; - glfwGetFramebufferSize(m_window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); - glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); @@ -107,4 +203,3 @@ namespace imgui_desktop::gui glfwDestroyWindow(m_window); } } // namespace imgui_desktop::gui -// imgui_desktop \ No newline at end of file From adad66599a9271e4ff18ffa0fb83d9c20278eedc Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:49:01 +0300 Subject: [PATCH 5/9] adde dash box --- examples/example_hud/gui/main_window.cpp | 16 +++++++++++++-- include/omath/hud/entity_overlay.hpp | 5 +++++ source/hud/entity_overlay.cpp | 25 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index 5624c3e4..dd066df0 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -66,6 +66,11 @@ namespace imgui_desktop::gui bool show_top_labels = true, show_bottom_labels = true; bool show_centered_top = true, show_centered_bottom = true; + // Dashed box + omath::Color dash_color = omath::Color::from_rgba(255, 200, 0, 255); + float dash_len = 8.f, dash_gap = 5.f, dash_thickness = 1.f; + bool show_dashed_box = false; + // Snap line omath::Color snap_color = omath::Color::from_rgba(255, 50, 50, 255); float snap_width = 1.5f; @@ -101,12 +106,17 @@ namespace imgui_desktop::gui if (ImGui::CollapsingHeader("Box", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Show box", &show_box); + ImGui::Checkbox("Show box", &show_box); ImGui::Checkbox("Show cornered box", &show_cornered_box); + ImGui::Checkbox("Show dashed box", &show_dashed_box); ImGui::ColorEdit4("Color##box", reinterpret_cast(&box_color), ImGuiColorEditFlags_NoInputs); ImGui::ColorEdit4("Fill##box", reinterpret_cast(&box_fill), ImGuiColorEditFlags_NoInputs); ImGui::SliderFloat("Thickness", &box_thickness, 0.5f, 5.f); - ImGui::SliderFloat("Corner ratio", &corner_ratio, 0.05f, 0.5f); + ImGui::SliderFloat("Corner ratio", &corner_ratio, 0.05f, 0.5f); + ImGui::ColorEdit4("Dash color", reinterpret_cast(&dash_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Dash length", &dash_len, 2.f, 30.f); + ImGui::SliderFloat("Dash gap", &dash_gap, 1.f, 20.f); + ImGui::SliderFloat("Dash thickness", &dash_thickness, 0.5f, 5.f); } if (ImGui::CollapsingHeader("Bars", ImGuiTreeNodeFlags_DefaultOpen)) @@ -154,6 +164,8 @@ namespace imgui_desktop::gui ent.add_2d_box(box_color, box_fill, box_thickness); if (show_cornered_box) ent.add_cornered_2d_box(omath::Color::from_rgba(255, 0, 255, 255), box_fill, corner_ratio, box_thickness); + if (show_dashed_box) + ent.add_dashed_box(dash_color, dash_len, dash_gap, dash_thickness); if (show_right_bar) ent.add_right_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); diff --git a/include/omath/hud/entity_overlay.hpp b/include/omath/hud/entity_overlay.hpp index b06fd621..fccad107 100644 --- a/include/omath/hud/entity_overlay.hpp +++ b/include/omath/hud/entity_overlay.hpp @@ -55,6 +55,9 @@ namespace omath::hud void add_snap_line(const Vector2& start_pos, const Color& color, float width); + void add_dashed_box(const Color& color, float dash_len = 8.f, float gap_len = 5.f, + float thickness = 1.f) const; + void add_bottom_bar(const Color& color, const Color& outline_color, const Color& bg_color, float height, float ratio, float offset = 5.f); @@ -101,6 +104,8 @@ namespace omath::hud private: 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; CanvasBox m_canvas; Vector2 m_text_cursor_right; Vector2 m_text_cursor_top; diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index 073fffd3..fd084831 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -122,6 +122,31 @@ namespace omath::hud + Vector2{m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x, 0.f} / 2; m_renderer->add_line(start_pos, line_end, color, width); } + void EntityOverlay::draw_dashed_line(const Vector2& from, const Vector2& to, const Color& color, + const float dash_len, const float gap_len, const float thickness) const + { + const auto edge = to - from; + const auto total = edge.length(); + const auto dir = edge.normalized(); + const float step = dash_len + gap_len; + + for (float pos = 0.f; pos < total; pos += step) + { + const auto dash_start = from + dir * pos; + const auto dash_end = from + dir * std::min(pos + dash_len, total); + m_renderer->add_line(dash_start, dash_end, color, thickness); + } + } + + void EntityOverlay::add_dashed_box(const Color& color, const float dash_len, const float gap_len, + const float thickness) const + { + draw_dashed_line(m_canvas.top_left_corner, m_canvas.top_right_corner, color, dash_len, gap_len, thickness); + draw_dashed_line(m_canvas.top_right_corner, m_canvas.bottom_right_corner, color, dash_len, gap_len, thickness); + draw_dashed_line(m_canvas.bottom_right_corner,m_canvas.bottom_left_corner, color, dash_len, gap_len, thickness); + draw_dashed_line(m_canvas.bottom_left_corner, m_canvas.top_left_corner, color, dash_len, gap_len, thickness); + } + void EntityOverlay::draw_outlined_text(const Vector2& position, const Color& color, const std::string_view& text) { From e849d23c47ce6cd00b43fdfaf25d80a9d65de218 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:56:10 +0300 Subject: [PATCH 6/9] improved dashed box --- source/hud/entity_overlay.cpp | 42 +++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index fd084831..4897923a 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -125,13 +125,23 @@ namespace omath::hud void EntityOverlay::draw_dashed_line(const Vector2& from, const Vector2& to, const Color& color, const float dash_len, const float gap_len, const float thickness) const { - const auto edge = to - from; - const auto total = edge.length(); - const auto dir = edge.normalized(); - const float step = dash_len + gap_len; + const auto total = (to - from).length(); + if (total <= 0.f) + return; - for (float pos = 0.f; pos < total; pos += step) + const auto dir = (to - from).normalized(); + const float step = dash_len + gap_len; + + const float n_dashes = std::floor((total + gap_len) / step); + if (n_dashes < 1.f) + return; + + const float used = n_dashes * dash_len + (n_dashes - 1.f) * gap_len; + const float offset = (total - used) / 2.f; + + for (float i = 0.f; i < n_dashes; ++i) { + const float pos = offset + i * step; const auto dash_start = from + dir * pos; const auto dash_end = from + dir * std::min(pos + dash_len, total); m_renderer->add_line(dash_start, dash_end, color, thickness); @@ -141,10 +151,24 @@ namespace omath::hud void EntityOverlay::add_dashed_box(const Color& color, const float dash_len, const float gap_len, const float thickness) const { - draw_dashed_line(m_canvas.top_left_corner, m_canvas.top_right_corner, color, dash_len, gap_len, thickness); - draw_dashed_line(m_canvas.top_right_corner, m_canvas.bottom_right_corner, color, dash_len, gap_len, thickness); - draw_dashed_line(m_canvas.bottom_right_corner,m_canvas.bottom_left_corner, color, dash_len, gap_len, thickness); - draw_dashed_line(m_canvas.bottom_left_corner, m_canvas.top_left_corner, color, dash_len, gap_len, thickness); + const float min_edge = std::min( + (m_canvas.top_right_corner - m_canvas.top_left_corner).length(), + (m_canvas.bottom_right_corner - m_canvas.top_right_corner).length()); + const float corner_len = std::min(dash_len, min_edge / 2.f); + + const auto draw_edge = [&](const Vector2& from, const Vector2& to) + { + const auto dir = (to - from).normalized(); + + m_renderer->add_line(from, from + dir * corner_len, color, thickness); + draw_dashed_line(from + dir * corner_len, to - dir * corner_len, color, dash_len, gap_len, thickness); + m_renderer->add_line(to - dir * corner_len, to, color, thickness); + }; + + draw_edge(m_canvas.top_left_corner, m_canvas.top_right_corner); + draw_edge(m_canvas.top_right_corner, m_canvas.bottom_right_corner); + draw_edge(m_canvas.bottom_right_corner,m_canvas.bottom_left_corner); + draw_edge(m_canvas.bottom_left_corner, m_canvas.top_left_corner); } void EntityOverlay::draw_outlined_text(const Vector2& position, const Color& color, From a45f095b9cb2b660ba7e936dc08ac46c6eaad75d Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 04:59:47 +0300 Subject: [PATCH 7/9] added skeleton --- examples/example_hud/gui/main_window.cpp | 15 +++++++++ include/omath/hud/entity_overlay.hpp | 2 ++ source/hud/entity_overlay.cpp | 40 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index dd066df0..d306d7cb 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -71,6 +71,11 @@ namespace imgui_desktop::gui float dash_len = 8.f, dash_gap = 5.f, dash_thickness = 1.f; bool show_dashed_box = false; + // Skeleton + omath::Color skel_color = omath::Color::from_rgba(255, 255, 255, 200); + float skel_thickness = 1.f; + bool show_skeleton = false; + // Snap line omath::Color snap_color = omath::Color::from_rgba(255, 50, 50, 255); float snap_width = 1.5f; @@ -145,6 +150,13 @@ namespace imgui_desktop::gui ImGui::Checkbox("Centered bot##lbl", &show_centered_bottom); } + if (ImGui::CollapsingHeader("Skeleton")) + { + ImGui::Checkbox("Show##skel", &show_skeleton); + ImGui::ColorEdit4("Color##skel", reinterpret_cast(&skel_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Thickness##skel", &skel_thickness, 0.5f, 5.f); + } + if (ImGui::CollapsingHeader("Snap Line")) { ImGui::Checkbox("Show##snap", &show_snap); @@ -199,6 +211,9 @@ namespace imgui_desktop::gui if (show_bottom_labels) ent.add_bottom_label(omath::Color::from_rgba(200, 200, 0, 255), label_offset, outlined, "42m"); + if (show_skeleton) + ent.add_skeleton(skel_color, skel_thickness); + if (show_snap) ent.add_snap_line({viewport->Size.x / 2.f, viewport->Size.y}, snap_color, snap_width); diff --git a/include/omath/hud/entity_overlay.hpp b/include/omath/hud/entity_overlay.hpp index fccad107..9b138187 100644 --- a/include/omath/hud/entity_overlay.hpp +++ b/include/omath/hud/entity_overlay.hpp @@ -58,6 +58,8 @@ namespace omath::hud void add_dashed_box(const Color& color, float dash_len = 8.f, float gap_len = 5.f, float thickness = 1.f) const; + void add_skeleton(const Color& color, float thickness = 1.f) const; + void add_bottom_bar(const Color& color, const Color& outline_color, const Color& bg_color, float height, float ratio, float offset = 5.f); diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index 4897923a..de50f20b 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -122,6 +122,46 @@ namespace omath::hud + Vector2{m_canvas.bottom_right_corner.x - m_canvas.bottom_left_corner.x, 0.f} / 2; m_renderer->add_line(start_pos, line_end, color, width); } + void EntityOverlay::add_skeleton(const Color& color, const float thickness) const + { + // Maps normalized (rx in [0,1], ry in [0,1]) to canvas screen position + const auto joint = [&](const float rx, const float ry) -> Vector2 + { + const auto top = m_canvas.top_left_corner + + (m_canvas.top_right_corner - m_canvas.top_left_corner) * rx; + const auto bot = m_canvas.bottom_left_corner + + (m_canvas.bottom_right_corner - m_canvas.bottom_left_corner) * rx; + return top + (bot - top) * ry; + }; + + using B = std::pair, std::pair>; + static constexpr std::array k_bones{{ + // Spine + {{0.50f, 0.13f}, {0.50f, 0.22f}}, // head → neck + {{0.50f, 0.22f}, {0.50f, 0.38f}}, // neck → chest + {{0.50f, 0.38f}, {0.50f, 0.55f}}, // chest → pelvis + // Left arm + {{0.50f, 0.22f}, {0.25f, 0.25f}}, // neck → L shoulder + {{0.25f, 0.25f}, {0.13f, 0.42f}}, // L shoulder → L elbow + {{0.13f, 0.42f}, {0.08f, 0.56f}}, // L elbow → L hand + // Right arm + {{0.50f, 0.22f}, {0.75f, 0.25f}}, // neck → R shoulder + {{0.75f, 0.25f}, {0.87f, 0.42f}}, // R shoulder → R elbow + {{0.87f, 0.42f}, {0.92f, 0.56f}}, // R elbow → R hand + // Left leg + {{0.50f, 0.55f}, {0.36f, 0.58f}}, // pelvis → L hip + {{0.36f, 0.58f}, {0.32f, 0.77f}}, // L hip → L knee + {{0.32f, 0.77f}, {0.27f, 0.97f}}, // L knee → L foot + // Right leg + {{0.50f, 0.55f}, {0.64f, 0.58f}}, // pelvis → R hip + {{0.64f, 0.58f}, {0.68f, 0.77f}}, // R hip → R knee + {{0.68f, 0.77f}, {0.73f, 0.97f}}, // R knee → R foot + }}; + + for (const auto& [a, b] : k_bones) + m_renderer->add_line(joint(a.first, a.second), joint(b.first, b.second), color, thickness); + } + void EntityOverlay::draw_dashed_line(const Vector2& from, const Vector2& to, const Color& color, const float dash_len, const float gap_len, const float thickness) const { From 46c94ae541257998ee1fb3215f4192f3efbe8f8b Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 13:44:25 +0300 Subject: [PATCH 8/9] decomposed Run --- examples/example_hud/gui/main_window.cpp | 325 ++++++++++------------- examples/example_hud/gui/main_window.hpp | 55 +++- 2 files changed, 192 insertions(+), 188 deletions(-) diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index d306d7cb..b54be5a2 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -1,7 +1,6 @@ // // Created by Orange on 11/11/2024. // - #include "main_window.hpp" #include "omath/hud/renderer_realizations/imgui_renderer.hpp" #include @@ -30,7 +29,6 @@ namespace imgui_desktop::gui ImGui::CreateContext(); ImGui::StyleColorsDark(); - ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = {0.05f, 0.05f, 0.05f, 0.92f}; ImGui::GetStyle().AntiAliasedLines = false; ImGui::GetStyle().AntiAliasedFill = false; @@ -40,193 +38,162 @@ namespace imgui_desktop::gui void MainWindow::Run() { - // Entity position - float entity_x = 550.f, entity_top_y = 150.f, entity_bottom_y = 450.f; - float box_ratio = 4.f; - - // Box - omath::Color box_color = {1.f, 1.f, 1.f, 1.f}; - omath::Color box_fill = {0.f, 0.f, 0.f, 0.f}; - float box_thickness = 1.f; - float corner_ratio = 0.2f; - bool show_box = true, show_cornered_box = true; - - // Bars - omath::Color bar_color = {0.f, 1.f, 0.f, 1.f}; - omath::Color bar_bg_color = {0.f, 0.f, 0.f, 0.5f}; - omath::Color bar_outline_color = {0.f, 0.f, 0.f, 1.f}; - float bar_width = 4.f, bar_value = 0.75f, bar_offset = 5.f; - bool show_right_bar = true, show_left_bar = true; - bool show_top_bar = true, show_bottom_bar = true; - - // Labels - float label_offset = 3.f; - bool outlined = true; - bool show_right_labels = true, show_left_labels = true; - bool show_top_labels = true, show_bottom_labels = true; - bool show_centered_top = true, show_centered_bottom = true; - - // Dashed box - omath::Color dash_color = omath::Color::from_rgba(255, 200, 0, 255); - float dash_len = 8.f, dash_gap = 5.f, dash_thickness = 1.f; - bool show_dashed_box = false; - - // Skeleton - omath::Color skel_color = omath::Color::from_rgba(255, 255, 255, 200); - float skel_thickness = 1.f; - bool show_skeleton = false; - - // Snap line - omath::Color snap_color = omath::Color::from_rgba(255, 50, 50, 255); - float snap_width = 1.5f; - bool show_snap = true; - while (!glfwWindowShouldClose(m_window) && m_opened) { glfwPollEvents(); - ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); - const auto* viewport = ImGui::GetMainViewport(); - ImGui::GetBackgroundDrawList()->AddRectFilled({}, viewport->Size, ImColor(30, 30, 30, 220)); - - // ── Side panel ────────────────────────────────────────────── - constexpr float panel_w = 280.f; - ImGui::SetNextWindowPos({0.f, 0.f}); - ImGui::SetNextWindowSize({panel_w, viewport->Size.y}); - ImGui::Begin("Controls", &m_opened, - ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); - - ImGui::PushItemWidth(160.f); - - if (ImGui::CollapsingHeader("Entity", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::SliderFloat("X##ent", &entity_x, 100.f, viewport->Size.x - 100.f); - ImGui::SliderFloat("Top Y", &entity_top_y, 20.f, entity_bottom_y - 20.f); - ImGui::SliderFloat("Bottom Y", &entity_bottom_y, entity_top_y + 20.f, viewport->Size.y - 20.f); - ImGui::SliderFloat("Aspect ratio", &box_ratio, 1.f, 10.f); - } - - if (ImGui::CollapsingHeader("Box", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::Checkbox("Show box", &show_box); - ImGui::Checkbox("Show cornered box", &show_cornered_box); - ImGui::Checkbox("Show dashed box", &show_dashed_box); - ImGui::ColorEdit4("Color##box", reinterpret_cast(&box_color), ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("Fill##box", reinterpret_cast(&box_fill), ImGuiColorEditFlags_NoInputs); - ImGui::SliderFloat("Thickness", &box_thickness, 0.5f, 5.f); - ImGui::SliderFloat("Corner ratio", &corner_ratio, 0.05f, 0.5f); - ImGui::ColorEdit4("Dash color", reinterpret_cast(&dash_color), ImGuiColorEditFlags_NoInputs); - ImGui::SliderFloat("Dash length", &dash_len, 2.f, 30.f); - ImGui::SliderFloat("Dash gap", &dash_gap, 1.f, 20.f); - ImGui::SliderFloat("Dash thickness", &dash_thickness, 0.5f, 5.f); - } - - if (ImGui::CollapsingHeader("Bars", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::ColorEdit4("Color##bar", reinterpret_cast(&bar_color), ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("BG##bar", reinterpret_cast(&bar_bg_color), ImGuiColorEditFlags_NoInputs); - ImGui::ColorEdit4("Outline##bar", reinterpret_cast(&bar_outline_color), ImGuiColorEditFlags_NoInputs); - ImGui::SliderFloat("Width##bar", &bar_width, 1.f, 20.f); - ImGui::SliderFloat("Value##bar", &bar_value, 0.f, 1.f); - ImGui::SliderFloat("Offset##bar", &bar_offset, 1.f, 20.f); - ImGui::Checkbox("Right bar", &show_right_bar); ImGui::SameLine(); - ImGui::Checkbox("Left bar", &show_left_bar); - ImGui::Checkbox("Top bar", &show_top_bar); ImGui::SameLine(); - ImGui::Checkbox("Bottom bar", &show_bottom_bar); - } - - if (ImGui::CollapsingHeader("Labels", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::Checkbox("Outlined", &outlined); - ImGui::SliderFloat("Offset##lbl", &label_offset, 0.f, 15.f); - ImGui::Checkbox("Right##lbl", &show_right_labels); ImGui::SameLine(); - ImGui::Checkbox("Left##lbl", &show_left_labels); - ImGui::Checkbox("Top##lbl", &show_top_labels); ImGui::SameLine(); - ImGui::Checkbox("Bottom##lbl", &show_bottom_labels); - ImGui::Checkbox("Centered top##lbl", &show_centered_top); ImGui::SameLine(); - ImGui::Checkbox("Centered bot##lbl", &show_centered_bottom); - } - - if (ImGui::CollapsingHeader("Skeleton")) - { - ImGui::Checkbox("Show##skel", &show_skeleton); - ImGui::ColorEdit4("Color##skel", reinterpret_cast(&skel_color), ImGuiColorEditFlags_NoInputs); - ImGui::SliderFloat("Thickness##skel", &skel_thickness, 0.5f, 5.f); - } - - if (ImGui::CollapsingHeader("Snap Line")) - { - ImGui::Checkbox("Show##snap", &show_snap); - ImGui::ColorEdit4("Color##snap", reinterpret_cast(&snap_color), ImGuiColorEditFlags_NoInputs); - ImGui::SliderFloat("Width##snap", &snap_width, 0.5f, 5.f); - } - - ImGui::PopItemWidth(); - ImGui::End(); - - // ── Entity overlay ─────────────────────────────────────────── - omath::hud::EntityOverlay ent( - {entity_x, entity_top_y}, {entity_x, entity_bottom_y}, - std::make_shared()); - - if (show_box) - ent.add_2d_box(box_color, box_fill, box_thickness); - if (show_cornered_box) - ent.add_cornered_2d_box(omath::Color::from_rgba(255, 0, 255, 255), box_fill, corner_ratio, box_thickness); - if (show_dashed_box) - ent.add_dashed_box(dash_color, dash_len, dash_gap, dash_thickness); - - if (show_right_bar) - ent.add_right_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); - if (show_left_bar) - ent.add_left_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); - if (show_top_bar) - ent.add_top_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); - if (show_bottom_bar) - ent.add_bottom_bar(bar_color, bar_outline_color, bar_bg_color, bar_width, bar_value, bar_offset); - - if (show_right_labels) - { - ent.add_right_label({0.f, 1.f, 0.f, 1.f}, label_offset, outlined, "Health: {}/100", 100); - ent.add_right_label({1.f, 0.f, 0.f, 1.f}, label_offset, outlined, "Shield: {}/125", 125); - ent.add_right_label({1.f, 0.f, 1.f, 1.f}, label_offset, outlined, "*LOCKED*"); - } - if (show_left_labels) - { - ent.add_left_label(omath::Color::from_rgba(255, 128, 0, 255), label_offset, outlined, "Armor: 75"); - ent.add_left_label(omath::Color::from_rgba(0, 200, 255, 255), label_offset, outlined, "Level: 42"); - } - if (show_top_labels) - { - ent.add_top_label(omath::Color::from_rgba(255, 255, 0, 255), label_offset, outlined, "*SCOPED*"); - ent.add_top_label(omath::Color::from_rgba(255, 0, 0, 255), label_offset, outlined, "*BLEEDING*"); - } - if (show_centered_top) - ent.add_centered_top_label(omath::Color::from_rgba(0, 255, 255, 255), label_offset, outlined, "*VISIBLE*"); - if (show_centered_bottom) - ent.add_centered_bottom_label(omath::Color::from_rgba(255, 255, 255, 255), label_offset, outlined, "PlayerName"); - if (show_bottom_labels) - ent.add_bottom_label(omath::Color::from_rgba(200, 200, 0, 255), label_offset, outlined, "42m"); - - if (show_skeleton) - ent.add_skeleton(skel_color, skel_thickness); - - if (show_snap) - ent.add_snap_line({viewport->Size.x / 2.f, viewport->Size.y}, snap_color, snap_width); + const auto* vp = ImGui::GetMainViewport(); + ImGui::GetBackgroundDrawList()->AddRectFilled({}, vp->Size, ImColor(30, 30, 30, 220)); - ImGui::Render(); + draw_controls(); + draw_overlay(); - int display_w, display_h; - glfwGetFramebufferSize(m_window, &display_w, &display_h); - glViewport(0, 0, display_w, display_h); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - glfwSwapBuffers(m_window); + ImGui::Render(); + present(); } glfwDestroyWindow(m_window); } + + void MainWindow::draw_controls() + { + const auto* vp = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos({0.f, 0.f}); + ImGui::SetNextWindowSize({280.f, vp->Size.y}); + ImGui::Begin("Controls", &m_opened, + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + ImGui::PushItemWidth(160.f); + + if (ImGui::CollapsingHeader("Entity", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::SliderFloat("X##ent", &m_entity_x, 100.f, vp->Size.x - 100.f); + ImGui::SliderFloat("Top Y", &m_entity_top_y, 20.f, m_entity_bottom_y - 20.f); + ImGui::SliderFloat("Bottom Y", &m_entity_bottom_y, m_entity_top_y + 20.f, vp->Size.y - 20.f); + } + + if (ImGui::CollapsingHeader("Box", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Checkbox("Box", &m_show_box); ImGui::SameLine(); + ImGui::Checkbox("Cornered", &m_show_cornered_box); ImGui::SameLine(); + ImGui::Checkbox("Dashed", &m_show_dashed_box); + ImGui::ColorEdit4("Color##box", reinterpret_cast(&m_box_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("Fill##box", reinterpret_cast(&m_box_fill), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Thickness", &m_box_thickness, 0.5f, 5.f); + ImGui::SliderFloat("Corner ratio", &m_corner_ratio, 0.05f, 0.5f); + ImGui::Separator(); + ImGui::ColorEdit4("Dash color", reinterpret_cast(&m_dash_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Dash length", &m_dash_len, 2.f, 30.f); + ImGui::SliderFloat("Dash gap", &m_dash_gap, 1.f, 20.f); + ImGui::SliderFloat("Dash thick", &m_dash_thickness, 0.5f, 5.f); + } + + if (ImGui::CollapsingHeader("Bars", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::ColorEdit4("Color##bar", reinterpret_cast(&m_bar_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("BG##bar", reinterpret_cast(&m_bar_bg_color), ImGuiColorEditFlags_NoInputs); + ImGui::ColorEdit4("Outline##bar", reinterpret_cast(&m_bar_outline_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Width##bar", &m_bar_width, 1.f, 20.f); + ImGui::SliderFloat("Value##bar", &m_bar_value, 0.f, 1.f); + ImGui::SliderFloat("Offset##bar", &m_bar_offset, 1.f, 20.f); + ImGui::Checkbox("Right##bar", &m_show_right_bar); ImGui::SameLine(); + ImGui::Checkbox("Left##bar", &m_show_left_bar); + ImGui::Checkbox("Top##bar", &m_show_top_bar); ImGui::SameLine(); + ImGui::Checkbox("Bottom##bar", &m_show_bottom_bar); + } + + if (ImGui::CollapsingHeader("Labels", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Checkbox("Outlined", &m_outlined); + ImGui::SliderFloat("Offset##lbl", &m_label_offset, 0.f, 15.f); + ImGui::Checkbox("Right##lbl", &m_show_right_labels); ImGui::SameLine(); + ImGui::Checkbox("Left##lbl", &m_show_left_labels); + ImGui::Checkbox("Top##lbl", &m_show_top_labels); ImGui::SameLine(); + ImGui::Checkbox("Bottom##lbl", &m_show_bottom_labels); + ImGui::Checkbox("Ctr top##lbl", &m_show_centered_top); ImGui::SameLine(); + ImGui::Checkbox("Ctr bot##lbl", &m_show_centered_bottom); + } + + if (ImGui::CollapsingHeader("Skeleton")) + { + ImGui::Checkbox("Show##skel", &m_show_skeleton); + ImGui::ColorEdit4("Color##skel", reinterpret_cast(&m_skel_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Thick##skel", &m_skel_thickness, 0.5f, 5.f); + } + + if (ImGui::CollapsingHeader("Snap Line")) + { + ImGui::Checkbox("Show##snap", &m_show_snap); + ImGui::ColorEdit4("Color##snap", reinterpret_cast(&m_snap_color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Width##snap", &m_snap_width, 0.5f, 5.f); + } + + ImGui::PopItemWidth(); + ImGui::End(); + } + + void MainWindow::draw_overlay() + { + const auto* vp = ImGui::GetMainViewport(); + + omath::hud::EntityOverlay ent( + {m_entity_x, m_entity_top_y}, {m_entity_x, m_entity_bottom_y}, + std::make_shared()); + + if (m_show_box) + ent.add_2d_box(m_box_color, m_box_fill, m_box_thickness); + if (m_show_cornered_box) + ent.add_cornered_2d_box(omath::Color::from_rgba(255, 0, 255, 255), m_box_fill, m_corner_ratio, m_box_thickness); + if (m_show_dashed_box) + ent.add_dashed_box(m_dash_color, m_dash_len, m_dash_gap, m_dash_thickness); + + if (m_show_right_bar) + ent.add_right_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); + if (m_show_left_bar) + ent.add_left_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); + if (m_show_top_bar) + ent.add_top_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); + if (m_show_bottom_bar) + ent.add_bottom_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); + + if (m_show_right_labels) + { + ent.add_right_label({0.f, 1.f, 0.f, 1.f}, m_label_offset, m_outlined, "Health: {}/100", 100); + ent.add_right_label({1.f, 0.f, 0.f, 1.f}, m_label_offset, m_outlined, "Shield: {}/125", 125); + ent.add_right_label({1.f, 0.f, 1.f, 1.f}, m_label_offset, m_outlined, "*LOCKED*"); + } + if (m_show_left_labels) + { + ent.add_left_label(omath::Color::from_rgba(255, 128, 0, 255), m_label_offset, m_outlined, "Armor: 75"); + ent.add_left_label(omath::Color::from_rgba(0, 200, 255, 255), m_label_offset, m_outlined, "Level: 42"); + } + if (m_show_top_labels) + { + ent.add_top_label(omath::Color::from_rgba(255, 255, 0, 255), m_label_offset, m_outlined, "*SCOPED*"); + ent.add_top_label(omath::Color::from_rgba(255, 0, 0, 255), m_label_offset, m_outlined, "*BLEEDING*"); + } + if (m_show_centered_top) + ent.add_centered_top_label(omath::Color::from_rgba(0, 255, 255, 255), m_label_offset, m_outlined, "*VISIBLE*"); + if (m_show_centered_bottom) + ent.add_centered_bottom_label(omath::Color::from_rgba(255, 255, 255, 255), m_label_offset, m_outlined, "PlayerName"); + if (m_show_bottom_labels) + ent.add_bottom_label(omath::Color::from_rgba(200, 200, 0, 255), m_label_offset, m_outlined, "42m"); + + if (m_show_skeleton) + ent.add_skeleton(m_skel_color, m_skel_thickness); + if (m_show_snap) + ent.add_snap_line({vp->Size.x / 2.f, vp->Size.y}, m_snap_color, m_snap_width); + } + + void MainWindow::present() + { + int w, h; + glfwGetFramebufferSize(m_window, &w, &h); + glViewport(0, 0, w, h); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + glfwSwapBuffers(m_window); + } } // namespace imgui_desktop::gui diff --git a/examples/example_hud/gui/main_window.hpp b/examples/example_hud/gui/main_window.hpp index f8eb072e..d57590db 100644 --- a/examples/example_hud/gui/main_window.hpp +++ b/examples/example_hud/gui/main_window.hpp @@ -1,11 +1,8 @@ -// -// Created by Vlad on 6/17/2025. -// - // // Created by Orange on 11/11/2024. // #pragma once +#include #include struct GLFWwindow; @@ -15,14 +12,54 @@ namespace imgui_desktop::gui class MainWindow { public: - MainWindow(const std::string_view &caption, int width, int height); - + MainWindow(const std::string_view& caption, int width, int height); void Run(); private: - GLFWwindow* m_window; + void draw_controls(); + void draw_overlay(); + void present(); + + GLFWwindow* m_window = nullptr; static bool m_canMoveWindow; bool m_opened = true; + + // Entity + float m_entity_x = 550.f, m_entity_top_y = 150.f, m_entity_bottom_y = 450.f; + + // Box + omath::Color m_box_color{1.f, 1.f, 1.f, 1.f}; + omath::Color m_box_fill{0.f, 0.f, 0.f, 0.f}; + float m_box_thickness = 1.f, m_corner_ratio = 0.2f; + bool m_show_box = true, m_show_cornered_box = true, m_show_dashed_box = false; + + // Dashed box + omath::Color m_dash_color = omath::Color::from_rgba(255, 200, 0, 255); + float m_dash_len = 8.f, m_dash_gap = 5.f, m_dash_thickness = 1.f; + + // Bars + omath::Color m_bar_color{0.f, 1.f, 0.f, 1.f}; + omath::Color m_bar_bg_color{0.f, 0.f, 0.f, 0.5f}; + omath::Color m_bar_outline_color{0.f, 0.f, 0.f, 1.f}; + float m_bar_width = 4.f, m_bar_value = 0.75f, m_bar_offset = 5.f; + bool m_show_right_bar = true, m_show_left_bar = true; + bool m_show_top_bar = true, m_show_bottom_bar = true; + + // Labels + float m_label_offset = 3.f; + bool m_outlined = true; + bool m_show_right_labels = true, m_show_left_labels = true; + bool m_show_top_labels = true, m_show_bottom_labels = true; + bool m_show_centered_top = true, m_show_centered_bottom = true; + + // Skeleton + omath::Color m_skel_color = omath::Color::from_rgba(255, 255, 255, 200); + float m_skel_thickness = 1.f; + bool m_show_skeleton = false; + + // Snap line + omath::Color m_snap_color = omath::Color::from_rgba(255, 50, 50, 255); + float m_snap_width = 1.5f; + bool m_show_snap = true; }; -} // gui -// imgui_desktop \ No newline at end of file +} // namespace imgui_desktop::gui From 56256c40fb50fb6d99d0e64161c259f4279419d2 Mon Sep 17 00:00:00 2001 From: Orange Date: Sun, 15 Mar 2026 13:47:41 +0300 Subject: [PATCH 9/9] cleaned code --- examples/example_hud/gui/main_window.cpp | 23 ++++++++++++++++++----- examples/example_hud/gui/main_window.hpp | 4 ++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index b54be5a2..0cafd8ea 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -141,13 +141,28 @@ namespace imgui_desktop::gui {m_entity_x, m_entity_top_y}, {m_entity_x, m_entity_bottom_y}, std::make_shared()); + draw_boxes(ent); + draw_bars(ent); + draw_labels(ent); + + if (m_show_skeleton) + ent.add_skeleton(m_skel_color, m_skel_thickness); + if (m_show_snap) + ent.add_snap_line({vp->Size.x / 2.f, vp->Size.y}, m_snap_color, m_snap_width); + } + + void MainWindow::draw_boxes(omath::hud::EntityOverlay& ent) const + { if (m_show_box) ent.add_2d_box(m_box_color, m_box_fill, m_box_thickness); if (m_show_cornered_box) ent.add_cornered_2d_box(omath::Color::from_rgba(255, 0, 255, 255), m_box_fill, m_corner_ratio, m_box_thickness); if (m_show_dashed_box) ent.add_dashed_box(m_dash_color, m_dash_len, m_dash_gap, m_dash_thickness); + } + void MainWindow::draw_bars(omath::hud::EntityOverlay& ent) const + { if (m_show_right_bar) ent.add_right_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); if (m_show_left_bar) @@ -156,7 +171,10 @@ namespace imgui_desktop::gui ent.add_top_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); if (m_show_bottom_bar) ent.add_bottom_bar(m_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, m_bar_value, m_bar_offset); + } + void MainWindow::draw_labels(omath::hud::EntityOverlay& ent) const + { if (m_show_right_labels) { ent.add_right_label({0.f, 1.f, 0.f, 1.f}, m_label_offset, m_outlined, "Health: {}/100", 100); @@ -179,11 +197,6 @@ namespace imgui_desktop::gui ent.add_centered_bottom_label(omath::Color::from_rgba(255, 255, 255, 255), m_label_offset, m_outlined, "PlayerName"); if (m_show_bottom_labels) ent.add_bottom_label(omath::Color::from_rgba(200, 200, 0, 255), m_label_offset, m_outlined, "42m"); - - if (m_show_skeleton) - ent.add_skeleton(m_skel_color, m_skel_thickness); - if (m_show_snap) - ent.add_snap_line({vp->Size.x / 2.f, vp->Size.y}, m_snap_color, m_snap_width); } void MainWindow::present() diff --git a/examples/example_hud/gui/main_window.hpp b/examples/example_hud/gui/main_window.hpp index d57590db..dc4c8194 100644 --- a/examples/example_hud/gui/main_window.hpp +++ b/examples/example_hud/gui/main_window.hpp @@ -2,6 +2,7 @@ // Created by Orange on 11/11/2024. // #pragma once +#include #include #include @@ -18,6 +19,9 @@ namespace imgui_desktop::gui private: void draw_controls(); void draw_overlay(); + void draw_boxes(omath::hud::EntityOverlay& ent) const; + void draw_bars(omath::hud::EntityOverlay& ent) const; + void draw_labels(omath::hud::EntityOverlay& ent) const; void present(); GLFWwindow* m_window = nullptr;