diff --git a/README.md b/README.md index a0b3b50..9e8b3df 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,20 @@ function() -- x, y, radius, start angle, sweep angle, color d2d.pie(1000, 500, 50, 0, 240, 0xFF00FFFF) d2d.pie(1100, 500, 50, 60, 240, 0xFF00FFFF) + -- negative start angle equals +360 degree + d2d.pie(1200, 100, 50, -90, 240, 0xFF00FFFF) + d2d.pie(1200, 200, 50, 270, 240, 0xFF00FFFF) + -- with clockwise=false + d2d.pie(1300, 100, 50, -90, 240, 0xFF00FFFF, false) -- x, y, outer radius, inner radius, start angle, sweep angle, color d2d.ring(1200, 500, 50, 30, 0, 240, 0xFF00FFFF) d2d.ring(1300, 500, 50, 30, 60, 240, 0xFF00FFFF) + -- negative start angle equals +360 degree + d2d.ring(1600, 100, 50, 30, -90, 240, 0xFF00FFFF) + d2d.ring(1600, 200, 50, 30, 270, 240, 0xFF00FFFF) + -- with clockwise=false + d2d.ring(1700, 100, 50, 30, -90, 240, 0xFF00FFFF, false) end) ``` diff --git a/src/D2DPainter.cpp b/src/D2DPainter.cpp index 246cafc..3716b54 100644 --- a/src/D2DPainter.cpp +++ b/src/D2DPainter.cpp @@ -125,7 +125,10 @@ void D2DPainter::circle(float centerX, float centerY, float radiusX, float radiu m_context->DrawEllipse(ellipse, m_brush.Get(), thickness); } -void D2DPainter::pie(float centerX, float centerY, float radius, float startAngle, float sweepAngle, unsigned int color) { +void D2DPainter::pie(float centerX, float centerY, float radius, float startAngle, float sweepAngle, unsigned int color, bool clockwise) { + if (startAngle < 0) { + startAngle += 360.0f; + } startAngle = std::clamp(startAngle, 0.0f, 360.0f); sweepAngle = std::clamp(sweepAngle, 0.0f, 360.0f); if (sweepAngle == 0.0f) { @@ -134,6 +137,7 @@ void D2DPainter::pie(float centerX, float centerY, float radius, float startAngl if (sweepAngle == 360.0f) { return this->fill_circle(centerX, centerY, radius, color); } + auto direction = clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; ComPtr pathGeometry; m_d2d1->CreatePathGeometry(&pathGeometry); @@ -142,7 +146,8 @@ void D2DPainter::pie(float centerX, float centerY, float radius, float startAngl pathGeometry->Open(&geometrySink); const float startRadians = startAngle * (3.14159265f / 180.0f); - const float endRadians = (startAngle + sweepAngle) * (3.14159265f / 180.0f); + const float sweepRadians = sweepAngle * (3.14159265f / 180.0f); + const float endRadians = clockwise ? (startRadians + sweepRadians) : (startRadians - sweepRadians); D2D1_POINT_2F circleCenter = D2D1::Point2F(centerX, centerY); @@ -153,7 +158,7 @@ void D2DPainter::pie(float centerX, float centerY, float radius, float startAngl // arc start -> arc end D2D1_POINT_2F arcEnd = D2D1::Point2F(centerX + radius * cosf(endRadians), centerY + radius * sinf(endRadians)); - geometrySink->AddArc(D2D1::ArcSegment(arcEnd, D2D1::SizeF(radius, radius), 0.0f, D2D1_SWEEP_DIRECTION_CLOCKWISE, + geometrySink->AddArc(D2D1::ArcSegment(arcEnd, D2D1::SizeF(radius, radius), 0.0f, direction, (sweepAngle > 180.0f) ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL)); // arc end -> circle center @@ -185,7 +190,11 @@ void D2DPainter::ring(float centerX, float centerY, float outerRadius, float inn m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); } -void D2DPainter::ring(float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color) { +void D2DPainter::ring( + float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, unsigned int color, bool clockwise) { + if (startAngle < 0) { + startAngle += 360.0f; + } startAngle = std::clamp(startAngle, 0.0f, 360.0f); sweepAngle = std::clamp(sweepAngle, 0.0f, 360.0f); if (sweepAngle == 0.0f) { @@ -194,6 +203,8 @@ void D2DPainter::ring(float centerX, float centerY, float outerRadius, float inn if (sweepAngle == 360.0f) { return this->ring(centerX, centerY, outerRadius, innerRadius, 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; set_color(color); @@ -204,7 +215,8 @@ void D2DPainter::ring(float centerX, float centerY, float outerRadius, float inn pathGeometry->Open(&sink); const float startRadians = startAngle * (3.14159265f / 180.0f); - const float endRadians = (startAngle + sweepAngle) * (3.14159265f / 180.0f); + const float sweepRadians = sweepAngle * (3.14159265f / 180.0f); + const float endRadians = clockwise ? (startRadians + sweepRadians) : (startRadians - sweepRadians); // outer arc start D2D1_POINT_2F outerStart = D2D1::Point2F(centerX + outerRadius * std::cos(startRadians), centerY + outerRadius * std::sin(startRadians)); @@ -212,7 +224,7 @@ void D2DPainter::ring(float centerX, float centerY, float outerRadius, float inn // outer arc start -> outer arc end D2D1_POINT_2F outerEnd = D2D1::Point2F(centerX + outerRadius * std::cos(endRadians), centerY + outerRadius * std::sin(endRadians)); - sink->AddArc(D2D1::ArcSegment(outerEnd, D2D1::SizeF(outerRadius, outerRadius), 0.0f, D2D1_SWEEP_DIRECTION_CLOCKWISE, + sink->AddArc(D2D1::ArcSegment(outerEnd, D2D1::SizeF(outerRadius, outerRadius), 0.0f, direction, (sweepAngle > 180.0f) ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL)); // outer arc end -> inner arc end @@ -221,7 +233,7 @@ void D2DPainter::ring(float centerX, float centerY, float outerRadius, float inn // inner arc end -> inner arc start D2D1_POINT_2F innerStart = D2D1::Point2F(centerX + innerRadius * std::cos(startRadians), centerY + innerRadius * std::sin(startRadians)); - sink->AddArc(D2D1::ArcSegment(innerStart, D2D1::SizeF(innerRadius, innerRadius), 0.0f, D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE, + sink->AddArc(D2D1::ArcSegment(innerStart, D2D1::SizeF(innerRadius, innerRadius), 0.0f, counterDirection, (sweepAngle > 180.0f) ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL)); // inner arc start -> outer arc start diff --git a/src/D2DPainter.hpp b/src/D2DPainter.hpp index 75b9973..8189152 100644 --- a/src/D2DPainter.hpp +++ b/src/D2DPainter.hpp @@ -36,9 +36,10 @@ class D2DPainter { 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); + 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 ring(float centerX, float centerY, float outerRadius, float innerRadius, float startAngle, float sweepAngle, 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 42319a2..0a756c3 100644 --- a/src/DrawList.cpp +++ b/src/DrawList.cpp @@ -107,7 +107,7 @@ void DrawList::CommandLock::circle(float x, float y, float radiusX, float radius commands.emplace_back(std::move(cmd)); } -void DrawList::CommandLock::pie(float x, float y, float r, float startAngle, float sweepAngle, unsigned int color) { +void DrawList::CommandLock::pie(float x, float y, float r, float startAngle, float sweepAngle, unsigned int color, bool clockwise) { Command cmd{}; cmd.type = CommandType::PIE; cmd.pie.x = x; @@ -116,10 +116,12 @@ void DrawList::CommandLock::pie(float x, float y, float r, float startAngle, flo cmd.pie.startAngle = startAngle; cmd.pie.sweepAngle = sweepAngle; cmd.pie.color = color; + cmd.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) { +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; @@ -129,5 +131,6 @@ void DrawList::CommandLock::ring(float x, float y, float outerRadius, float inne cmd.ring.startAngle = startAngle; cmd.ring.sweepAngle = sweepAngle; cmd.ring.color = color; + cmd.ring.clockwise = clockwise; commands.emplace_back(std::move(cmd)); } diff --git a/src/DrawList.hpp b/src/DrawList.hpp index 55fbf5a..29c96e9 100644 --- a/src/DrawList.hpp +++ b/src/DrawList.hpp @@ -90,6 +90,7 @@ class DrawList { float startAngle{}; float sweepAngle{}; unsigned int color{}; + bool clockwise{}; } pie; struct { float x{}; @@ -99,6 +100,7 @@ class DrawList { float startAngle{}; float sweepAngle{}; unsigned int color{}; + bool clockwise{}; } ring; }; std::string str{}; @@ -119,8 +121,9 @@ class DrawList { void image(std::shared_ptr& image, float x, float y, float w, float h); 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); - void ring(float x, float y, float outerRadius, float innerRadius, float startAngle, float sweepAngle, 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); }; auto acquire() { return CommandLock{m_commands, std::scoped_lock{m_commands_mux}}; } diff --git a/src/Plugin.cpp b/src/Plugin.cpp index c81a2f7..0aee523 100644 --- a/src/Plugin.cpp +++ b/src/Plugin.cpp @@ -162,11 +162,22 @@ void on_ref_lua_state_created(lua_State* l) try { d2d["oval"] = [](float x, float y, float rX, float rY, float thickness, unsigned int color) { g_plugin->cmds->circle(x, y, rX, rY, thickness, color); }; - d2d["pie"] = [](float x, float y, float r, float startAngle, float sweepAngle, unsigned int color) { - g_plugin->cmds->pie(x, y, r, startAngle, sweepAngle, color); + d2d["pie"] = [](float x, float y, float r, float startAngle, float sweepAngle, unsigned int color, sol::object clockwise_obj) { + auto clockwise = true; + + if (clockwise_obj.is()) { + clockwise = clockwise_obj.as(); + } + g_plugin->cmds->pie(x, y, r, startAngle, sweepAngle, color, clockwise); }; - d2d["ring"] = [](float x, float y, float outerR, float innerR, float startAngle, float sweepAngle, unsigned int color) { - g_plugin->cmds->ring(x, y, outerR, innerR, startAngle, sweepAngle, color); + d2d["ring"] = [](float x, float y, float outerR, float innerR, float startAngle, float sweepAngle, unsigned int color, + sol::object clockwise_obj) { + auto clockwise = true; + + if (clockwise_obj.is()) { + clockwise = clockwise_obj.as(); + } + g_plugin->cmds->ring(x, y, outerR, innerR, startAngle, sweepAngle, color, clockwise); }; d2d["surface_size"] = [](sol::this_state s) { auto [w, h] = g_plugin->d2d->surface_size(); @@ -267,11 +278,12 @@ 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); + 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); 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); + 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); break; } }