From b75cacf52561f1e1ceef2c245c9749e7f3c43e73 Mon Sep 17 00:00:00 2001 From: Albin Johansson Date: Sun, 25 Aug 2024 22:30:55 +0200 Subject: [PATCH] Move primitive rendering functions --- source/core/CMakeLists.txt | 1 + .../inc/tactile/core/ui/canvas_renderer.hpp | 57 --------- .../inc/tactile/core/ui/render/primitives.hpp | 113 ++++++++++++++++++ .../src/tactile/core/ui/canvas_renderer.cpp | 67 +---------- 4 files changed, 117 insertions(+), 121 deletions(-) create mode 100644 source/core/inc/tactile/core/ui/render/primitives.hpp diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index cd612622fb..365da9f42e 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -259,6 +259,7 @@ target_sources(tactile-core "inc/tactile/core/ui/menu/tileset_menu.hpp" "inc/tactile/core/ui/menu/view_menu.hpp" "inc/tactile/core/ui/render/hexagon_info.hpp" + "inc/tactile/core/ui/render/primitives.hpp" "inc/tactile/core/ui/canvas_overlay.hpp" "inc/tactile/core/ui/canvas_renderer.hpp" "inc/tactile/core/ui/fonts.hpp" diff --git a/source/core/inc/tactile/core/ui/canvas_renderer.hpp b/source/core/inc/tactile/core/ui/canvas_renderer.hpp index 75df059748..51b814a05f 100644 --- a/source/core/inc/tactile/core/ui/canvas_renderer.hpp +++ b/source/core/inc/tactile/core/ui/canvas_renderer.hpp @@ -86,63 +86,6 @@ class CanvasRenderer final ~CanvasRenderer() noexcept; - /** - * Renders a rectangle. - * - * \param screen_pos The rectangle position, in screen-space. - * \param size The rectangle size. - * \param color The line color. - * \param thickness The line thickness. - */ - static void draw_rect(const Float2& screen_pos, - const Float2& size, - const UColor& color, - float thickness = 1.0f); - - /** - * Renders a filled rectangle. - * - * \param screen_pos The rectangle position, in screen-space. - * \param size The rectangle size. - * \param color The fill color. - */ - static void fill_rect(const Float2& screen_pos, const Float2& size, const UColor& color); - - /** - * Renders an N-sided polygon. - * - * \param screen_pos The center position of the polygon, in screen-space. - * \param radius The radius of the polygon. - * \param color_mask The ABGR line color mask. - * \param segment_count The number of sides (the "N" in N-gon). - * \param thickness The line thickness. - * \param angle The polygon rotation, in radians. - */ - static void draw_ngon(const Float2& screen_pos, - float radius, - uint32 color_mask, - int segment_count, - float thickness = 1.0f, - float angle = 0.0f); - - /** - * Renders a hexagon. - * - * \details - * The rendered hexagon will feature an vertex immediately above the provided - * center point, as if rendered via \c draw_ngon() with an angle of Pi divided - * by two. - * - * \param screen_pos The center position of the hexagon, in screen-space. - * \param radius The radius of the hexagon. - * \param color_mask The ABGR line color mask. - * \param thickness The line thickness. - */ - static void draw_hexagon(const Float2& screen_pos, - float radius, - uint32 color_mask, - float thickness = 1.0f); - /** * Clears the canvas with a given color. * diff --git a/source/core/inc/tactile/core/ui/render/primitives.hpp b/source/core/inc/tactile/core/ui/render/primitives.hpp new file mode 100644 index 0000000000..455e5c54ea --- /dev/null +++ b/source/core/inc/tactile/core/ui/render/primitives.hpp @@ -0,0 +1,113 @@ +// Copyright (C) 2024 Albin Johansson (GNU General Public License v3.0) + +#pragma once + +#include // pi_v + +#include + +#include "tactile/base/meta/color.hpp" +#include "tactile/base/numeric/vec.hpp" +#include "tactile/base/prelude.hpp" +#include "tactile/core/meta/color.hpp" +#include "tactile/core/ui/imgui_compat.hpp" + +namespace tactile::ui { + +/** + * Renders a rectangle. + * + * \param screen_pos The rectangle position, in screen-space. + * \param size The rectangle size. + * \param color The line color. + * \param thickness The line thickness. + */ +inline void draw_rect(const Float2& screen_pos, + const Float2& size, + const UColor& color, + const float thickness = 1.0f) +{ + if (auto* draw_list = ImGui::GetWindowDrawList()) { + draw_list->AddRect(to_imvec2(screen_pos), + to_imvec2(screen_pos + size), + to_uint32_abgr(color), + 0.0f, + ImDrawFlags_None, + thickness); + } +} + +/** + * Renders a filled rectangle. + * + * \param screen_pos The rectangle position, in screen-space. + * \param size The rectangle size. + * \param color The fill color. + */ +inline void fill_rect(const Float2& screen_pos, const Float2& size, const UColor& color) +{ + if (auto* draw_list = ImGui::GetWindowDrawList()) { + draw_list->AddRectFilled(to_imvec2(screen_pos), + to_imvec2(screen_pos + size), + to_uint32_abgr(color)); + } +} + +/** + * Renders an N-sided polygon. + * + * \param screen_pos The center position of the polygon, in screen-space. + * \param radius The radius of the polygon. + * \param color_mask The ABGR line color mask. + * \param segment_count The number of sides (the "N" in N-gon). + * \param thickness The line thickness. + * \param angle The polygon rotation, in radians. + */ +inline void draw_ngon(const Float2& screen_pos, + const float radius, + const uint32 color_mask, + const int segment_count, + const float thickness = 1.0f, + const float angle = 0.0f) +{ + if ((color_mask & IM_COL32_A_MASK) == 0 || segment_count <= 2) { + return; + } + + // We're drawing a closed shape, so we remove one of the segments/points. + const auto segment_max = + static_cast(segment_count - 1) / static_cast(segment_count); + const auto angle_max = 2.0f * std::numbers::pi_v * segment_max; + + if (auto* draw_list = ImGui::GetWindowDrawList()) { + draw_list->PathArcTo(to_imvec2(screen_pos), + radius, + angle, + angle + angle_max, + segment_count - 1); + draw_list->PathStroke(color_mask, ImDrawFlags_Closed, thickness); + } +} + +/** + * Renders a hexagon. + * + * \details + * The rendered hexagon will feature a vertex immediately above the provided center point, as + * if rendered via \c draw_ngon with an angle of half Pi. + * + * \param screen_pos The center position of the hexagon, in screen-space. + * \param radius The radius of the hexagon. + * \param color_mask The ABGR line color mask. + * \param thickness The line thickness. + */ +inline void draw_hexagon(const Float2& screen_pos, + const float radius, + const uint32 color_mask, + const float thickness = 1.0f) +{ + constexpr auto half_pi = 0.5f * std::numbers::pi_v; + draw_ngon(screen_pos, radius, color_mask, 6, thickness, half_pi); +} + +} // namespace tactile::ui diff --git a/source/core/src/tactile/core/ui/canvas_renderer.cpp b/source/core/src/tactile/core/ui/canvas_renderer.cpp index a2e006cc0a..f0ea160e9c 100644 --- a/source/core/src/tactile/core/ui/canvas_renderer.cpp +++ b/source/core/src/tactile/core/ui/canvas_renderer.cpp @@ -4,7 +4,6 @@ #include // clamp #include // fmod -#include // pi_v #include @@ -12,18 +11,16 @@ #include "tactile/core/debug/assert.hpp" #include "tactile/core/meta/color.hpp" #include "tactile/core/ui/imgui_compat.hpp" +#include "tactile/core/ui/render/primitives.hpp" #include "tactile/core/ui/viewport.hpp" namespace tactile::ui { -inline namespace renderer { +namespace { using VisibleRegion = CanvasRenderer::VisibleRegion; using VisibleTileRegion = CanvasRenderer::VisibleTileRegion; using RenderBounds = CanvasRenderer::RenderBounds; -inline constexpr float kHalfPi = std::numbers::pi_v * 0.5f; -inline constexpr float kTau = std::numbers::pi_v * 2.0f; - [[nodiscard]] auto _get_visible_region(const Float2& viewport_pos, const Float2& window_size) -> VisibleRegion @@ -69,7 +66,7 @@ auto _get_render_bounds(const VisibleTileRegion& tiles, return bounds; } -} // namespace renderer +} // namespace CanvasRenderer::CanvasRenderer(const Float2& canvas_tl, const Float2& canvas_br, @@ -95,64 +92,6 @@ CanvasRenderer::~CanvasRenderer() noexcept draw_list.PopClipRect(); } -void CanvasRenderer::draw_rect(const Float2& screen_pos, - const Float2& size, - const UColor& color, - const float thickness) -{ - auto& draw_list = get_draw_list(); - draw_list.AddRect(to_imvec2(screen_pos), - to_imvec2(screen_pos + size), - to_uint32_abgr(color), - 0.0f, - ImDrawFlags_None, - thickness); -} - -void CanvasRenderer::fill_rect(const Float2& screen_pos, - const Float2& size, - const UColor& color) -{ - auto& draw_list = get_draw_list(); - draw_list.AddRectFilled(to_imvec2(screen_pos), - to_imvec2(screen_pos + size), - to_uint32_abgr(color)); -} - -void CanvasRenderer::draw_ngon(const Float2& screen_pos, - const float radius, - const uint32 color_mask, - const int segment_count, - const float thickness, - const float angle) -{ - if ((color_mask & IM_COL32_A_MASK) == 0 || segment_count <= 2) { - return; - } - - // We're drawing a closed shape, so we remove one of the segments/points. - const auto segment_max = - static_cast(segment_count - 1) / static_cast(segment_count); - const auto angle_max = kTau * segment_max; - - auto& draw_list = get_draw_list(); - - draw_list.PathArcTo(to_imvec2(screen_pos), - radius, - angle, - angle + angle_max, - segment_count - 1); - draw_list.PathStroke(color_mask, ImDrawFlags_Closed, thickness); -} - -void CanvasRenderer::draw_hexagon(const Float2& screen_pos, - const float radius, - const uint32 color_mask, - const float thickness) -{ - draw_ngon(screen_pos, radius, color_mask, 6, thickness, kHalfPi); -} - void CanvasRenderer::clear_canvas(const UColor& color) const { fill_rect(mWindowTL, mWindowBR, color);