diff --git a/src/CanvasComponents/EllipseCanvasComponent.cpp b/src/CanvasComponents/EllipseCanvasComponent.cpp index 1d3697e..c45d797 100644 --- a/src/CanvasComponents/EllipseCanvasComponent.cpp +++ b/src/CanvasComponents/EllipseCanvasComponent.cpp @@ -22,6 +22,7 @@ #include "Helpers/SCollision.hpp" #include #include "../DrawCollision.hpp" +#include #include CanvasComponentType EllipseCanvasComponent::get_type() const { @@ -77,6 +78,43 @@ void EllipseCanvasComponent::create_draw_data() { void EllipseCanvasComponent::initialize_draw_data(DrawingProgram& drawP) { create_draw_data(); + create_collider(); +} + +void EllipseCanvasComponent::create_collider() { + switch(d.fillStrokeMode) { + case 0: { + colliderPath = ellipsePath; + break; + } + case 1: { + float radiusX = d.p2.x() - d.p1.x(); + float radiusY = d.p2.y() - d.p1.y(); + if(radiusX < d.strokeWidth || radiusY < d.strokeWidth) { + SkRect largeRect = SkRect::MakeLTRB(d.p1.x() - d.strokeWidth * 0.5f, d.p1.y() - d.strokeWidth * 0.5f, d.p2.x() + d.strokeWidth * 0.5f, d.p2.y() + d.strokeWidth * 0.5f); + SkPathBuilder ellipsePathBuilder; + ellipsePathBuilder.addOval(largeRect); + colliderPath = ellipsePathBuilder.detach(); + } + else { + SkRect smallRect = SkRect::MakeLTRB(d.p1.x() + d.strokeWidth * 0.5f, d.p1.y() + d.strokeWidth * 0.5f, d.p2.x() - d.strokeWidth * 0.5f, d.p2.y() - d.strokeWidth * 0.5f); + SkRect largeRect = SkRect::MakeLTRB(d.p1.x() - d.strokeWidth * 0.5f, d.p1.y() - d.strokeWidth * 0.5f, d.p2.x() + d.strokeWidth * 0.5f, d.p2.y() + d.strokeWidth * 0.5f); + SkPathBuilder ellipsePathBuilder; + ellipsePathBuilder.addOval(largeRect); + ellipsePathBuilder.addOval(smallRect); + ellipsePathBuilder.setFillType(SkPathFillType::kEvenOdd); + colliderPath = ellipsePathBuilder.detach(); + } + break; + } + case 2: { + SkRect largeRect = SkRect::MakeLTRB(d.p1.x() - d.strokeWidth * 0.5f, d.p1.y() - d.strokeWidth * 0.5f, d.p2.x() + d.strokeWidth * 0.5f, d.p2.y() + d.strokeWidth * 0.5f); + SkPathBuilder ellipsePathBuilder; + ellipsePathBuilder.addOval(largeRect); + colliderPath = ellipsePathBuilder.detach(); + break; + } + } } std::unique_ptr EllipseCanvasComponent::get_data_copy() const { @@ -91,20 +129,20 @@ void EllipseCanvasComponent::set_data_from(const CanvasComponent& other) { } bool EllipseCanvasComponent::collides_within_coords_point(const Vector2f& checkAgainst) const { - bool intersectsAABB = ellipsePath.getBounds().contains(checkAgainst.x(), checkAgainst.y()); + bool intersectsAABB = colliderPath.getBounds().contains(checkAgainst.x(), checkAgainst.y()); if(!intersectsAABB) return false; - return ellipsePath.contains(checkAgainst.x(), checkAgainst.y()); + return colliderPath.contains(checkAgainst.x(), checkAgainst.y()); } bool EllipseCanvasComponent::collides_within_coords_skpath(const SkPath& checkAgainst) const { - bool intersectsAABB = ellipsePath.getBounds().intersects(checkAgainst.getBounds()); + bool intersectsAABB = colliderPath.getBounds().intersects(checkAgainst.getBounds()); if(!intersectsAABB) return false; - std::optional pathIntersectCheck = Op(checkAgainst, ellipsePath, SkPathOp::kIntersect_SkPathOp); + std::optional pathIntersectCheck = Op(checkAgainst, colliderPath, SkPathOp::kIntersect_SkPathOp); return pathIntersectCheck.has_value() && !pathIntersectCheck.value().isEmpty(); } SCollision::AABB EllipseCanvasComponent::get_obj_coord_bounds() const { - return ellipsePath.getBounds(); + return colliderPath.getBounds(); } diff --git a/src/CanvasComponents/EllipseCanvasComponent.hpp b/src/CanvasComponents/EllipseCanvasComponent.hpp index 2f35c0e..b15d093 100644 --- a/src/CanvasComponents/EllipseCanvasComponent.hpp +++ b/src/CanvasComponents/EllipseCanvasComponent.hpp @@ -51,6 +51,8 @@ class EllipseCanvasComponent : public CanvasComponent { virtual bool collides_within_coords_point(const Vector2f& checkAgainst) const override; virtual bool collides_within_coords_skpath(const SkPath& checkAgainst) const override; virtual SCollision::AABB get_obj_coord_bounds() const override; + void create_collider(); void create_triangles(const std::function& passTriangleFunc); + SkPath colliderPath; SkPath ellipsePath; }; diff --git a/src/CanvasComponents/RectangleCanvasComponent.cpp b/src/CanvasComponents/RectangleCanvasComponent.cpp index eda5cc3..8f94c85 100644 --- a/src/CanvasComponents/RectangleCanvasComponent.cpp +++ b/src/CanvasComponents/RectangleCanvasComponent.cpp @@ -85,6 +85,7 @@ void RectangleCanvasComponent::set_data_from(const CanvasComponent& other) { void RectangleCanvasComponent::initialize_draw_data(DrawingProgram& drawP) { create_draw_data(); + create_collider(); } void RectangleCanvasComponent::create_draw_data() { @@ -101,21 +102,57 @@ void RectangleCanvasComponent::create_draw_data() { } } +void RectangleCanvasComponent::create_collider() { + switch(d.fillStrokeMode) { + case 0: { + colliderPath = rectPath; + break; + } + case 1: { + float radiusX = d.p2.x() - d.p1.x(); + float radiusY = d.p2.y() - d.p1.y(); + if(radiusX < d.strokeWidth || radiusY < d.strokeWidth) { + SkRect largeRect = SkRect::MakeLTRB(d.p1.x() - d.strokeWidth * 0.5f, d.p1.y() - d.strokeWidth * 0.5f, d.p2.x() + d.strokeWidth * 0.5f, d.p2.y() + d.strokeWidth * 0.5f); + SkPathBuilder rectPathBuilder; + rectPathBuilder.addRect(largeRect); + colliderPath = rectPathBuilder.detach(); + } + else { + SkRect smallRect = SkRect::MakeLTRB(d.p1.x() + d.strokeWidth * 0.5f, d.p1.y() + d.strokeWidth * 0.5f, d.p2.x() - d.strokeWidth * 0.5f, d.p2.y() - d.strokeWidth * 0.5f); + SkRect largeRect = SkRect::MakeLTRB(d.p1.x() - d.strokeWidth * 0.5f, d.p1.y() - d.strokeWidth * 0.5f, d.p2.x() + d.strokeWidth * 0.5f, d.p2.y() + d.strokeWidth * 0.5f); + SkPathBuilder rectPathBuilder; + rectPathBuilder.addRect(largeRect); + rectPathBuilder.addRect(smallRect); + rectPathBuilder.setFillType(SkPathFillType::kEvenOdd); + colliderPath = rectPathBuilder.detach(); + } + break; + } + case 2: { + SkRect largeRect = SkRect::MakeLTRB(d.p1.x() - d.strokeWidth * 0.5f, d.p1.y() - d.strokeWidth * 0.5f, d.p2.x() + d.strokeWidth * 0.5f, d.p2.y() + d.strokeWidth * 0.5f); + SkPathBuilder rectPathBuilder; + rectPathBuilder.addRect(largeRect); + colliderPath = rectPathBuilder.detach(); + break; + } + } +} + bool RectangleCanvasComponent::collides_within_coords_point(const Vector2f& checkAgainst) const { - bool intersectsAABB = rectPath.getBounds().contains(checkAgainst.x(), checkAgainst.y()); + bool intersectsAABB = colliderPath.getBounds().contains(checkAgainst.x(), checkAgainst.y()); if(!intersectsAABB) return false; - return rectPath.contains(checkAgainst.x(), checkAgainst.y()); + return colliderPath.contains(checkAgainst.x(), checkAgainst.y()); } bool RectangleCanvasComponent::collides_within_coords_skpath(const SkPath& checkAgainst) const { - bool intersectsAABB = rectPath.getBounds().intersects(checkAgainst.getBounds()); + bool intersectsAABB = colliderPath.getBounds().intersects(checkAgainst.getBounds()); if(!intersectsAABB) return false; - std::optional pathIntersectCheck = Op(checkAgainst, rectPath, SkPathOp::kIntersect_SkPathOp); + std::optional pathIntersectCheck = Op(checkAgainst, colliderPath, SkPathOp::kIntersect_SkPathOp); return pathIntersectCheck.has_value() && !pathIntersectCheck.value().isEmpty(); } SCollision::AABB RectangleCanvasComponent::get_obj_coord_bounds() const { - return rectPath.getBounds(); + return colliderPath.getBounds(); } diff --git a/src/CanvasComponents/RectangleCanvasComponent.hpp b/src/CanvasComponents/RectangleCanvasComponent.hpp index 81d738b..3102994 100644 --- a/src/CanvasComponents/RectangleCanvasComponent.hpp +++ b/src/CanvasComponents/RectangleCanvasComponent.hpp @@ -52,8 +52,9 @@ class RectangleCanvasComponent : public CanvasComponent { virtual bool collides_within_coords_point(const Vector2f& checkAgainst) const override; virtual bool collides_within_coords_skpath(const SkPath& checkAgainst) const override; void create_draw_data(); + void create_collider(); virtual SCollision::AABB get_obj_coord_bounds() const override; - SkPath rectPath; + SkPath colliderPath; }; diff --git a/src/DrawingProgram/ToolConfiguration.hpp b/src/DrawingProgram/ToolConfiguration.hpp index 941e573..0443121 100644 --- a/src/DrawingProgram/ToolConfiguration.hpp +++ b/src/DrawingProgram/ToolConfiguration.hpp @@ -39,7 +39,7 @@ class ToolConfiguration { struct EllipseDrawToolConfig { float relativeWidth = 15.0f; - int fillStrokeMode = 1; + unsigned fillStrokeMode = 1; NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(EllipseDrawToolConfig, relativeWidth, fillStrokeMode) } ellipseDraw; diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index edeb1b6..1872ba4 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -255,7 +255,7 @@ bool EraserTool::prevent_undo_or_redo() { } void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) { - if(!drawP.world.main.input.isTouchDevice && !drawData.main->g.gui.cursor_obstructed() && !erasePath.isEmpty()) { + if(!drawP.world.main.input.isTouchDevice && (!drawData.main->g.gui.cursor_obstructed() || isErasing) && !erasePath.isEmpty()) { SkPaint linePaint; linePaint.setAntiAlias(drawData.skiaAA); linePaint.setColor4f({0.0f, 0.0f, 0.0f, 0.4f});