diff --git a/src/path/face.cpp b/src/path/face.cpp index e323fd9fe..b195278f4 100644 --- a/src/path/face.cpp +++ b/src/path/face.cpp @@ -211,6 +211,11 @@ bool Face::contains(const Face& other) const return p_this.contains(p_other); } +bool Face::contains(const Vec2f& pos) const +{ + return to_painter_path().contains(pos.to_pointf()); +} + bool Face::operator==(const Face& other) const { const auto points = path_points(); diff --git a/src/path/face.h b/src/path/face.h index d40bcdb11..2336f66eb 100644 --- a/src/path/face.h +++ b/src/path/face.h @@ -3,6 +3,7 @@ #include #include #include +#include "geometry/vec2.h" class QPainterPath; @@ -52,6 +53,7 @@ class Face [[nodiscard]] Face operator^(const Face& other) const; Face& operator^=(const Face& other); [[nodiscard]] bool contains(const Face& other) const; + [[nodiscard]] bool contains(const Vec2f& pos) const; [[nodiscard]] bool operator==(const Face& other) const; [[nodiscard]] bool operator!=(const Face& other) const; diff --git a/src/tools/handles/CMakeLists.txt b/src/tools/handles/CMakeLists.txt index dfc328346..a73b3a42c 100644 --- a/src/tools/handles/CMakeLists.txt +++ b/src/tools/handles/CMakeLists.txt @@ -2,6 +2,8 @@ target_sources(libommpfritt PRIVATE abstractselecthandle.cpp abstractselecthandle.h boundingboxhandle.h + facehandle.cpp + facehandle.h handle.cpp handle.h moveaxishandle.h diff --git a/src/tools/handles/facehandle.cpp b/src/tools/handles/facehandle.cpp new file mode 100644 index 000000000..0c8168f76 --- /dev/null +++ b/src/tools/handles/facehandle.cpp @@ -0,0 +1,45 @@ +#include "tools/handles/facehandle.h" +#include "path/edge.h" +#include +#include "objects/pathobject.h" +#include "scene/faceselection.h" +#include "scene/scene.h" + +namespace omm +{ + +FaceHandle::FaceHandle(Tool& tool, PathObject& path_object, const Face& face) + : Handle(tool) + , m_path_object(path_object) + , m_face(face) + , m_path(face.to_painter_path()) +{ +} + +bool FaceHandle::contains_global(const Vec2f& point) const +{ + const auto p = transformation().inverted().apply_to_position(point); + return m_face.contains(p); +} + +void FaceHandle::draw(QPainter& painter) const +{ + painter.save(); + painter.setTransform(transformation().to_qtransform()); + const auto status = is_selected() ? HandleStatus::Active : this->status(); + painter.setBrush(ui_color(status, "face")); + painter.drawPath(m_path); + painter.restore(); +} + +ObjectTransformation FaceHandle::transformation() const +{ + return m_path_object.global_transformation(Space::Viewport); +} + +bool FaceHandle::is_selected() const +{ + return tool.scene()->face_selection->faces().contains(m_face); +} + +} // namespace omm diff --git a/src/tools/handles/facehandle.h b/src/tools/handles/facehandle.h new file mode 100644 index 000000000..b3ef9b0bb --- /dev/null +++ b/src/tools/handles/facehandle.h @@ -0,0 +1,30 @@ +#pragma once + +#include "geometry/vec2.h" +#include "tools/handles/handle.h" +#include "tools/tool.h" +#include "path/face.h" +#include + +namespace omm +{ +class FaceHandle : public Handle +{ +public: + explicit FaceHandle(Tool& tool, PathObject& path_object, const Face& face); + [[nodiscard]] bool contains_global(const Vec2f& point) const override; + void draw(QPainter& painter) const override; + Vec2f position = Vec2f::o(); + ObjectTransformation transformation() const; + bool is_selected() const; + +protected: + bool transform_in_tool_space{}; + +private: + PathObject& m_path_object; + const Face m_face; + const QPainterPath m_path; +}; + +} // namespace omm diff --git a/src/tools/handles/pointselecthandle.cpp b/src/tools/handles/pointselecthandle.cpp index 2552d68ce..a6c7826ae 100644 --- a/src/tools/handles/pointselecthandle.cpp +++ b/src/tools/handles/pointselecthandle.cpp @@ -55,7 +55,7 @@ bool PointSelectHandle::mouse_press(const Vec2f& pos, const QMouseEvent& event) return false; } -bool PointSelectHandle ::mouse_move(const Vec2f& delta, const Vec2f& pos, const QMouseEvent& event) +bool PointSelectHandle::mouse_move(const Vec2f& delta, const Vec2f& pos, const QMouseEvent& event) { if (AbstractSelectHandle::mouse_move(delta, pos, event)) { return true; diff --git a/src/tools/handles/scalebandhandle.h b/src/tools/handles/scalebandhandle.h index 7118af0ad..7c5426943 100644 --- a/src/tools/handles/scalebandhandle.h +++ b/src/tools/handles/scalebandhandle.h @@ -3,6 +3,7 @@ #include "geometry/vec2.h" #include "tools/handles/handle.h" #include "tools/tool.h" +#include namespace omm { diff --git a/src/tools/selectfacestool.cpp b/src/tools/selectfacestool.cpp index 0b97b8f40..06d2399a9 100644 --- a/src/tools/selectfacestool.cpp +++ b/src/tools/selectfacestool.cpp @@ -1,7 +1,10 @@ #include "tools/selectfacestool.h" -#include "scene/scene.h" +#include "handles/facehandle.h" +#include "objects/pathobject.h" #include "path/face.h" +#include "path/pathvector.h" #include "scene/faceselection.h" +#include "scene/scene.h" namespace omm { @@ -27,4 +30,21 @@ void SelectFacesTool::transform_objects(ObjectTransformation transformation) // return scene()->face_selection->center(Space::Viewport); } +void SelectFacesTool::reset() +{ + clear(); + make_handles(); +} + +void SelectFacesTool::make_handles() +{ + for (auto* path_object : scene()->item_selection()) { + const auto faces = path_object->geometry().faces(); + for (const auto& face : faces) { + auto handle = std::make_unique(*this, *path_object, face); + push_handle(std::move(handle)); + } + } +} + } // namespace omm diff --git a/src/tools/selectfacestool.h b/src/tools/selectfacestool.h index 15f47862d..f42726ba6 100644 --- a/src/tools/selectfacestool.h +++ b/src/tools/selectfacestool.h @@ -15,6 +15,10 @@ class SelectFacesTool : public AbstractSelectTool static constexpr auto TYPE = QT_TRANSLATE_NOOP("any-context", "SelectFacesTool"); Vec2f selection_center() const override; void transform_objects(omm::ObjectTransformation transformation) override; + void reset() override; + +private: + void make_handles(); }; } // namespace diff --git a/uicolors/ui-colors-dark.cfg b/uicolors/ui-colors-dark.cfg index 67a7eaa5f..996265156 100644 --- a/uicolors/ui-colors-dark.cfg +++ b/uicolors/ui-colors-dark.cfg @@ -76,6 +76,7 @@ particle: #ffff80ff/#ffff00ff/#ffff00ff particle fill: #ffff80ff/#ffff00ff/#ffff00ff point: #000000ff/#000000ff/#000000ff point fill: #ffffffff/#ffff00ff/#ffffffff +face: #ffffff40/#ffff0020/#ffffff00 tangent: #000000ff/#000000ff/#000000ff tangent fill: #ffffffff/#ff0000ff/#0000ffff marker: #0000ffff/#0000ffff/#0000ffff diff --git a/uicolors/ui-colors-light.cfg b/uicolors/ui-colors-light.cfg index da3b02f43..313ba9a4f 100644 --- a/uicolors/ui-colors-light.cfg +++ b/uicolors/ui-colors-light.cfg @@ -67,8 +67,8 @@ y-axis-fill: #80ff80ff/#00ff00ff/#ffffffff y-axis-outline: #008000ff/#000000ff/#008000ff rotate-ring-fill: #8080ffff/#0000ffff/#ffffffff rotate-ring-outline: #000080ff/#000000ff/#000080ff -band: #000000ff/#000000ff/#00000000 band fill: #808080ff/#A0A0A0ff/#ffffffff +band: #000000ff/#000000ff/#00000000 bounding-box: #000000ff/#00000080/#ffffffff object: #ffff00ff/#A0A020ff/#ffffffff object fill: #ffff10ff/#B0B030ff/#ffffffff @@ -76,6 +76,7 @@ particle: #ffff80ff/#ffff00ff/#ffffffff particle fill: #ffff80ff/#ffff00ff/#ffffffff point: #000000ff/#000000ff/#000000ff point fill: #ffffffff/#ffff00ff/#ffff00ff +face: #ffffff40/#ffff0020/#ffff0000 tangent: #000000ff/#000000ff/#000000ff tangent fill: #ffffffff/#ff0000ff/#0000ffff marker: #0000ffff/#0000ffff/#0000ffff