diff --git a/README.md b/README.md index eab7373..1793c55 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ function() d2d.fill_rect(500, 100, w, h, 0xFFFFFFFF) d2d.text(font, str, 500, 100, 0xFF000000) d2d.outline_rect(500, 100, w, h, 5, 0xFF00FFFF) + d2d.quad(100, 100, 500, 100, 500, 500, 400, 500, 5, 0xFF00FFFF) + d2d.fill_quad(1100, 1100, 1500, 1100, 1500, 1500, 1400, 1500, 0xFF00FFFF) local screen_w, screen_h = d2d.surface_size() local img_w, img_h = image:size() @@ -42,6 +44,39 @@ function() -- Draw image at the bottom left corner of the screen but scaled to 50x50. d2d.image(image, 0, screen_h - 50, 50, 50) + + -- x, y, width, height, corner round x, corner round y, thickness, color + d2d.rounded_rect(400, 500, 80, 40, 5, 15, 5, 0xFF00FFFF) + -- x, y, width, height, corner round x, corner round y, color + d2d.fill_rounded_rect(400, 500, 80, 40, 5, 15, 0xFF00FFFF) + + -- x, y, radius, color + d2d.fill_circle(600, 500, 50, 0xFF00FFFF) + -- x, y, radius x, radius y, color + d2d.fill_oval(700, 500, 50, 80, 0xFF00FFFF) + + -- x, y, radius, thickness, color + d2d.circle(800, 500, 50, 5, 0xFF00FFFF) + -- x, y, radius x, radius y, thickness, color + d2d.oval(900, 500, 50, 80, 5, 0xFF00FFFF) + + -- 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) ``` @@ -121,6 +156,60 @@ Draws the outline of a rectangle --- +### `d2d.rounded_rect(x, y, w, h, rX, rY, thickness, color)` +Draws the outline of a rounded rectangle + +#### Params +* `x` the horizontal position on the screen +* `y` the vertical position on the screen +* `w` the width of the rectangle +* `h` the height of the rectangle +* `rX` the corner radius X +* `rY` the corner radius Y +* `thickness` the thickness of the outline +* `color` the ARGB color of the rectangle + +--- + +### `d2d.fill_rounded_rect(x, y, w, h, rX, rY, color)` +Draws a filled in a rounded rectangle + +#### Params +* `x` the horizontal position on the screen +* `y` the vertical position on the screen +* `w` the width of the rectangle +* `h` the height of the rectangle +* `rX` the corner radius X +* `rY` the corner radius Y +* `color` the ARGB color of the rectangle + +--- + +### `d2d.quad(x1, y1, x2, y2, x3, y3, x4, y4, thickness, color)` +Draws the outline of a quad + +#### Params +* `x1, y1` the first coordinate +* `x2, y2` the second coordinate +* `x3, y3` the third coordinate +* `x4, y4` the fourth coordinate +* `thickness` the thickness of the outline +* `color` the ARGB color of the quad + +--- + +### `d2d.fill_quad(x1, y1, x2, y2, x3, y3, x4, y4, color)` +Draws a filled in a quad + +#### Params +* `x1, y1` the first coordinate +* `x2, y2` the second coordinate +* `x3, y3` the third coordinate +* `x4, y4` the fourth coordinate +* `color` the ARGB color of the quad + +--- + ### `d2d.line(x1, y1, x2, y2, thickness, color)` Draws a line between two points @@ -134,6 +223,82 @@ Draws a line between two points --- +### `d2d.circle(x, y, r, thickness, color)` +Draws the outline of a circle + +#### Params +* `x` the horizontal center on the screen +* `y` the vertical center on the screen +* `r` the radius of the circle +* `thickness` the thickness of the outline +* `color` the ARGB color of the circle + +--- + +### `d2d.fill_circle(x, y, r, color)` +Draws a filled in a circle + +#### Params +* `x` the horizontal center on the screen +* `y` the vertical center on the screen +* `r` the radius of the circle +* `color` the ARGB color of the circle + +--- + +### `d2d.oval(x, y, rX, rY, thickness, color)` +Draws the outline of a oval + +#### Params +* `x` the horizontal center on the screen +* `y` the vertical center on the screen +* `rX` the horizontal radius of the oval +* `rY` the vertical radius of the oval +* `thickness` the thickness of the outline +* `color` the ARGB color of the oval + +--- + +### `d2d.fill_oval(x, y, rX, rY, color)` +Draws a filled in a oval + +#### Params +* `x` the horizontal center on the screen +* `y` the vertical center on the screen +* `rX` the horizontal radius of the oval +* `rY` the vertical radius of the oval +* `color` the ARGB color of the oval + +--- + +### `d2d.pie(x, y, r, startAngle, sweepAngle, color, clockwise)` +Draws a filled pie + +#### Params +* `x` the horizontal center on the screen +* `y` the vertical center on the screen +* `startAngle` the pie start angle, range from -360 to 360. +* `sweepAngle` the pie sweep angle, range from 0 to 360. +* `color` the ARGB color of the pie +* `clockwise` by default is true, clockwise. Set false to counter clockwise. + +--- + +### `d2d.ring(x, y, outerRadius, innerRadius, startAngle, sweepAngle, color, clockwise)` +Draws a filled ring + +#### Params +* `x` the horizontal center on the screen +* `y` the vertical center on the screen +* `outerRadius` the ring outer radius +* `innerRadius` the ring inner radius +* `startAngle` the pie start angle, range from -360 to 360. +* `sweepAngle` the pie sweep angle, range from 0 to 360. +* `color` the ARGB color of the pie +* `clockwise` by default is true, clockwise. Set false to counter clockwise. + +--- + ### `d2d.image(image, x, y, [w], [h])` Draws an image at the specified position, optionally scaled. diff --git a/src/D2DPainter.cpp b/src/D2DPainter.cpp index 18dce8a..d015117 100644 --- a/src/D2DPainter.cpp +++ b/src/D2DPainter.cpp @@ -77,6 +77,54 @@ void D2DPainter::outline_rect(float x, float y, float w, float h, float thicknes m_context->DrawRectangle({x, y, x + w, y + h}, m_brush.Get(), thickness); } +void D2DPainter::rounded_rect(float x, float y, float w, float h, float radiusX, float radiusY, float thickness, unsigned int color) { + set_color(color); + m_context->DrawRoundedRectangle({x, y, x + w, y + h, radiusX, radiusY}, m_brush.Get(), thickness); +} + +void D2DPainter::fill_rounded_rect(float x, float y, float w, float h, float radiusX, float radiusY, unsigned int color) { + set_color(color); + m_context->FillRoundedRectangle({x, y, x + w, y + h, radiusX, radiusY}, m_brush.Get()); +} + +void D2DPainter::quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float thickness, unsigned int color) { + ComPtr pathGeometry; + m_d2d1->CreatePathGeometry(&pathGeometry); + + ComPtr sink; + pathGeometry->Open(&sink); + + sink->BeginFigure(D2D1::Point2F(x1, y1), D2D1_FIGURE_BEGIN_FILLED); + sink->AddLine(D2D1::Point2F(x2, y2)); + sink->AddLine(D2D1::Point2F(x3, y3)); + sink->AddLine(D2D1::Point2F(x4, y4)); + + sink->EndFigure(D2D1_FIGURE_END_CLOSED); + sink->Close(); + + set_color(color); + m_context->DrawGeometry(pathGeometry.Get(), m_brush.Get(), thickness); +} + +void D2DPainter::fill_quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, unsigned int color) { + ComPtr pathGeometry; + m_d2d1->CreatePathGeometry(&pathGeometry); + + ComPtr sink; + pathGeometry->Open(&sink); + + sink->BeginFigure(D2D1::Point2F(x1, y1), D2D1_FIGURE_BEGIN_FILLED); + sink->AddLine(D2D1::Point2F(x2, y2)); + sink->AddLine(D2D1::Point2F(x3, y3)); + sink->AddLine(D2D1::Point2F(x4, y4)); + + sink->EndFigure(D2D1_FIGURE_END_CLOSED); + sink->Close(); + + set_color(color); + m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); +} + void D2DPainter::line(float x1, float y1, float x2, float y2, float thickness, unsigned int color) { set_color(color); m_context->DrawLine({x1, y1}, {x2, y2}, m_brush.Get(), thickness); @@ -90,3 +138,149 @@ void D2DPainter::image(std::shared_ptr& image, float x, float y) { void D2DPainter::image(std::shared_ptr& image, float x, float y, float w, float h) { m_context->DrawBitmap(image->bitmap().Get(), {x, y, x + w, y + h}); } + +void D2DPainter::fill_circle(float centerX, float centerY, float radius, unsigned int color) { + set_color(color); + D2D1_ELLIPSE ellipse = D2D1::Ellipse(D2D1::Point2F(centerX, centerY), radius, radius); + m_context->FillEllipse(ellipse, m_brush.Get()); +} + +void D2DPainter::fill_circle(float centerX, float centerY, float radiusX, float radiusY, unsigned int color) { + set_color(color); + D2D1_ELLIPSE ellipse = D2D1::Ellipse(D2D1::Point2F(centerX, centerY), radiusX, radiusY); + m_context->FillEllipse(ellipse, m_brush.Get()); +} + +void D2DPainter::circle(float centerX, float centerY, float radius, int 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) { + 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) { + 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) { + return; + } + 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); + + ComPtr geometrySink; + pathGeometry->Open(&geometrySink); + + const float startRadians = startAngle * (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); + + // circle center -> arc start + D2D1_POINT_2F arcStart = D2D1::Point2F(centerX + radius * cosf(startRadians), centerY + radius * sinf(startRadians)); + geometrySink->BeginFigure(circleCenter, D2D1_FIGURE_BEGIN_FILLED); + geometrySink->AddLine(arcStart); + + // 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, direction, + (sweepAngle > 180.0f) ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL)); + + // arc end -> circle center + geometrySink->AddLine(circleCenter); + + // end + geometrySink->EndFigure(D2D1_FIGURE_END_CLOSED); + geometrySink->Close(); + + set_color(color); + m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); +} + +void D2DPainter::ring(float centerX, float centerY, float outerRadius, float innerRadius, unsigned int color) { + ComPtr outerCircle; + m_d2d1->CreateEllipseGeometry(D2D1::Ellipse(D2D1::Point2F(centerX, centerY), outerRadius, outerRadius), &outerCircle); + ComPtr innerCircle; + m_d2d1->CreateEllipseGeometry(D2D1::Ellipse(D2D1::Point2F(centerX, centerY), innerRadius, innerRadius), &innerCircle); + + ComPtr pathGeometry; + m_d2d1->CreatePathGeometry(&pathGeometry); + ComPtr sink; + pathGeometry->Open(&sink); + + outerCircle->CombineWithGeometry(innerCircle.Get(), D2D1_COMBINE_MODE_EXCLUDE, NULL, sink.Get()); + sink->Close(); + + set_color(color); + 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, 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) { + return; + } + 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); + + ComPtr pathGeometry; + m_d2d1->CreatePathGeometry(&pathGeometry); + + ComPtr sink; + pathGeometry->Open(&sink); + + const float startRadians = startAngle * (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, direction, + (sweepAngle > 180.0f) ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL)); + + // outer arc end -> inner arc end + D2D1_POINT_2F innerEnd = D2D1::Point2F(centerX + innerRadius * std::cos(endRadians), centerY + innerRadius * std::sin(endRadians)); + sink->AddLine(innerEnd); + + // 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, counterDirection, + (sweepAngle > 180.0f) ? D2D1_ARC_SIZE_LARGE : D2D1_ARC_SIZE_SMALL)); + + // inner arc start -> outer arc start + sink->AddLine(outerStart); + + // end + sink->EndFigure(D2D1_FIGURE_END_CLOSED); + sink->Close(); + + set_color(color); + m_context->FillGeometry(pathGeometry.Get(), m_brush.Get()); +} diff --git a/src/D2DPainter.hpp b/src/D2DPainter.hpp index eff4da4..f3f87bf 100644 --- a/src/D2DPainter.hpp +++ b/src/D2DPainter.hpp @@ -27,9 +27,21 @@ class D2DPainter { void text(std::shared_ptr& font, const std::string& text, float x, float y, unsigned int color); void fill_rect(float x, float y, float w, float h, unsigned int color); void outline_rect(float x, float y, float w, float h, float thickness, unsigned int color); + void rounded_rect(float x, float y, float w, float h, float radiusX, float radiusY, float thickness, unsigned int color); + void fill_rounded_rect(float x, float y, float w, float h, float radiusX, float radiusY, unsigned int color); + void quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float thickness, unsigned int color); + void fill_quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, unsigned int color); void line(float x1, float y1, float x2, float y2, float thickness, unsigned int color); void image(std::shared_ptr& image, float x, float y); 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, + 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 585070a..2658c2f 100644 --- a/src/DrawList.cpp +++ b/src/DrawList.cpp @@ -34,6 +34,66 @@ void DrawList::CommandLock::outline_rect(float x, float y, float w, float h, flo commands.emplace_back(std::move(cmd)); } +void DrawList::CommandLock::rounded_rect(float x, float y, float w, float h, float rX, float rY, float thickness, unsigned int color) { + Command cmd{}; + cmd.type = CommandType::ROUNDED_RECT; + cmd.rounded_rect.x = x; + cmd.rounded_rect.y = y; + cmd.rounded_rect.w = w; + cmd.rounded_rect.h = h; + cmd.rounded_rect.rX = rX; + cmd.rounded_rect.rY = rY; + cmd.rounded_rect.thickness = thickness; + cmd.rounded_rect.color = color; + commands.emplace_back(std::move(cmd)); +} + +void DrawList::CommandLock::fill_rounded_rect(float x, float y, float w, float h, float rX, float rY, unsigned int color) { + Command cmd{}; + cmd.type = CommandType::FILL_ROUNDED_RECT; + cmd.rounded_rect.x = x; + cmd.rounded_rect.y = y; + cmd.rounded_rect.w = w; + cmd.rounded_rect.h = h; + cmd.rounded_rect.rX = rX; + cmd.rounded_rect.rY = rY; + cmd.rounded_rect.color = color; + commands.emplace_back(std::move(cmd)); +} + +void DrawList::CommandLock::quad( + float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float thickness, unsigned int color) { + Command cmd{}; + cmd.type = CommandType::QUAD; + cmd.quad.x1 = x1; + cmd.quad.y1 = y1; + cmd.quad.x2 = x2; + cmd.quad.y2 = y2; + cmd.quad.x3 = x3; + cmd.quad.y3 = y3; + cmd.quad.x4 = x4; + cmd.quad.y4 = y4; + cmd.quad.thickness = thickness; + cmd.quad.color = color; + commands.emplace_back(std::move(cmd)); +} + +void DrawList::CommandLock::fill_quad( + float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, unsigned int color) { + Command cmd{}; + cmd.type = CommandType::FILL_QUAD; + cmd.fill_quad.x1 = x1; + cmd.fill_quad.y1 = y1; + cmd.fill_quad.x2 = x2; + cmd.fill_quad.y2 = y2; + cmd.fill_quad.x3 = x3; + cmd.fill_quad.y3 = y3; + cmd.fill_quad.x4 = x4; + cmd.fill_quad.y4 = y4; + cmd.fill_quad.color = color; + commands.emplace_back(std::move(cmd)); +} + void DrawList::CommandLock::line(float x1, float y1, float x2, float y2, float thickness, unsigned int color) { Command cmd{}; cmd.type = CommandType::LINE; @@ -56,3 +116,54 @@ void DrawList::CommandLock::image(std::shared_ptr& image, float x, flo cmd.image_resource = image; commands.emplace_back(std::move(cmd)); } + +void DrawList::CommandLock::fill_circle(float x, float y, float radiusX, float radiusY, unsigned int color) { + Command cmd{}; + cmd.type = CommandType::FILL_CIRCLE; + cmd.fill_circle.x = x; + cmd.fill_circle.y = y; + cmd.fill_circle.radiusX = radiusX; + cmd.fill_circle.radiusY = radiusY; + cmd.fill_circle.color = color; + commands.emplace_back(std::move(cmd)); +} + +void DrawList::CommandLock::circle(float x, float y, float radiusX, float radiusY, float thickness, unsigned int color) { + Command cmd{}; + cmd.type = CommandType::CIRCLE; + cmd.circle.x = x; + cmd.circle.y = y; + cmd.circle.radiusX = radiusX; + cmd.circle.radiusY = radiusY; + cmd.circle.thickness = thickness; + cmd.circle.color = color; + commands.emplace_back(std::move(cmd)); +} + +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; + cmd.pie.y = y; + cmd.pie.r = r; + 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, + bool clockwise) { + Command cmd{}; + cmd.type = CommandType::RING; + cmd.ring.x = x; + cmd.ring.y = y; + cmd.ring.outerRadius = outerRadius; + cmd.ring.innerRadius = innerRadius; + 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 1c8a626..0e1983d 100644 --- a/src/DrawList.hpp +++ b/src/DrawList.hpp @@ -10,7 +10,7 @@ class DrawList { public: - enum class CommandType { TEXT, FILL_RECT, OUTLINE_RECT, LINE, IMAGE }; + enum class CommandType { TEXT, FILL_RECT, OUTLINE_RECT, ROUNDED_RECT, FILL_ROUNDED_RECT, QUAD, FILL_QUAD, LINE, IMAGE, FILL_CIRCLE, CIRCLE, PIE, RING }; struct Command { CommandType type; @@ -35,6 +35,48 @@ class DrawList { float thickness{}; unsigned int color{}; } outline_rect; + struct { + float x{}; + float y{}; + float w{}; + float h{}; + float rX{}; + float rY{}; + float thickness{}; + unsigned int color{}; + } rounded_rect; + struct { + float x{}; + float y{}; + float w{}; + float h{}; + float rX{}; + float rY{}; + unsigned int color{}; + } fill_rounded_rect; + struct { + float x1{}; + float y1{}; + float x2{}; + float y2{}; + float x3{}; + float y3{}; + float x4{}; + float y4{}; + float thickness{}; + unsigned int color{}; + } quad; + struct { + float x1{}; + float y1{}; + float x2{}; + float y2{}; + float x3{}; + float y3{}; + float x4{}; + float y4{}; + unsigned int color{}; + } fill_quad; struct { float x1{}; float y1{}; @@ -49,6 +91,40 @@ class DrawList { float w{}; float h{}; } image; + struct { + float x{}; + float y{}; + float radiusX{}; + float radiusY{}; + unsigned int color{}; + } fill_circle; + struct { + float x{}; + float y{}; + float radiusX{}; + float radiusY{}; + float thickness{}; + unsigned int color{}; + } circle; + struct { + float x{}; + float y{}; + float r{}; + float startAngle{}; + float sweepAngle{}; + unsigned int color{}; + bool clockwise{}; + } pie; + struct { + float x{}; + float y{}; + float outerRadius{}; + float innerRadius{}; + float startAngle{}; + float sweepAngle{}; + unsigned int color{}; + bool clockwise{}; + } ring; }; std::string str{}; std::shared_ptr font_resource{}; @@ -62,8 +138,17 @@ class DrawList { void text(std::shared_ptr& font, std::string text, float x, float y, unsigned int color); void fill_rect(float x, float y, float w, float h, unsigned int color); void outline_rect(float x, float y, float w, float h, float thickness, unsigned int color); + void rounded_rect(float x, float y, float w, float h, float rX, float rY, float thickness, unsigned int color); + void fill_rounded_rect(float x, float y, float w, float h, float rX, float rY, unsigned int color); + void quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float thickness, unsigned int color); + void fill_quad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, unsigned int color); void line(float x1, float y1, float x2, float y2, float thickness, unsigned int color); 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, 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 846cbf0..9fd3461 100644 --- a/src/Plugin.cpp +++ b/src/Plugin.cpp @@ -132,6 +132,18 @@ void on_ref_lua_state_created(lua_State* l) try { d2d["outline_rect"] = [](float x, float y, float w, float h, float thickness, unsigned int color) { g_plugin->cmds->outline_rect(x, y, w, h, thickness, color); }; + d2d["rounded_rect"] = [](float x, float y, float w, float h, float rX, float rY, float thickness, unsigned int color) { + g_plugin->cmds->rounded_rect(x, y, w, h, rX, rY, thickness, color); + }; + d2d["fill_rounded_rect"] = [](float x, float y, float w, float h, float rX, float rY, unsigned int color) { + g_plugin->cmds->fill_rounded_rect(x, y, w, h, rX, rY, color); + }; + d2d["quad"] = [](float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float thickness, unsigned int color) { + g_plugin->cmds->quad(x1, y1, x2, y2, x3, y3, x4, y4, thickness, color); + }; + d2d["fill_quad"] = [](float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, unsigned int color) { + g_plugin->cmds->fill_quad(x1, y1, x2, y2, x3, y3, x4, y4, color); + }; d2d["line"] = [](float x1, float y1, float x2, float y2, float thickness, unsigned int color) { g_plugin->cmds->line(x1, y1, x2, y2, thickness, color); }; @@ -148,6 +160,31 @@ void on_ref_lua_state_created(lua_State* l) try { g_plugin->cmds->image(image, x, y, w, h); }; + d2d["fill_circle"] = [](float x, float y, float r, unsigned int color) { g_plugin->cmds->fill_circle(x, y, r, r, color); }; + d2d["circle"] = [](float x, float y, float r, float thickness, unsigned int color) { + g_plugin->cmds->circle(x, y, r, r, thickness, color); + }; + d2d["fill_oval"] = [](float x, float y, float rX, float rY, unsigned int color) { g_plugin->cmds->fill_circle(x, y, rX, rY, color); }; + 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, 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, + 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(); sol::variadic_results results{}; @@ -219,6 +256,26 @@ void on_ref_frame() try { cmd.outline_rect.thickness, cmd.outline_rect.color); break; + case DrawList::CommandType::ROUNDED_RECT: + g_plugin->d2d->rounded_rect(cmd.rounded_rect.x, cmd.rounded_rect.y, cmd.rounded_rect.w, cmd.rounded_rect.h, + cmd.rounded_rect.rX, cmd.rounded_rect.rY, cmd.rounded_rect.thickness, cmd.rounded_rect.color); + break; + + case DrawList::CommandType::FILL_ROUNDED_RECT: + g_plugin->d2d->fill_rounded_rect(cmd.rounded_rect.x, cmd.rounded_rect.y, cmd.rounded_rect.w, cmd.rounded_rect.h, + cmd.rounded_rect.rX, cmd.rounded_rect.rY, cmd.rounded_rect.color); + break; + + case DrawList::CommandType::QUAD: + g_plugin->d2d->quad(cmd.quad.x1, cmd.quad.y1, cmd.quad.x2, cmd.quad.y2, cmd.quad.x3, cmd.quad.y3, + cmd.quad.x4, cmd.quad.y4, cmd.quad.thickness, cmd.quad.color); + break; + + case DrawList::CommandType::FILL_QUAD: + g_plugin->d2d->fill_quad(cmd.fill_quad.x1, cmd.fill_quad.y1, cmd.fill_quad.x2, cmd.fill_quad.y2, + cmd.fill_quad.x3, cmd.fill_quad.y3, cmd.fill_quad.x4, cmd.fill_quad.y4, cmd.fill_quad.color); + break; + case DrawList::CommandType::LINE: g_plugin->d2d->line(cmd.line.x1, cmd.line.y1, cmd.line.x2, cmd.line.y2, cmd.line.thickness, cmd.line.color); break; @@ -226,6 +283,24 @@ void on_ref_frame() try { case DrawList::CommandType::IMAGE: g_plugin->d2d->image(cmd.image_resource, cmd.image.x, cmd.image.y, cmd.image.w, cmd.image.h); break; + + case DrawList::CommandType::FILL_CIRCLE: + g_plugin->d2d->fill_circle( + cmd.fill_circle.x, cmd.fill_circle.y, cmd.fill_circle.radiusX, cmd.fill_circle.radiusY, cmd.fill_circle.color); + break; + + case DrawList::CommandType::CIRCLE: + g_plugin->d2d->circle(cmd.circle.x, cmd.circle.y, cmd.circle.radiusX, cmd.circle.radiusY, cmd.circle.thickness, cmd.circle.color); + 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); + 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); + break; } } },