From e6ea67bc1e282f9a5e935e9895674eb408a84643 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 13 Dec 2021 15:01:08 +0100 Subject: [PATCH] PD: highlight current profile and sections of a loft when selecting a new profile/section --- src/Mod/PartDesign/Gui/CMakeLists.txt | 2 + .../PartDesign/Gui/ReferenceHighlighter.cpp | 91 +++++++++++++++++++ src/Mod/PartDesign/Gui/ReferenceHighlighter.h | 71 +++++++++++++++ src/Mod/PartDesign/Gui/TaskLoftParameters.cpp | 25 ++++- src/Mod/PartDesign/Gui/ViewProviderLoft.cpp | 86 ++++++++++-------- src/Mod/PartDesign/Gui/ViewProviderLoft.h | 20 +++- 6 files changed, 249 insertions(+), 46 deletions(-) create mode 100644 src/Mod/PartDesign/Gui/ReferenceHighlighter.cpp create mode 100644 src/Mod/PartDesign/Gui/ReferenceHighlighter.h diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index e3964bcaf2..e8b49fa76d 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -228,6 +228,8 @@ SET(PartDesignGuiModule_SRCS CommandBody.cpp EnumFlags.h Resources/PartDesign.qrc + ReferenceHighlighter.cpp + ReferenceHighlighter.h PreCompiled.cpp PreCompiled.h Utils.cpp diff --git a/src/Mod/PartDesign/Gui/ReferenceHighlighter.cpp b/src/Mod/PartDesign/Gui/ReferenceHighlighter.cpp new file mode 100644 index 0000000000..6e98051c58 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ReferenceHighlighter.cpp @@ -0,0 +1,91 @@ +/*************************************************************************** + * Copyright (c) 2021 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 +#endif + +#include +#include "ReferenceHighlighter.h" + + +using namespace PartDesignGui; + +ReferenceHighlighter::ReferenceHighlighter(const TopoDS_Shape& shape, const App::Color& color) + : lineColor(color) + , singleEdges(1.0f,0.0f,1.0f) // magenta + , allEdges(0.6f,0.0f,1.0f) // purple +{ + TopExp::MapShapes(shape, TopAbs_EDGE, eMap); + TopExp::MapShapes(shape, TopAbs_FACE, fMap); +} + +void ReferenceHighlighter::getEdgeColor(const std::string& element, std::vector& colors) const +{ + int idx = std::stoi(element.substr(4)) - 1; + assert ( idx >= 0 ); + std::size_t pos = std::size_t(idx); + if (pos < colors.size()) + colors[pos] = singleEdges; +} + +void ReferenceHighlighter::getEdgeColorsOfFace(const std::string& element, std::vector& colors) const +{ + int idx = std::stoi(element.substr(4)); + assert ( idx > 0 ); + // get the edges of the faces + TopoDS_Shape face = fMap.FindKey(idx); + for (TopExp_Explorer xp(face, TopAbs_EDGE); xp.More(); xp.Next()) { + int edgeIndex = eMap.FindIndex(xp.Current()); + + // Edge found? + if (edgeIndex > 0) { + std::size_t pos = std::size_t(edgeIndex - 1); + if (pos < colors.size()) + colors[pos] = singleEdges; + } + } +} + +void ReferenceHighlighter::getEdgeColors(const std::vector& elements, + std::vector& colors) const +{ + colors.resize(eMap.Extent(), lineColor); + + if (!elements.empty()) { + for (std::string e : elements) { + if (boost::starts_with(e, "Edge")) { + getEdgeColor(e, colors); + } + else if (boost::starts_with(e, "Face")) { + getEdgeColorsOfFace(e, colors); + } + } + } + else { + std::fill(colors.begin(), colors.end(), allEdges); + } +} diff --git a/src/Mod/PartDesign/Gui/ReferenceHighlighter.h b/src/Mod/PartDesign/Gui/ReferenceHighlighter.h new file mode 100644 index 0000000000..498b80ae09 --- /dev/null +++ b/src/Mod/PartDesign/Gui/ReferenceHighlighter.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) 2021 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_REFERENCEHIGHLIGHTER_H +#define PARTGUI_REFERENCEHIGHLIGHTER_H + +#include +#include +#include +#include + +namespace PartDesignGui { + +/*! + * \brief The ReferenceHighlighter class + * \author Werner Mayer + */ +class ReferenceHighlighter +{ +public: + /*! + * \brief ReferenceHighlighter + * \param shape The input shape. + * \param color The standard edge color. + */ + ReferenceHighlighter(const TopoDS_Shape& shape, const App::Color& color); + /*! + * \brief getEdgeColors + * \param elements The sub-element names + * \param colors The size of the \a colors array is equal to the number of edges of the shape + */ + void getEdgeColors(const std::vector& elements, + std::vector& colors) const; + +private: + void getEdgeColor(const std::string& element, std::vector& colors) const; + void getEdgeColorsOfFace(const std::string& element, std::vector& colors) const; + +private: + App::Color lineColor; + App::Color singleEdges; + App::Color allEdges; + TopTools_IndexedMapOfShape eMap; + TopTools_IndexedMapOfShape fMap; +}; + + +} // namespace PartDesignGui + + +#endif // PARTGUI_REFERENCEHIGHLIGHTER_H diff --git a/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp b/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp index 7618e116dd..bfe2732761 100644 --- a/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskLoftParameters.cpp @@ -172,7 +172,6 @@ void TaskLoftParameters::onSelectionChanged(const Gui::SelectionChanges& msg) } clearButtons(); - //static_cast(vp)->highlightReferences(false, true); recomputeFeature(); } @@ -202,6 +201,7 @@ bool TaskLoftParameters::referenceSelected(const Gui::SelectionChanges& msg) con App::DocumentObject* obj = loft->getDocument()->getObject(msg.pObjectName); if (selectionMode == refProfile) { + static_cast(vp)->highlightReferences(ViewProviderLoft::Profile, false); loft->Profile.setValue(obj, {msg.pSubName}); return true; } @@ -262,7 +262,6 @@ void TaskLoftParameters::onDeleteSection() // `setValues(ref)` cleanly ensures subnames are preserved. loft->Sections.removeValue(obj); - //static_cast(vp)->highlightReferences(false, true); recomputeFeature(); updateUI(); } @@ -328,7 +327,12 @@ void TaskLoftParameters::onProfileButton(bool checked) Gui::Selection().clearSelection(); selectionMode = refProfile; this->blockSelection(false); - //static_cast(vp)->highlightReferences(true, true); + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, true); + } + else { + Gui::Selection().clearSelection(); + selectionMode = none; + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, false); } } @@ -339,7 +343,12 @@ void TaskLoftParameters::onRefButtonAdd(bool checked) Gui::Selection().clearSelection(); selectionMode = refAdd; this->blockSelection(false); - //static_cast(vp)->highlightReferences(true, true); + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, true); + } + else { + Gui::Selection().clearSelection(); + selectionMode = none; + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, false); } } @@ -350,7 +359,12 @@ void TaskLoftParameters::onRefButtonRemove(bool checked) Gui::Selection().clearSelection(); selectionMode = refRemove; this->blockSelection(false); - //static_cast(vp)->highlightReferences(true, true); + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, true); + } + else { + Gui::Selection().clearSelection(); + selectionMode = none; + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, false); } } @@ -379,6 +393,7 @@ bool TaskDlgLoftParameters::accept() { // TODO Fill this with commands (2015-09-11, Fat-Zer) PartDesign::Loft* pcLoft = static_cast(vp->getObject()); + static_cast(vp)->highlightReferences(ViewProviderLoft::Both, false); for (App::DocumentObject* obj : pcLoft->Sections.getValues()) { FCMD_OBJ_HIDE(obj); diff --git a/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp b/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp index 68e946a1f1..756175e487 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderLoft.cpp @@ -26,14 +26,12 @@ #ifndef _PreComp_ # include # include -# include -# include #endif #include "Utils.h" #include "ViewProviderLoft.h" -//#include "TaskLoftParameters.h" #include "TaskLoftParameters.h" +#include "ReferenceHighlighter.h" #include #include #include @@ -115,47 +113,63 @@ bool ViewProviderLoft::onDelete(const std::vector & /*s*/) return true; } -void ViewProviderLoft::highlightReferences(const bool /*on*/, bool /*auxiliary*/) -{/* +void ViewProviderLoft::highlightProfile(bool on) +{ PartDesign::Loft* pcLoft = static_cast(getObject()); - Part::Feature* base; - if(!auxiliary) - base = static_cast(pcLoft->Spine.getValue()); - else - base = static_cast(pcLoft->AuxillerySpine.getValue()); + highlightReferences(dynamic_cast(pcLoft->Profile.getValue()), + pcLoft->Profile.getSubValues(), on); +} - if (base == NULL) return; +void ViewProviderLoft::highlightSection(bool on) +{ + PartDesign::Loft* pcLoft = static_cast(getObject()); + auto sections = pcLoft->Sections.getSubListValues(); + for (auto it : sections) { + if (it.second.size() == 1 && it.second[0].empty()) + it.second.clear(); + highlightReferences(dynamic_cast(it.first), it.second, on); + } +} + +void ViewProviderLoft::highlightReferences(ViewProviderLoft::Reference mode, bool on) +{ + switch (mode) { + case Profile: + highlightProfile(on); + break; + case Section: + highlightSection(on); + break; + case Both: + highlightProfile(on); + highlightSection(on); + break; + default: + break; + } +} + +void ViewProviderLoft::highlightReferences(Part::Feature* base, const std::vector& elements, bool on) +{ PartGui::ViewProviderPart* svp = dynamic_cast( Gui::Application::Instance->getViewProvider(base)); - if (svp == NULL) return; + if (svp == nullptr) + return; - std::vector edges; - if(!auxiliary) - edges = pcLoft->Spine.getSubValuesStartsWith("Edge"); - else - edges = pcLoft->AuxillerySpine.getSubValuesStartsWith("Edge"); + std::vector& edgeColors = originalLineColors[base->getID()]; if (on) { - if (!edges.empty() && originalLineColors.empty()) { - TopTools_IndexedMapOfShape eMap; - TopExp::MapShapes(base->Shape.getValue(), TopAbs_EDGE, eMap); - originalLineColors = svp->LineColorArray.getValues(); - std::vector colors = originalLineColors; - colors.resize(eMap.Extent(), svp->LineColor.getValue()); + edgeColors = svp->LineColorArray.getValues(); + std::vector colors = edgeColors; - for (std::string e : edges) { - int idx = atoi(e.substr(4).c_str()) - 1; - if (idx < colors.size()) - colors[idx] = App::Color(1.0,0.0,1.0); // magenta - } - svp->LineColorArray.setValues(colors); - } - } else { - if (!edges.empty() && !originalLineColors.empty()) { - svp->LineColorArray.setValues(originalLineColors); - originalLineColors.clear(); - } - }*/ + ReferenceHighlighter highlighter(base->Shape.getValue(), svp->LineColor.getValue()); + highlighter.getEdgeColors(elements, colors); + svp->LineColorArray.setValues(colors); + } + else if (!edgeColors.empty()) { + svp->LineColorArray.setValues(edgeColors); + edgeColors.clear(); + } } QIcon ViewProviderLoft::getIcon(void) const { diff --git a/src/Mod/PartDesign/Gui/ViewProviderLoft.h b/src/Mod/PartDesign/Gui/ViewProviderLoft.h index 01f24e76c5..7c4dd1ec33 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderLoft.h +++ b/src/Mod/PartDesign/Gui/ViewProviderLoft.h @@ -33,6 +33,12 @@ class PartDesignGuiExport ViewProviderLoft : public ViewProviderAddSub PROPERTY_HEADER(PartDesignGui::ViewProviderLoft); public: + enum Reference { + Profile, + Section, + Both + }; + /// constructor ViewProviderLoft(); /// destructor @@ -43,17 +49,21 @@ public: void setupContextMenu(QMenu*, QObject*, const char*); virtual bool onDelete(const std::vector &); - void highlightReferences(const bool on, bool auxiliary); + void highlightProfile(bool on); + void highlightSection(bool on); + void highlightReferences(Reference mode, bool on); protected: + virtual QIcon getIcon(void) const; virtual bool setEdit(int ModNum); virtual void unsetEdit(int ModNum); virtual TaskDlgFeatureParameters* getEditDialog(); - - virtual QIcon getIcon(void) const; - + private: - std::vector originalLineColors; + void highlightReferences(Part::Feature*, const std::vector&, bool); + +private: + std::map> originalLineColors; };