Skip to content

Commit

Permalink
Move primitive rendering functions
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Aug 25, 2024
1 parent 27c523d commit b75cacf
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 121 deletions.
1 change: 1 addition & 0 deletions source/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
57 changes: 0 additions & 57 deletions source/core/inc/tactile/core/ui/canvas_renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
113 changes: 113 additions & 0 deletions source/core/inc/tactile/core/ui/render/primitives.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (C) 2024 Albin Johansson (GNU General Public License v3.0)

#pragma once

#include <numbers> // pi_v

#include <imgui.h>

#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<float>(segment_count - 1) / static_cast<float>(segment_count);
const auto angle_max = 2.0f * std::numbers::pi_v<float> * 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<float>;
draw_ngon(screen_pos, radius, color_mask, 6, thickness, half_pi);
}

} // namespace tactile::ui
67 changes: 3 additions & 64 deletions source/core/src/tactile/core/ui/canvas_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,23 @@

#include <algorithm> // clamp
#include <cmath> // fmod
#include <numbers> // pi_v

#include <imgui.h>

#include "tactile/base/numeric/vec_common.hpp"
#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<float> * 0.5f;
inline constexpr float kTau = std::numbers::pi_v<float> * 2.0f;

[[nodiscard]]
auto _get_visible_region(const Float2& viewport_pos,
const Float2& window_size) -> VisibleRegion
Expand Down Expand Up @@ -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,
Expand All @@ -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<float>(segment_count - 1) / static_cast<float>(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);
Expand Down

0 comments on commit b75cacf

Please sign in to comment.