From 738a044f3ce86b675da2bb818cd8cb68b8094df9 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Mon, 6 Jan 2025 23:18:02 +0100 Subject: [PATCH] Gui: Add Show Plane utility to 2D Objects --- src/Mod/Part/Gui/ViewProvider2DObject.cpp | 118 +++++++++++++++++++- src/Mod/Part/Gui/ViewProvider2DObject.h | 15 +++ src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 7 +- 3 files changed, 135 insertions(+), 5 deletions(-) diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.cpp b/src/Mod/Part/Gui/ViewProvider2DObject.cpp index be4c10fc3c..e9b62513bf 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.cpp +++ b/src/Mod/Part/Gui/ViewProvider2DObject.cpp @@ -45,6 +45,10 @@ #include "ViewProvider2DObject.h" +#include +#include +#include + using namespace PartGui; using namespace std; @@ -317,10 +321,45 @@ void ViewProvider2DObjectGrid::updateGridExtent(float minx, float maxx, float mi PROPERTY_SOURCE(PartGui::ViewProvider2DObject, PartGui::ViewProviderPart) -ViewProvider2DObject::ViewProvider2DObject() = default; +ViewProvider2DObject::ViewProvider2DObject() + : plane(new SoSwitch) +{ + ADD_PROPERTY_TYPE(ShowPlane, + (false), + "Display Options", + (App::PropertyType)(App::Prop_None), + "If true, plane related with object is additionally rendered."); +} ViewProvider2DObject::~ViewProvider2DObject() = default; +void ViewProvider2DObject::attach(App::DocumentObject* documentObject) +{ + ViewProviderPart::attach(documentObject); + + getAnnotation()->addChild(plane); + + updatePlane(); +} + +void ViewProvider2DObject::updateData(const App::Property* property) +{ + ViewProviderPart::updateData(property); + + if (dynamic_cast(property)) { + updatePlane(); + } +} + +void ViewProvider2DObject::onChanged(const App::Property* property) +{ + ViewProviderPart::onChanged(property); + + if (property == &ShowPlane) { + plane->whichChild = ShowPlane.getValue() ? SO_SWITCH_ALL : SO_SWITCH_NONE; + } +} + std::vector ViewProvider2DObject::getDisplayModes() const { // get the modes of the father @@ -340,6 +379,83 @@ const char* ViewProvider2DObject::getDefaultDisplayMode() const return "Wireframe"; } +void ViewProvider2DObject::updatePlane() +{ + plane->whichChild = ShowPlane.getValue() ? SO_SWITCH_ALL : SO_SWITCH_NONE; + + Gui::coinRemoveAllChildren(plane); + + auto shapeProperty = getObject()->getPropertyByName("Shape"); + + if (!shapeProperty) { + return; + } + + auto bbox = shapeProperty->getBoundingBox(); + Base::Placement place = shapeProperty->getComplexData()->getPlacement(); + Base::ViewOrthoProjMatrix proj(place.inverse().toMatrix()); + Base::BoundBox2d bb = bbox.ProjectBox(&proj); + + SbVec3f verts[4] = { + SbVec3f(bb.MinX - horizontalPlanePadding, bb.MinY - verticalPlanePadding, 0), + SbVec3f(bb.MinX - horizontalPlanePadding, bb.MaxY + verticalPlanePadding, 0), + SbVec3f(bb.MaxX + horizontalPlanePadding, bb.MaxY + verticalPlanePadding, 0), + SbVec3f(bb.MaxX + horizontalPlanePadding, bb.MinY - verticalPlanePadding, 0), + }; + + static const int32_t lines[6] = { 0, 1, 2, 3, 0, -1 }; + + auto pCoords = new SoCoordinate3(); + pCoords->point.setNum(4); + pCoords->point.setValues(0, 4, verts); + plane->addChild(pCoords); + + auto pLines = new SoIndexedLineSet(); + pLines->coordIndex.setNum(6); + pLines->coordIndex.setValues(0, 6, lines); + plane->addChild(pLines); + + // add semi transparent face + auto faceSeparator = new SoSeparator(); + plane->addChild(faceSeparator); + + auto material = new SoMaterial(); + SbColor color(1.0f, 1.0f, 0.0f); + material->transparency.setValue(0.85f); + material->ambientColor.setValue(color); + material->diffuseColor.setValue(color); + faceSeparator->addChild(material); + + // disable backface culling and render with two-sided lighting + auto shapeHints = new SoShapeHints(); + shapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; + shapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; + faceSeparator->addChild(shapeHints); + + auto pickStyle = new SoPickStyle(); + pickStyle->style = SoPickStyle::UNPICKABLE; + faceSeparator->addChild(pickStyle); + + auto faceSet = new SoFaceSet(); + auto vertexProperty = new SoVertexProperty(); + vertexProperty->vertex.setValues(0, 4, verts); + faceSet->vertexProperty.setValue(vertexProperty); + faceSeparator->addChild(faceSet); + + auto ps = new SoPickStyle(); + ps->style.setValue(SoPickStyle::BOUNDING_BOX); + + auto dashed = new SoDrawStyle(); + dashed->linePattern = 0xF0F0; + + auto annotation = new SoAnnotation(); + annotation->addChild(dashed); + annotation->addChild(pLines); + + plane->addChild(annotation); + plane->addChild(ps); +} + namespace Gui { /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(PartGui::ViewProvider2DObjectPython, PartGui::ViewProvider2DObject) diff --git a/src/Mod/Part/Gui/ViewProvider2DObject.h b/src/Mod/Part/Gui/ViewProvider2DObject.h index 6438d0de6d..47280be184 100644 --- a/src/Mod/Part/Gui/ViewProvider2DObject.h +++ b/src/Mod/Part/Gui/ViewProvider2DObject.h @@ -41,13 +41,28 @@ class PartGuiExport ViewProvider2DObject : public PartGui::ViewProviderPart { PROPERTY_HEADER_WITH_OVERRIDE(PartGui::ViewProvider2DObject); + static constexpr float horizontalPlanePadding = 8; + static constexpr float verticalPlanePadding = 5; + public: /// constructor ViewProvider2DObject(); /// destructor ~ViewProvider2DObject() override; + + App::PropertyBool ShowPlane; + + void attach(App::DocumentObject*) override; + void updateData(const App::Property *) override; + void onChanged(const App::Property *) override; + std::vector getDisplayModes() const override; const char* getDefaultDisplayMode() const override; + +protected: + void updatePlane(); + + Gui::CoinPtr plane; }; class PartGuiExport ViewProvider2DObjectGrid : public ViewProvider2DObject diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 71d03efadc..2bb70154b2 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -2923,8 +2923,7 @@ void ViewProviderSketch::onChanged(const App::Property* prop) return; } - // call father - ViewProviderPart::onChanged(prop); + ViewProvider2DObject::onChanged(prop); } void SketcherGui::ViewProviderSketch::startRestoring() @@ -2960,14 +2959,14 @@ void SketcherGui::ViewProviderSketch::finishRestoring() void ViewProviderSketch::attach(App::DocumentObject* pcFeat) { - ViewProviderPart::attach(pcFeat); + ViewProvider2DObject::attach(pcFeat); } void ViewProviderSketch::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) { menu->addAction(tr("Edit sketch"), receiver, member); // Call the extensions - Gui::ViewProvider::setupContextMenu(menu, receiver, member); + ViewProvider::setupContextMenu(menu, receiver, member); } bool ViewProviderSketch::setEdit(int ModNum)