diff --git a/examples/example_hud/gui/main_window.cpp b/examples/example_hud/gui/main_window.cpp index 73f0e41..e044946 100644 --- a/examples/example_hud/gui/main_window.cpp +++ b/examples/example_hud/gui/main_window.cpp @@ -66,6 +66,19 @@ namespace imgui_desktop::gui ImGui::Begin("Controls", &m_opened, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); ImGui::PushItemWidth(160.f); + const auto draw_glow_controls = [](const char* label, GlowSettings& settings) + { + ImGui::PushID(label); + ImGui::TextUnformatted(label); + ImGui::Checkbox("Glow", &settings.enabled); + if (settings.enabled) + { + ImGui::ColorEdit4("Color", reinterpret_cast(&settings.color), ImGuiColorEditFlags_NoInputs); + ImGui::SliderFloat("Radius", &settings.radius, 1.f, 12.f); + ImGui::SliderFloat("Intensity", &settings.intensity, 0.f, 1.f); + } + ImGui::PopID(); + }; if (ImGui::CollapsingHeader("Entity", ImGuiTreeNodeFlags_DefaultOpen)) { @@ -96,6 +109,8 @@ namespace imgui_desktop::gui ImGui::ColorEdit4("Outline##box", reinterpret_cast(&m_box_outline), ImGuiColorEditFlags_NoInputs); ImGui::SliderFloat("Thickness", &m_box_thickness, 0.5f, 5.f); ImGui::SliderFloat("Corner ratio", &m_corner_ratio, 0.05f, 0.5f); + draw_glow_controls("Box glow", m_box_glow); + draw_glow_controls("Cornered box glow", m_cornered_box_glow); ImGui::Separator(); ImGui::ColorEdit4("Dash color", reinterpret_cast(&m_dash_color), ImGuiColorEditFlags_NoInputs); ImGui::SliderFloat("Dash length", &m_dash_len, 2.f, 30.f); @@ -127,6 +142,7 @@ namespace imgui_desktop::gui ImGui::Checkbox("Bot dashed##bar", &m_show_bottom_dashed_bar); ImGui::SliderFloat("Dash len##bar", &m_bar_dash_len, 2.f, 20.f); ImGui::SliderFloat("Dash gap##bar", &m_bar_dash_gap, 1.f, 15.f); + draw_glow_controls("Bar glow", m_bar_glow); } if (ImGui::CollapsingHeader("Labels", ImGuiTreeNodeFlags_DefaultOpen)) @@ -150,6 +166,7 @@ namespace imgui_desktop::gui ImGui::Checkbox("Ctr top##lbl", &m_show_centered_top); ImGui::SameLine(); ImGui::Checkbox("Ctr bot##lbl", &m_show_centered_bottom); + draw_glow_controls("Label glow", m_label_glow); } if (ImGui::CollapsingHeader("Skeleton")) @@ -229,16 +246,26 @@ namespace imgui_desktop::gui const auto red = omath::Color{1.f, 0.f, 0.f, 1.f}; const auto green = omath::Color{0.f, 1.f, 0.f, 1.f}; const auto bar_value_color = omath::Color{red.value() * (1.f - m_bar_value) + green.value() * m_bar_value}; + const auto make_glow = [](const GlowSettings& settings) -> std::optional + { + if (!settings.enabled) + return std::nullopt; + return Glow{settings.color, settings.radius, settings.intensity}; + }; + const auto box_glow = make_glow(m_box_glow); + const auto cornered_box_glow = make_glow(m_cornered_box_glow); + const auto bar_glow = make_glow(m_bar_glow); + const auto label_glow = make_glow(m_label_glow); const Paint vertical_bar_color = m_gradient_bars ? Paint{omath::hud::Gradient{bar_value_color, bar_value_color, red, red}} : Paint{m_bar_color}; const Paint horizontal_bar_color = m_gradient_bars ? Paint{omath::hud::Gradient{red, bar_value_color, bar_value_color, red}} : Paint{m_bar_color}; - const Bar vertical_bar{vertical_bar_color, m_bar_outline_color, m_bar_bg_color, - m_bar_width, m_bar_value, m_bar_offset}; - const Bar horizontal_bar{horizontal_bar_color, m_bar_outline_color, m_bar_bg_color, - m_bar_width, m_bar_value, m_bar_offset}; + const Bar vertical_bar{vertical_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, + m_bar_value, m_bar_offset, bar_glow}; + const Bar horizontal_bar{horizontal_bar_color, m_bar_outline_color, m_bar_bg_color, m_bar_width, + m_bar_value, m_bar_offset, bar_glow}; const Paint box_fill = m_gradient_box_fill ? Paint{omath::hud::Gradient{box_gradient_top, box_gradient_top, box_gradient_bottom, box_gradient_bottom}} @@ -257,9 +284,10 @@ namespace imgui_desktop::gui std::make_shared()) .contents( // ── Boxes ──────────────────────────────────────────────────── - when(m_show_box, Box{m_box_color, box_fill, m_box_outline, m_box_thickness}), - when(m_show_cornered_box, CorneredBox{omath::Color::from_rgba(255, 0, 255, 255), m_box_fill, - m_box_outline, m_corner_ratio, m_box_thickness}), + when(m_show_box, Box{m_box_color, box_fill, m_box_outline, m_box_thickness, box_glow}), + when(m_show_cornered_box, + CorneredBox{omath::Color::from_rgba(255, 0, 255, 255), m_box_fill, m_box_outline, + m_corner_ratio, m_box_thickness, cornered_box_glow}), when(m_show_dashed_box, DashedBox{m_dash_color, m_dash_len, m_dash_gap, m_dash_thickness}), RightSide{ when(m_show_right_bar, vertical_bar), @@ -307,7 +335,7 @@ namespace imgui_desktop::gui when(m_show_bottom_dashed_bar, dbar), when(m_show_centered_bottom, Centered{Label{centered_label_color, m_label_offset, outline_helper(m_outlined), - "Gradient PlayerName"}}), + "Gradient PlayerName", label_glow}}), when(m_show_bottom_labels, Label{omath::Color::from_rgba(200, 200, 0, 255), m_label_offset, outline_helper(m_outlined), "42m"}), }, diff --git a/examples/example_hud/gui/main_window.hpp b/examples/example_hud/gui/main_window.hpp index 153adc6..26e3ef2 100644 --- a/examples/example_hud/gui/main_window.hpp +++ b/examples/example_hud/gui/main_window.hpp @@ -17,6 +17,14 @@ namespace imgui_desktop::gui void Run(); private: + struct GlowSettings + { + omath::Color color{0.f, 0.7f, 1.f, 0.8f}; + float radius = 4.f; + float intensity = 0.8f; + bool enabled = false; + }; + void draw_controls(); void draw_overlay(); void present(); @@ -64,6 +72,11 @@ namespace imgui_desktop::gui bool m_show_top_labels = true, m_show_bottom_labels = true; bool m_show_centered_top = true, m_show_centered_bottom = true; + GlowSettings m_box_glow; + GlowSettings m_cornered_box_glow{{1.f, 0.f, 1.f, 0.8f}}; + GlowSettings m_bar_glow{{1.f, 0.f, 0.f, 0.8f}}; + GlowSettings m_label_glow; + // Skeleton omath::Color m_skel_color = omath::Color::from_rgba(255, 255, 255, 200); float m_skel_thickness = 1.f; diff --git a/include/omath/hud/entity_overlay.hpp b/include/omath/hud/entity_overlay.hpp index e2bf608..f8b3712 100644 --- a/include/omath/hud/entity_overlay.hpp +++ b/include/omath/hud/entity_overlay.hpp @@ -42,16 +42,20 @@ namespace omath::hud // ── Bars ───────────────────────────────────────────────────────── EntityOverlay& add_right_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, - float width, float ratio, float offset = 5.f); + float width, float ratio, float offset = 5.f, + const std::optional& glow = std::nullopt); EntityOverlay& add_left_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, - float width, float ratio, float offset = 5.f); + float width, float ratio, float offset = 5.f, + const std::optional& glow = std::nullopt); EntityOverlay& add_top_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, - float height, float ratio, float offset = 5.f); + float height, float ratio, float offset = 5.f, + const std::optional& glow = std::nullopt); EntityOverlay& add_bottom_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, - float height, float ratio, float offset = 5.f); + float height, float ratio, float offset = 5.f, + const std::optional& glow = std::nullopt); EntityOverlay& add_right_dashed_bar(const Color& color, const Color& outline_color, const Color& bg_color, float width, float ratio, float dash_len, float gap_len, @@ -69,22 +73,26 @@ namespace omath::hud // ── Labels ─────────────────────────────────────────────────────── EntityOverlay& add_right_label(const widget::Paint& color, float offset, widget::Outlined outlined, - const std::string_view& text); + const std::string_view& text, + const std::optional& glow = std::nullopt); EntityOverlay& add_left_label(const widget::Paint& color, float offset, widget::Outlined outlined, - const std::string_view& text); + const std::string_view& text, + const std::optional& glow = std::nullopt); EntityOverlay& add_top_label(const widget::Paint& color, float offset, widget::Outlined outlined, - std::string_view text); + std::string_view text, const std::optional& glow = std::nullopt); EntityOverlay& add_bottom_label(const widget::Paint& color, float offset, widget::Outlined outlined, - std::string_view text); + std::string_view text, const std::optional& glow = std::nullopt); EntityOverlay& add_centered_top_label(const widget::Paint& color, float offset, widget::Outlined outlined, - const std::string_view& text); + const std::string_view& text, + const std::optional& glow = std::nullopt); EntityOverlay& add_centered_bottom_label(const widget::Paint& color, float offset, widget::Outlined outlined, - const std::string_view& text); + const std::string_view& text, + const std::optional& glow = std::nullopt); template requires(sizeof...(Args) > 0) @@ -253,7 +261,13 @@ namespace omath::hud void dispatch(const widget::ProjectileAim& proj_widget); void draw_progress_ring(const Vector2& center, const widget::ProgressRing& ring); void draw_label(const Vector2& position, const widget::Paint& paint, widget::Outlined outlined, - const std::string_view& text); + const std::string_view& text, const std::optional& glow); + void draw_glow_polyline(const std::span>& points, const widget::Glow& glow, + float thickness) const; + void draw_glow_line(const Vector2& from, const Vector2& to, const widget::Glow& glow, + float thickness) const; + void draw_glow_rectangle(const Vector2& min, const Vector2& max, + const std::optional& glow) const; void draw_filled_rectangle(const Vector2& min, const Vector2& max, const widget::Paint& paint) const; void draw_dashed_line(const Vector2& from, const Vector2& to, const Color& color, float dash_len, diff --git a/include/omath/hud/entity_overlay_widgets.hpp b/include/omath/hud/entity_overlay_widgets.hpp index aefb2ef..5c4d1b9 100644 --- a/include/omath/hud/entity_overlay_widgets.hpp +++ b/include/omath/hud/entity_overlay_widgets.hpp @@ -32,6 +32,13 @@ namespace omath::hud::widget template Overloaded(Ts...) -> Overloaded; + struct Glow + { + Color color; + float radius = 4.f; + float intensity = 1.f; + }; + // ── Standalone widgets ──────────────────────────────────────────────────── struct Box { @@ -39,6 +46,7 @@ namespace omath::hud::widget Paint fill{Color{0.f, 0.f, 0.f, 0.f}}; Color outline{0.f, 0.f, 0.f, 0.f}; float thickness = 1.f; + std::optional glow = std::nullopt; }; enum class Outlined @@ -53,6 +61,7 @@ namespace omath::hud::widget Color outline{0.f, 0.f, 0.f, 0.f}; float corner_ratio = 0.2f; float thickness = 1.f; + std::optional glow = std::nullopt; }; struct DashedBox @@ -114,6 +123,7 @@ namespace omath::hud::widget float size; float ratio; float offset = 5.f; + std::optional glow = std::nullopt; }; /// A dashed bar. Same field semantics as Bar plus dash parameters. @@ -135,6 +145,7 @@ namespace omath::hud::widget float offset; Outlined outlined; std::string_view text; + std::optional glow = std::nullopt; }; /// Wraps a Label to request horizontal centering (only applied in TopSide / BottomSide). diff --git a/source/hud/entity_overlay.cpp b/source/hud/entity_overlay.cpp index b33c534..ef22d62 100644 --- a/source/hud/entity_overlay.cpp +++ b/source/hud/entity_overlay.cpp @@ -78,7 +78,7 @@ namespace omath::hud } EntityOverlay& EntityOverlay::add_right_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, const float width, float ratio, - const float offset) + const float offset, const std::optional& glow) { ratio = std::clamp(ratio, 0.f, 1.f); const auto max_bar_height = std::abs(m_canvas.top_right_corner.y - m_canvas.bottom_right_corner.y); @@ -86,6 +86,7 @@ namespace omath::hud const auto bar_start = Vector2{m_text_cursor_right.x + offset, m_canvas.bottom_right_corner.y}; m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(width, -max_bar_height), bg_color); + draw_glow_rectangle(bar_start, bar_start + Vector2(width, -max_bar_height * ratio), glow); draw_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); @@ -96,7 +97,7 @@ namespace omath::hud } EntityOverlay& EntityOverlay::add_left_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, const float width, float ratio, - const float offset) + const float offset, const std::optional& glow) { 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); @@ -104,6 +105,7 @@ namespace omath::hud const auto bar_start = Vector2{m_text_cursor_left.x - (offset + width), m_canvas.bottom_left_corner.y}; m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(width, -max_bar_height), bg_color); + draw_glow_rectangle(bar_start, bar_start + Vector2(width, -max_bar_height * ratio), glow); draw_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); @@ -113,26 +115,28 @@ namespace omath::hud return *this; } EntityOverlay& EntityOverlay::add_right_label(const widget::Paint& color, const float offset, - const widget::Outlined outlined, const std::string_view& text) + const widget::Outlined outlined, const std::string_view& text, + const std::optional& glow) { - draw_label(m_text_cursor_right + Vector2{offset, 0.f}, color, outlined, text); + draw_label(m_text_cursor_right + Vector2{offset, 0.f}, color, outlined, text, glow); m_text_cursor_right.y += m_renderer->calc_text_size(text.data()).y; return *this; } EntityOverlay& EntityOverlay::add_top_label(const widget::Paint& color, const float offset, - const widget::Outlined outlined, const std::string_view text) + const widget::Outlined outlined, const std::string_view text, + const std::optional& glow) { m_text_cursor_top.y -= m_renderer->calc_text_size(text.data()).y; - draw_label(m_text_cursor_top + Vector2{0.f, -offset}, color, outlined, text); + draw_label(m_text_cursor_top + Vector2{0.f, -offset}, color, outlined, text, glow); return *this; } EntityOverlay& EntityOverlay::add_top_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, const float height, float ratio, - const float offset) + const float offset, const std::optional& glow) { ratio = std::clamp(ratio, 0.f, 1.f); const auto max_bar_width = std::abs(m_canvas.top_left_corner.x - m_canvas.bottom_right_corner.x); @@ -140,6 +144,7 @@ namespace omath::hud const auto bar_start = Vector2{m_canvas.top_left_corner.x, m_text_cursor_top.y - offset}; m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(max_bar_width, -height), bg_color); + draw_glow_rectangle(bar_start, bar_start + Vector2(max_bar_width * ratio, -height), glow); draw_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); @@ -375,8 +380,35 @@ namespace omath::hud } void EntityOverlay::draw_label(const Vector2& position, const widget::Paint& paint, - const widget::Outlined outlined, const std::string_view& text) + const widget::Outlined outlined, const std::string_view& text, + const std::optional& glow) { + if (glow) + { + const int radius = static_cast(std::ceil(std::max(glow->radius, 0.f))); + for (int layer = radius; layer > 0; --layer) + { + const float alpha = glow->color.value().w * std::clamp(glow->intensity, 0.f, 1.f) + * (1.f - static_cast(layer - 1) / static_cast(radius + 1)); + const auto value = glow->color.value(); + const Color color{value.x, value.y, value.z, alpha / static_cast(radius)}; + for (int x = -layer; x <= layer; ++x) + { + m_renderer->add_text(position + Vector2{static_cast(x), static_cast(-layer)}, + color, text); + m_renderer->add_text(position + Vector2{static_cast(x), static_cast(layer)}, + color, text); + } + for (int y = -layer + 1; y < layer; ++y) + { + m_renderer->add_text(position + Vector2{static_cast(-layer), static_cast(y)}, + color, text); + m_renderer->add_text(position + Vector2{static_cast(layer), static_cast(y)}, + color, text); + } + } + } + if (outlined == widget::Outlined::On) { static constexpr std::array outline_offsets = { @@ -401,6 +433,49 @@ namespace omath::hud paint); } + void EntityOverlay::draw_glow_polyline(const std::span>& points, const widget::Glow& glow, + const float thickness) const + { + const int radius = static_cast(std::ceil(std::max(glow.radius, 0.f))); + const auto value = glow.color.value(); + for (int layer = radius; layer > 0; --layer) + { + const float falloff = 1.f - static_cast(layer - 1) / static_cast(radius + 1); + const Color color{value.x, value.y, value.z, + value.w * std::clamp(glow.intensity, 0.f, 1.f) * falloff / static_cast(radius)}; + m_renderer->add_polyline(points, color, thickness + static_cast(layer) * 2.f); + } + } + + void EntityOverlay::draw_glow_line(const Vector2& from, const Vector2& to, const widget::Glow& glow, + const float thickness) const + { + const int radius = static_cast(std::ceil(std::max(glow.radius, 0.f))); + const auto value = glow.color.value(); + for (int layer = radius; layer > 0; --layer) + { + const float falloff = 1.f - static_cast(layer - 1) / static_cast(radius + 1); + const Color color{value.x, value.y, value.z, + value.w * std::clamp(glow.intensity, 0.f, 1.f) * falloff / static_cast(radius)}; + m_renderer->add_line(from, to, color, thickness + static_cast(layer) * 2.f); + } + } + + void EntityOverlay::draw_glow_rectangle(const Vector2& min, const Vector2& max, + const std::optional& glow) const + { + if (!glow || glow->radius <= 0.f) + return; + + const std::array points = { + Vector2{std::min(min.x, max.x), std::min(min.y, max.y)}, + Vector2{std::max(min.x, max.x), std::min(min.y, max.y)}, + Vector2{std::max(min.x, max.x), std::max(min.y, max.y)}, + Vector2{std::min(min.x, max.x), std::max(min.y, max.y)}, + }; + draw_glow_polyline(points, *glow, 1.f); + } + void EntityOverlay::draw_filled_rectangle(const Vector2& min, const Vector2& max, const widget::Paint& paint) const { @@ -421,13 +496,14 @@ namespace omath::hud } EntityOverlay& EntityOverlay::add_bottom_bar(const widget::Paint& color, const Color& outline_color, const Color& bg_color, const float height, float ratio, - const float offset) + const float offset, const std::optional& glow) { 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 = Vector2{m_canvas.bottom_left_corner.x, m_text_cursor_bottom.y + offset}; m_renderer->add_filled_rectangle(bar_start, bar_start + Vector2(max_bar_width, height), bg_color); + draw_glow_rectangle(bar_start, bar_start + Vector2(max_bar_width * ratio, height), glow); draw_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); @@ -437,11 +513,12 @@ namespace omath::hud } EntityOverlay& EntityOverlay::add_bottom_label(const widget::Paint& color, const float offset, - const widget::Outlined outlined, const std::string_view text) + const widget::Outlined outlined, const std::string_view text, + const std::optional& glow) { const auto text_size = m_renderer->calc_text_size(text); - draw_label(m_text_cursor_bottom + Vector2{0.f, offset}, color, outlined, text); + draw_label(m_text_cursor_bottom + Vector2{0.f, offset}, color, outlined, text, glow); m_text_cursor_bottom.y += text_size.y; @@ -449,12 +526,13 @@ namespace omath::hud } EntityOverlay& EntityOverlay::add_left_label(const widget::Paint& color, const float offset, - const widget::Outlined outlined, const std::string_view& text) + const widget::Outlined outlined, const std::string_view& text, + const std::optional& glow) { const auto text_size = m_renderer->calc_text_size(text); const auto pos = m_text_cursor_left + Vector2{-(offset + text_size.x), 0.f}; - draw_label(pos, color, outlined, text); + draw_label(pos, color, outlined, text, glow); m_text_cursor_left.y += text_size.y; @@ -463,14 +541,15 @@ namespace omath::hud EntityOverlay& EntityOverlay::add_centered_bottom_label(const widget::Paint& color, const float offset, const widget::Outlined outlined, - const std::string_view& text) + const std::string_view& text, + const std::optional& glow) { 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}; - draw_label(pos, color, outlined, text); + draw_label(pos, color, outlined, text, glow); m_text_cursor_bottom.y += text_size.y; @@ -478,7 +557,8 @@ namespace omath::hud } EntityOverlay& EntityOverlay::add_centered_top_label(const widget::Paint& color, const float offset, - const widget::Outlined outlined, const std::string_view& text) + const widget::Outlined outlined, const std::string_view& text, + const std::optional& glow) { const auto text_size = m_renderer->calc_text_size(text); const auto box_center_x = @@ -487,7 +567,7 @@ namespace omath::hud 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}; - draw_label(pos, color, outlined, text); + draw_label(pos, color, outlined, text, glow); return *this; } @@ -633,6 +713,11 @@ namespace omath::hud // ── widget dispatch ─────────────────────────────────────────────────────── void EntityOverlay::dispatch(const widget::Box& box) { + if (box.glow) + { + const auto points = m_canvas.as_array(); + draw_glow_polyline(points, *box.glow, box.thickness); + } std::visit( [&](const auto& fill) { @@ -643,6 +728,23 @@ namespace omath::hud void EntityOverlay::dispatch(const widget::CorneredBox& cornered_box) { + if (cornered_box.glow) + { + const float length = + std::abs(m_canvas.top_left_corner.x - m_canvas.top_right_corner.x) * cornered_box.corner_ratio; + const std::array lines = { + std::pair{m_canvas.top_left_corner, m_canvas.top_left_corner + Vector2{length, 0.f}}, + std::pair{m_canvas.top_left_corner, m_canvas.top_left_corner + Vector2{0.f, length}}, + std::pair{m_canvas.bottom_left_corner, m_canvas.bottom_left_corner - Vector2{0.f, length}}, + std::pair{m_canvas.bottom_left_corner, m_canvas.bottom_left_corner + Vector2{length, 0.f}}, + std::pair{m_canvas.top_right_corner, m_canvas.top_right_corner - Vector2{length, 0.f}}, + std::pair{m_canvas.top_right_corner, m_canvas.top_right_corner + Vector2{0.f, length}}, + std::pair{m_canvas.bottom_right_corner, m_canvas.bottom_right_corner - Vector2{0.f, length}}, + std::pair{m_canvas.bottom_right_corner, m_canvas.bottom_right_corner - Vector2{length, 0.f}}, + }; + for (const auto& [from, to] : lines) + draw_glow_line(from, to, *cornered_box.glow, cornered_box.thickness); + } add_cornered_2d_box(cornered_box.color, cornered_box.fill, cornered_box.outline, cornered_box.corner_ratio, cornered_box.thickness); } @@ -741,7 +843,7 @@ namespace omath::hud }, [this](const widget::Bar& w) { - add_right_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset); + add_right_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset, w.glow); }, [this](const widget::DashedBar& w) { @@ -750,11 +852,12 @@ namespace omath::hud }, [this](const widget::Label& w) { - add_right_label(w.color, w.offset, w.outlined, w.text); + add_right_label(w.color, w.offset, w.outlined, w.text, w.glow); }, [this](const widget::Centered& w) { - add_right_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); + add_right_label(w.child.color, w.child.offset, w.child.outlined, w.child.text, + w.child.glow); }, [this](const widget::SpaceVertical& w) { @@ -787,7 +890,7 @@ namespace omath::hud }, [this](const widget::Bar& w) { - add_left_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset); + add_left_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset, w.glow); }, [this](const widget::DashedBar& w) { @@ -796,11 +899,12 @@ namespace omath::hud }, [this](const widget::Label& w) { - add_left_label(w.color, w.offset, w.outlined, w.text); + add_left_label(w.color, w.offset, w.outlined, w.text, w.glow); }, [this](const widget::Centered& w) { - add_left_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); + add_left_label(w.child.color, w.child.offset, w.child.outlined, w.child.text, + w.child.glow); }, [this](const widget::SpaceVertical& w) { @@ -833,7 +937,7 @@ namespace omath::hud }, [this](const widget::Bar& w) { - add_top_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset); + add_top_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset, w.glow); }, [this](const widget::DashedBar& w) { @@ -842,11 +946,12 @@ namespace omath::hud }, [this](const widget::Label& w) { - add_top_label(w.color, w.offset, w.outlined, w.text); + add_top_label(w.color, w.offset, w.outlined, w.text, w.glow); }, [this](const widget::Centered& w) { - add_centered_top_label(w.child.color, w.child.offset, w.child.outlined, w.child.text); + add_centered_top_label(w.child.color, w.child.offset, w.child.outlined, w.child.text, + w.child.glow); }, [this](const widget::SpaceVertical& w) { @@ -878,7 +983,7 @@ namespace omath::hud }, [this](const widget::Bar& w) { - add_bottom_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset); + add_bottom_bar(w.color, w.outline, w.bg, w.size, w.ratio, w.offset, w.glow); }, [this](const widget::DashedBar& w) { @@ -887,12 +992,12 @@ namespace omath::hud }, [this](const widget::Label& w) { - add_bottom_label(w.color, w.offset, w.outlined, w.text); + add_bottom_label(w.color, w.offset, w.outlined, w.text, w.glow); }, [this](const widget::Centered& w) { - add_centered_bottom_label(w.child.color, w.child.offset, w.child.outlined, - w.child.text); + add_centered_bottom_label(w.child.color, w.child.offset, w.child.outlined, w.child.text, + w.child.glow); }, [this](const widget::SpaceVertical& w) {