From a3dfb0ff98f8ffcb3310c3a7ffd5d407e8d686c4 Mon Sep 17 00:00:00 2001 From: LingSamuel Date: Tue, 17 Dec 2024 01:08:21 +0800 Subject: [PATCH] feat: add outline for pie and ring --- src/D2DPainter.cpp | 39 ++++++++++++++++++++++++++++----------- src/D2DPainter.hpp | 11 ++++++----- src/DrawList.cpp | 33 +++++++++++++++++++++++++++++++-- src/DrawList.hpp | 29 ++++++++++++++++++++++++++--- src/Plugin.cpp | 33 +++++++++++++++++++++++++++++++-- 5 files changed, 122 insertions(+), 23 deletions(-) diff --git a/src/D2DPainter.cpp b/src/D2DPainter.cpp index d015117..fdad668 100644 --- a/src/D2DPainter.cpp +++ b/src/D2DPainter.cpp @@ -151,19 +151,20 @@ void D2DPainter::fill_circle(float centerX, float centerY, float radiusX, float m_context->FillEllipse(ellipse, m_brush.Get()); } -void D2DPainter::circle(float centerX, float centerY, float radius, int thickness, unsigned int color) { +void D2DPainter::circle(float centerX, float centerY, float radius, float thickness, unsigned int color) { set_color(color); D2D1_ELLIPSE ellipse = D2D1::Ellipse(D2D1::Point2F(centerX, centerY), radius, radius); m_context->DrawEllipse(ellipse, m_brush.Get(), thickness); } -void D2DPainter::circle(float centerX, float centerY, float radiusX, float radiusY, int thickness, unsigned int color) { +void D2DPainter::circle(float centerX, float centerY, float radiusX, float radiusY, float thickness, unsigned int color) { set_color(color); D2D1_ELLIPSE ellipse = D2D1::Ellipse(D2D1::Point2F(centerX, centerY), radiusX, radiusY); m_context->DrawEllipse(ellipse, m_brush.Get(), thickness); } -void D2DPainter::pie(float centerX, float centerY, float radius, float startAngle, float sweepAngle, unsigned int color, bool clockwise) { +void D2DPainter::pie(float centerX, float centerY, float radius, float startAngle, float sweepAngle, float thickness, + unsigned int color, bool clockwise) { if (startAngle < 0) { startAngle += 360.0f; } @@ -173,7 +174,11 @@ void D2DPainter::pie(float centerX, float centerY, float radius, float startAngl return; } if (sweepAngle == 360.0f) { - return this->fill_circle(centerX, centerY, radius, color); + if (thickness == 0) { + return this->fill_circle(centerX, centerY, radius, color); + } else { + return this->circle(centerX, centerY, radius, thickness, color); + } } auto direction = clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; @@ -207,10 +212,14 @@ void D2DPainter::pie(float centerX, float centerY, float radius, float startAngl geometrySink->Close(); set_color(color); - m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); + if (thickness == 0) { + m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); + } else { + m_context->DrawGeometry(pathGeometry.Get(), m_brush.Get(), thickness); + } } -void D2DPainter::ring(float centerX, float centerY, float outerRadius, float innerRadius, unsigned int color) { +void D2DPainter::ring(float centerX, float centerY, float outerRadius, float innerRadius, float thickness, unsigned int color) { ComPtr outerCircle; m_d2d1->CreateEllipseGeometry(D2D1::Ellipse(D2D1::Point2F(centerX, centerY), outerRadius, outerRadius), &outerCircle); ComPtr innerCircle; @@ -225,11 +234,15 @@ void D2DPainter::ring(float centerX, float centerY, float outerRadius, float inn sink->Close(); set_color(color); - m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); + if (thickness == 0) { + m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); + } else { + m_context->DrawGeometry(pathGeometry.Get(), m_brush.Get(), thickness); + } } -void D2DPainter::ring( - float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, bool clockwise) { +void D2DPainter::ring(float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, + float thickness, unsigned int color, bool clockwise) { if (startAngle < 0) { startAngle += 360.0f; } @@ -239,7 +252,7 @@ void D2DPainter::ring( return; } if (sweepAngle == 360.0f) { - return this->ring(centerX, centerY, outerRadius, innerRadius, color); + return this->ring(centerX, centerY, outerRadius, innerRadius, thickness, color); } auto direction = clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; auto counterDirection = !clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; @@ -282,5 +295,9 @@ void D2DPainter::ring( sink->Close(); set_color(color); - m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); + if (thickness == 0) { + m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); + } else { + m_context->DrawGeometry(pathGeometry.Get(), m_brush.Get(), thickness); + } } diff --git a/src/D2DPainter.hpp b/src/D2DPainter.hpp index f3f87bf..3b1a162 100644 --- a/src/D2DPainter.hpp +++ b/src/D2DPainter.hpp @@ -36,12 +36,13 @@ class D2DPainter { void image(std::shared_ptr& image, float x, float y, float w, float h); void fill_circle(float centerX, float centerY, float radius, unsigned int color); void fill_circle(float centerX, float centerY, float radiusX, float radiusY, unsigned int color); - void circle(float centerX, float centerY, float radius, int thickness, unsigned int color); - void circle(float centerX, float centerY, float radiusX, float radiusY, int thickness, unsigned int color); - void pie(float centerX, float centerY, float radius, float startAngle, float sweepAngle, unsigned int color, bool clockwise); - void ring(float centerX, float centerY, float outerRadius, float innerRadius, unsigned int color); - void ring(float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, + void circle(float centerX, float centerY, float radius, float thickness, unsigned int color); + void circle(float centerX, float centerY, float radiusX, float radiusY, float thickness, unsigned int color); + void pie(float centerX, float centerY, float radius, float startAngle, float sweepAngle, float thickness, unsigned int color, bool clockwise); + void ring(float centerX, float centerY, float outerRadius, float innerRadius, float thickness, unsigned int color); + void ring(float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, float thickness, + unsigned int color, bool clockwise); auto surface_size() const { return std::make_tuple(m_rt_desc.Width, m_rt_desc.Height); } diff --git a/src/DrawList.cpp b/src/DrawList.cpp index 2658c2f..547869e 100644 --- a/src/DrawList.cpp +++ b/src/DrawList.cpp @@ -153,8 +153,21 @@ void DrawList::CommandLock::pie(float x, float y, float r, float startAngle, flo commands.emplace_back(std::move(cmd)); } -void DrawList::CommandLock::ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, - bool clockwise) { +void DrawList::CommandLock::outline_pie(float x, float y, float r, float startAngle, float sweepAngle, float thickness, unsigned int color, bool clockwise) { + Command cmd{}; + cmd.type = CommandType::OUTLINE_PIE; + cmd.outline_pie.x = x; + cmd.outline_pie.y = y; + cmd.outline_pie.r = r; + cmd.outline_pie.startAngle = startAngle; + cmd.outline_pie.sweepAngle = sweepAngle; + cmd.outline_pie.thickness = thickness; + cmd.outline_pie.color = color; + cmd.outline_pie.clockwise = clockwise; + commands.emplace_back(std::move(cmd)); +} + +void DrawList::CommandLock::ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, bool clockwise) { Command cmd{}; cmd.type = CommandType::RING; cmd.ring.x = x; @@ -167,3 +180,19 @@ void DrawList::CommandLock::ring(float x, float y, float outerRadius, float inne cmd.ring.clockwise = clockwise; commands.emplace_back(std::move(cmd)); } + +void DrawList::CommandLock::outline_ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, + float thickness, unsigned int color, bool clockwise) { + Command cmd{}; + cmd.type = CommandType::OUTLINE_RING; + cmd.outline_ring.x = x; + cmd.outline_ring.y = y; + cmd.outline_ring.outerRadius = outerRadius; + cmd.outline_ring.innerRadius = innerRadius; + cmd.outline_ring.startAngle = startAngle; + cmd.outline_ring.sweepAngle = sweepAngle; + cmd.outline_ring.thickness = thickness; + cmd.outline_ring.color = color; + cmd.outline_ring.clockwise = clockwise; + commands.emplace_back(std::move(cmd)); +} diff --git a/src/DrawList.hpp b/src/DrawList.hpp index 0e1983d..61d12e9 100644 --- a/src/DrawList.hpp +++ b/src/DrawList.hpp @@ -10,7 +10,7 @@ class DrawList { public: - enum class CommandType { TEXT, FILL_RECT, OUTLINE_RECT, ROUNDED_RECT, FILL_ROUNDED_RECT, QUAD, FILL_QUAD, LINE, IMAGE, FILL_CIRCLE, CIRCLE, PIE, RING }; + enum class CommandType { TEXT, FILL_RECT, OUTLINE_RECT, ROUNDED_RECT, FILL_ROUNDED_RECT, QUAD, FILL_QUAD, LINE, IMAGE, FILL_CIRCLE, CIRCLE, PIE, OUTLINE_PIE, RING, OUTLINE_RING }; struct Command { CommandType type; @@ -115,6 +115,16 @@ class DrawList { unsigned int color{}; bool clockwise{}; } pie; + struct { + float x{}; + float y{}; + float r{}; + float startAngle{}; + float sweepAngle{}; + float thickness{}; + unsigned int color{}; + bool clockwise{}; + } outline_pie; struct { float x{}; float y{}; @@ -125,6 +135,17 @@ class DrawList { unsigned int color{}; bool clockwise{}; } ring; + struct { + float x{}; + float y{}; + float outerRadius{}; + float innerRadius{}; + float startAngle{}; + float sweepAngle{}; + float thickness{}; + unsigned int color{}; + bool clockwise{}; + } outline_ring; }; std::string str{}; std::shared_ptr font_resource{}; @@ -147,8 +168,10 @@ class DrawList { void fill_circle(float x, float y, float radiusX, float radiusY, unsigned int color); void circle(float x, float y, float radiusX, float radiusY, float thickness, unsigned int color); void pie(float x, float y, float r, float startAngle, float sweepAngle, unsigned int color, bool clockwise); - void ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, - bool clockwise); + void outline_pie(float x, float y, float r, float startAngle, float sweepAngle, float thickness, unsigned int color, bool clockwise); + void ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, bool clockwise); + void outline_ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, float thickness, + unsigned int color, bool clockwise); }; auto acquire() { return CommandLock{m_commands, std::scoped_lock{m_commands_mux}}; } diff --git a/src/Plugin.cpp b/src/Plugin.cpp index 9fd3461..5937963 100644 --- a/src/Plugin.cpp +++ b/src/Plugin.cpp @@ -176,6 +176,15 @@ void on_ref_lua_state_created(lua_State* l) try { } g_plugin->cmds->pie(x, y, r, startAngle, sweepAngle, color, clockwise); }; + d2d["outline_pie"] = [](float x, float y, float r, float startAngle, float sweepAngle, float thickness, unsigned int color, + sol::object clockwise_obj) { + auto clockwise = true; + + if (clockwise_obj.is()) { + clockwise = clockwise_obj.as(); + } + g_plugin->cmds->outline_pie(x, y, r, startAngle, sweepAngle, thickness, color, clockwise); + }; d2d["ring"] = [](float x, float y, float outerR, float innerR, float startAngle, float sweepAngle, unsigned int color, sol::object clockwise_obj) { auto clockwise = true; @@ -185,6 +194,16 @@ void on_ref_lua_state_created(lua_State* l) try { } g_plugin->cmds->ring(x, y, outerR, innerR, startAngle, sweepAngle, color, clockwise); }; + d2d["outline_ring"] = [](float x, float y, float outerR, float innerR, float startAngle, float sweepAngle, float thickness, + unsigned int color, + sol::object clockwise_obj) { + auto clockwise = true; + + if (clockwise_obj.is()) { + clockwise = clockwise_obj.as(); + } + g_plugin->cmds->outline_ring(x, y, outerR, innerR, startAngle, sweepAngle, thickness, color, clockwise); + }; d2d["surface_size"] = [](sol::this_state s) { auto [w, h] = g_plugin->d2d->surface_size(); sol::variadic_results results{}; @@ -294,12 +313,22 @@ void on_ref_frame() try { break; case DrawList::CommandType::PIE: - g_plugin->d2d->pie(cmd.pie.x, cmd.pie.y, cmd.pie.r, cmd.pie.startAngle, cmd.pie.sweepAngle, cmd.pie.color, cmd.pie.clockwise); + g_plugin->d2d->pie(cmd.pie.x, cmd.pie.y, cmd.pie.r, cmd.pie.startAngle, cmd.pie.sweepAngle, 0, cmd.pie.color, cmd.pie.clockwise); + break; + + case DrawList::CommandType::OUTLINE_PIE: + g_plugin->d2d->pie(cmd.outline_pie.x, cmd.outline_pie.y, cmd.outline_pie.r, cmd.outline_pie.startAngle, + cmd.outline_pie.sweepAngle, cmd.outline_pie.thickness, cmd.outline_pie.color, cmd.outline_pie.clockwise); break; case DrawList::CommandType::RING: g_plugin->d2d->ring(cmd.ring.x, cmd.ring.y, cmd.ring.outerRadius, cmd.ring.innerRadius, cmd.ring.startAngle, cmd.ring.sweepAngle, - cmd.ring.color, cmd.ring.clockwise); + 0, cmd.ring.color, cmd.ring.clockwise); + break; + + case DrawList::CommandType::OUTLINE_RING: + g_plugin->d2d->ring(cmd.outline_ring.x, cmd.outline_ring.y, cmd.outline_ring.outerRadius, cmd.outline_ring.innerRadius, + cmd.outline_ring.startAngle, cmd.outline_ring.sweepAngle, cmd.outline_ring.thickness, cmd.outline_ring.color, cmd.outline_ring.clockwise); break; } }