diff --git a/src/Mod/Part/Gui/BoxSelection.cpp b/src/Mod/Part/Gui/BoxSelection.cpp new file mode 100644 index 0000000000..ef3d136a81 --- /dev/null +++ b/src/Mod/Part/Gui/BoxSelection.cpp @@ -0,0 +1,194 @@ +/*************************************************************************** + * Copyright (c) 2018 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include "BoxSelection.h" +#include "ViewProviderExt.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +using namespace PartGui; + +class BoxSelection::FaceSelectionGate : public Gui::SelectionFilterGate +{ +public: + FaceSelectionGate() + : Gui::SelectionFilterGate() + { + } + ~FaceSelectionGate() + { + } + bool allow(App::Document*, App::DocumentObject*, const char*sSubName) + { + if (!sSubName || sSubName[0] == '\0') + return false; + std::string element(sSubName); + return element.substr(0,4) == "Face"; + } +}; + +BoxSelection::BoxSelection() +{ + +} + +BoxSelection::~BoxSelection() +{ + +} + +void BoxSelection::selectionCallback(void * ud, SoEventCallback * cb) +{ + Gui::View3DInventorViewer* view = reinterpret_cast(cb->getUserData()); + view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, ud); + SoNode* root = view->getSceneGraph(); + static_cast(root)->selectionRole.setValue(true); + + std::vector picked = view->getGLPolygon(); + SoCamera* cam = view->getSoRenderManager()->getCamera(); + SbViewVolume vv = cam->getViewVolume(); + Gui::ViewVolumeProjection proj(vv); + Base::Polygon2d polygon; + if (picked.size() == 2) { + SbVec2f pt1 = picked[0]; + SbVec2f pt2 = picked[1]; + polygon.Add(Base::Vector2d(pt1[0], pt1[1])); + polygon.Add(Base::Vector2d(pt1[0], pt2[1])); + polygon.Add(Base::Vector2d(pt2[0], pt2[1])); + polygon.Add(Base::Vector2d(pt2[0], pt1[1])); + } + else { + for (std::vector::const_iterator it = picked.begin(); it != picked.end(); ++it) + polygon.Add(Base::Vector2d((*it)[0],(*it)[1])); + } + + BoxSelection* self = static_cast(ud); + App::Document* doc = App::GetApplication().getActiveDocument(); + if (doc) { + cb->setHandled(); + + std::vector geom = doc->getObjectsOfType(); + for (auto it : geom) { + Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(it); + if (!vp->isVisible()) + continue; + const TopoDS_Shape& shape = it->Shape.getValue(); + self->addFacesToSelection(doc->getName(), it->getNameInDocument(), proj, polygon, shape); + } + view->redraw(); + } + + Gui::Selection().rmvSelectionGate(); + delete self; +} + +void BoxSelection::addFacesToSelection(const char* doc, const char* obj, + const Gui::ViewVolumeProjection& proj, + const Base::Polygon2d& polygon, + const TopoDS_Shape& shape) +{ + try { + TopTools_IndexedMapOfShape M; + + TopExp_Explorer xp_face(shape,TopAbs_FACE); + while (xp_face.More()) { + M.Add(xp_face.Current()); + xp_face.Next(); + } + + for (Standard_Integer k = 1; k <= M.Extent(); k++) { + const TopoDS_Shape& face = M(k); + + TopExp_Explorer xp_vertex(face,TopAbs_VERTEX); + while (xp_vertex.More()) { + gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(xp_vertex.Current())); + Base::Vector3d pt2d; + pt2d = proj(Base::Vector3d(p.X(), p.Y(), p.Z())); + if (polygon.Contains(Base::Vector2d(pt2d.x, pt2d.y))) { + std::stringstream str; + str << "Face" << k; + Gui::Selection().addSelection(doc, obj, str.str().c_str()); + break; + } + xp_vertex.Next(); + } + } + } + catch (...) { + } +} + +void BoxSelection::start() +{ + Gui::View3DInventor* view = qobject_cast(Gui::getMainWindow()->activeWindow()); + if (view) { + Gui::View3DInventorViewer* viewer = view->getViewer(); + if (!viewer->isSelecting()) { + viewer->startSelection(Gui::View3DInventorViewer::Rubberband); + viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), selectionCallback, this); + // avoid that the selection node handles the event otherwise the callback function won't be + // called immediately + SoNode* root = viewer->getSceneGraph(); + static_cast(root)->selectionRole.setValue(false); + + Gui::Selection().addSelectionGate(new FaceSelectionGate); + } + } +} diff --git a/src/Mod/Part/Gui/BoxSelection.h b/src/Mod/Part/Gui/BoxSelection.h new file mode 100644 index 0000000000..07d0d1b94f --- /dev/null +++ b/src/Mod/Part/Gui/BoxSelection.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (c) 2018 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PARTGUI_BOXSELECTION_H +#define PARTGUI_BOXSELECTION_H + +class SoEventCallback; +class TopoDS_Shape; + +namespace Base { +class Polygon2d; +} + +namespace Gui { +class View3DInventorViewer; +class ViewVolumeProjection; +} + +namespace PartGui { + +class BoxSelection +{ +public: + BoxSelection(); + ~BoxSelection(); + + void start(); + +private: + class FaceSelectionGate; + void addFacesToSelection(const char* doc, const char* obj, + const Gui::ViewVolumeProjection& proj, + const Base::Polygon2d& polygon, + const TopoDS_Shape& shape); + static void selectionCallback(void * ud, SoEventCallback * cb); +}; + +} //namespace PartGui + +#endif // PARTGUI_BOXSELECTION_H diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index a3dd00b30c..3bcc8c47ba 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -111,6 +111,8 @@ SET(PartGui_SRCS AppPartGui.cpp AttacherTexts.h AttacherTexts.cpp + BoxSelection.cpp + BoxSelection.h Command.cpp CommandSimple.cpp CommandParametric.cpp diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index c22d06599e..792e5115ba 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -72,6 +72,7 @@ #include "TaskSweep.h" #include "TaskDimension.h" #include "TaskCheckGeometry.h" +#include "BoxSelection.h" //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -2222,6 +2223,35 @@ bool CmdMeasureToggleDelta::isActive(void) return hasActiveDocument(); } +//=========================================================================== +// Part_BoxSelection +//=========================================================================== + +DEF_STD_CMD_A(CmdBoxSelection) + +CmdBoxSelection::CmdBoxSelection() + : Command("Part_BoxSelection") +{ + sAppModule = "Part"; + sGroup = QT_TR_NOOP("Part"); + sMenuText = QT_TR_NOOP("Box selection"); + sToolTipText = QT_TR_NOOP("Box selection"); + sWhatsThis = "Part_BoxSelection"; + sStatusTip = QT_TR_NOOP("Box selection"); +} + +void CmdBoxSelection::activated(int iMsg) +{ + Q_UNUSED(iMsg); + PartGui::BoxSelection* sel = new PartGui::BoxSelection(); + sel->start(); +} + +bool CmdBoxSelection::isActive(void) +{ + return hasActiveDocument(); +} + void CreatePartCommands(void) { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); @@ -2268,4 +2298,5 @@ void CreatePartCommands(void) rcCmdMgr.addCommand(new CmdMeasureToggleAll()); rcCmdMgr.addCommand(new CmdMeasureToggle3d()); rcCmdMgr.addCommand(new CmdMeasureToggleDelta()); -} + rcCmdMgr.addCommand(new CmdBoxSelection()); +} diff --git a/src/Mod/Part/Gui/Workbench.cpp b/src/Mod/Part/Gui/Workbench.cpp index fd94722087..06dd0b3239 100644 --- a/src/Mod/Part/Gui/Workbench.cpp +++ b/src/Mod/Part/Gui/Workbench.cpp @@ -95,6 +95,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const part->setCommand("&Part"); *part << "Part_Import" << "Part_Export" + << "Separator" + << "Part_BoxSelection" << "Separator"; *part << prim << "Part_Primitives"