Skip to content

Commit

Permalink
support negative startAngle and clockwise
Browse files Browse the repository at this point in the history
  • Loading branch information
lingsamuel committed Nov 26, 2024
1 parent f5a80c6 commit 135e665
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 19 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
```

Expand Down
26 changes: 19 additions & 7 deletions src/D2DPainter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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<ID2D1PathGeometry> pathGeometry;
m_d2d1->CreatePathGeometry(&pathGeometry);
Expand All @@ -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);

Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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);

Expand All @@ -204,15 +215,16 @@ 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));
sink->BeginFigure(outerStart, D2D1_FIGURE_BEGIN_FILLED);

// 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
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions src/D2DPainter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); }

Expand Down
7 changes: 5 additions & 2 deletions src/DrawList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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));
}
7 changes: 5 additions & 2 deletions src/DrawList.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class DrawList {
float startAngle{};
float sweepAngle{};
unsigned int color{};
bool clockwise{};
} pie;
struct {
float x{};
Expand All @@ -99,6 +100,7 @@ class DrawList {
float startAngle{};
float sweepAngle{};
unsigned int color{};
bool clockwise{};
} ring;
};
std::string str{};
Expand All @@ -119,8 +121,9 @@ class DrawList {
void image(std::shared_ptr<D2DImage>& 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}}; }
Expand Down
24 changes: 18 additions & 6 deletions src/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool>()) {
clockwise = clockwise_obj.as<bool>();
}
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<bool>()) {
clockwise = clockwise_obj.as<bool>();
}
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();
Expand Down Expand Up @@ -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;
}
}
Expand Down

0 comments on commit 135e665

Please sign in to comment.