From 40271a29ea7453d29d86111f1661279e98339bfd Mon Sep 17 00:00:00 2001 From: Paddle Date: Mon, 21 Nov 2022 09:34:32 +0100 Subject: [PATCH] Sketcher: Grid rework. Include: - Adding 'auto spacing' option. - Drawing grid dynamically on viewer area only. - Moving code to coinManager. - Adding a 'grid tool' to sketcher-edit-mode toolbar. --- src/Mod/Sketcher/Gui/AppSketcherGui.cpp | 1 + src/Mod/Sketcher/Gui/CMakeLists.txt | 3 + src/Mod/Sketcher/Gui/Command.cpp | 244 ++++++++- src/Mod/Sketcher/Gui/EditModeCoinManager.cpp | 35 +- src/Mod/Sketcher/Gui/EditModeCoinManager.h | 11 +- .../Gui/EditModeCoinManagerParameters.h | 5 + .../Sketcher/Gui/EditModeGridCoinManager.cpp | 237 +++++++++ .../Sketcher/Gui/EditModeGridCoinManager.h | 76 +++ src/Mod/Sketcher/Gui/Resources/Sketcher.qrc | 6 + .../icons/general/Sketcher_GridAuto.svg | 355 +++++++++++++ .../general/Sketcher_GridAuto_Deactivated.svg | 343 +++++++++++++ .../icons/general/Sketcher_GridSnap.svg | 305 ++++++++++++ .../general/Sketcher_GridSnap_Deactivated.svg | 305 ++++++++++++ .../icons/general/Sketcher_GridToggle.svg | 322 ++++++++++++ .../Sketcher_GridToggle_Deactivated.svg | 318 ++++++++++++ src/Mod/Sketcher/Gui/SketcherSettings.cpp | 113 ++++- src/Mod/Sketcher/Gui/SketcherSettings.h | 22 + .../Sketcher/Gui/SketcherSettingsDisplay.ui | 40 +- src/Mod/Sketcher/Gui/SketcherSettingsGrid.ui | 471 ++++++++++++++++++ src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 93 +++- src/Mod/Sketcher/Gui/ViewProviderSketch.h | 15 +- .../Gui/ViewProviderSketchCoinAttorney.h | 7 +- src/Mod/Sketcher/Gui/Workbench.cpp | 3 +- 23 files changed, 3205 insertions(+), 125 deletions(-) create mode 100644 src/Mod/Sketcher/Gui/EditModeGridCoinManager.cpp create mode 100644 src/Mod/Sketcher/Gui/EditModeGridCoinManager.h create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto.svg create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto_Deactivated.svg create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap.svg create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap_Deactivated.svg create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle.svg create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle_Deactivated.svg create mode 100644 src/Mod/Sketcher/Gui/SketcherSettingsGrid.ui diff --git a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp index 3d8f11b284..345c71a6ca 100644 --- a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp +++ b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp @@ -127,6 +127,7 @@ PyMOD_INIT_FUNC(SketcherGui) SketcherGui::ViewProviderSketchGeometryExtension ::init(); (void)new Gui::PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Sketcher") ); + (void)new Gui::PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Sketcher") ); (void)new Gui::PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Sketcher") ); (void)new Gui::PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Sketcher") ); diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index 8b93cebf55..ff3338aea5 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -38,6 +38,7 @@ set(SketcherGui_UIC_SRCS SketchOrientationDialog.ui SketchMirrorDialog.ui SketcherSettings.ui + SketcherSettingsGrid.ui SketcherSettingsColors.ui SketcherSettingsDisplay.ui SketchRectangularArrayDialog.ui @@ -119,6 +120,8 @@ SET(SketcherGui_SRCS EditModeCoinManagerParameters.cpp EditModeCoinManager.cpp EditModeCoinManager.h + EditModeGridCoinManager.cpp + EditModeGridCoinManager.h EditModeGeometryCoinManager.cpp EditModeGeometryCoinManager.h EditModeConstraintCoinManager.cpp diff --git a/src/Mod/Sketcher/Gui/Command.cpp b/src/Mod/Sketcher/Gui/Command.cpp index 196fa7b900..5b694dacae 100644 --- a/src/Mod/Sketcher/Gui/Command.cpp +++ b/src/Mod/Sketcher/Gui/Command.cpp @@ -25,14 +25,20 @@ # include # include # include +# include +# include #endif #include #include +#include +#include +#include #include #include #include #include +#include #include #include #include @@ -124,6 +130,14 @@ namespace SketcherGui { } } //namespace SketcherGui +bool isSketchInEdit(Gui::Document* doc) { + if (doc) { + // checks if a Sketch Viewprovider is in Edit and is in no special mode + auto* vp = dynamic_cast(doc->getInEdit()); + return (vp != nullptr); + } + return false; +} /* Sketch commands =======================================================*/ DEF_STD_CMD_A(CmdSketcherNewSketch) @@ -314,14 +328,7 @@ void CmdSketcherLeaveSketch::activated(int iMsg) bool CmdSketcherLeaveSketch::isActive() { - Gui::Document *doc = getActiveGuiDocument(); - if (doc) { - // checks if a Sketch Viewprovider is in Edit and is in no special mode - SketcherGui::ViewProviderSketch* vp = dynamic_cast(doc->getInEdit()); - if (vp /*&& vp->getSketchMode() == ViewProviderSketch::STATUS_NONE*/) - return true; - } - return false; + return isSketchInEdit(getActiveGuiDocument()); } DEF_STD_CMD_A(CmdSketcherStopOperation) @@ -697,14 +704,7 @@ void CmdSketcherViewSketch::activated(int iMsg) bool CmdSketcherViewSketch::isActive() { - Gui::Document *doc = getActiveGuiDocument(); - if (doc) { - // checks if a Sketch Viewprovider is in Edit and is in no special mode - SketcherGui::ViewProviderSketch* vp = dynamic_cast(doc->getInEdit()); - if (vp /*&& vp->getSketchMode() == ViewProviderSketch::STATUS_NONE*/) - return true; - } - return false; + return isSketchInEdit(getActiveGuiDocument()); } DEF_STD_CMD_A(CmdSketcherValidateSketch) @@ -971,16 +971,211 @@ void CmdSketcherViewSection::activated(int iMsg) bool CmdSketcherViewSection::isActive() { - Gui::Document *doc = getActiveGuiDocument(); - if (doc) { - // checks if a Sketch Viewprovider is in Edit and is in no special mode - SketcherGui::ViewProviderSketch* vp = dynamic_cast(doc->getInEdit()); - if (vp /*&& vp->getSketchMode() == ViewProviderSketch::STATUS_NONE*/) - return true; - } - return false; + return isSketchInEdit(getActiveGuiDocument()); } +/* Grid tool */ +class GridSpaceAction : public QWidgetAction +{ +public: + GridSpaceAction(QObject* parent) : QWidgetAction(parent) { + } + +protected: + QWidget* createWidget(QWidget* parent) override + { + auto* sizeLabel = new QLabel(QApplication::translate("Sketcher_GridSize", "Spacing")); + auto* gridSizeBox = new Gui::QuantitySpinBox(); + gridSizeBox->setProperty("unit", QVariant(QStringLiteral("mm"))); + gridSizeBox->setObjectName(QStringLiteral("gridSize")); + gridSizeBox->setToolTip(QApplication::translate("Sketcher_GridSize", "Distance between two subsequent grid lines")); + //Is General/GridSize correct? From taskSketcherGeneral it seems yes. + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General/GridSize"); + gridSizeBox->setValue(hGrp->GetFloat("GridSize", 10.0)); + gridSizeBox->setMaximum(99999999.0); + gridSizeBox->setMinimum(0.001); + + QObject::connect(gridSizeBox, qOverload(&Gui::QuantitySpinBox::valueChanged), + [=](double val) { + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + assert(doc); + auto* sketchView = dynamic_cast(doc->getInEdit()); + assert(sketchView); + + sketchView->GridSize.setValue(val); + }); + + QWidget* gridSizeW = new QWidget(parent); + QHBoxLayout* layout = new QHBoxLayout(gridSizeW); + layout->addWidget(sizeLabel); + layout->addWidget(gridSizeBox); + gridSizeW->installEventFilter(this); + return gridSizeW; + } + + bool eventFilter(QObject* obj, QEvent* event) override + { + if (event->type() == QEvent::Show) { + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (doc) { + auto* sketchView = dynamic_cast(doc->getInEdit()); + if (sketchView && sketchView->GridSize.getValue() > 0) { + double gridSize = sketchView->GridSize.getValue(); + + QList widgets = createdWidgets(); + for (auto it : widgets) { + if (auto* gridSizeBox = it->findChild(QStringLiteral("gridSize"))) { + QSignalBlocker sigblk(gridSizeBox); + gridSizeBox->setValue(gridSize); + } + } + } + } + } + + return QWidgetAction::eventFilter(obj, event); + } +}; + +DEF_STD_CMD_ACL(CmdSketcherCompGrid) + +CmdSketcherCompGrid::CmdSketcherCompGrid() + : Command("Sketcher_CompGrid") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Activate Grid"); + sToolTipText = QT_TR_NOOP("Activate grid and further settings"); + sWhatsThis = "Sketcher_CompGrid"; + sStatusTip = sToolTipText; + eType = 0; +} + +void CmdSketcherCompGrid::activated(int iMsg) +{ + Gui::ActionGroup* pcAction = qobject_cast(getAction()); + assert(pcAction); + QList a = pcAction->actions(); + + Gui::Document* doc = getActiveGuiDocument(); + assert(doc); + auto* sketchView = dynamic_cast(doc->getInEdit()); + assert(sketchView); + + if (iMsg == 0) { + bool newState = !a[0]->isChecked(); + a[0]->setChecked(newState); + sketchView->ShowGrid.setValue(newState); + + //activate/deactivate others + a[1]->setEnabled(newState); + a[2]->setEnabled(newState); + } + else if (iMsg == 1) { + bool newState = !a[1]->isChecked(); + a[0]->setChecked(newState); + sketchView->GridSnap.setValue(newState); + + pcAction->setProperty("defaultAction", QVariant(0)); + } + else if (iMsg == 2){ + bool newState = !a[2]->isChecked(); + a[2]->setChecked(newState); + sketchView->GridAuto.setValue(newState); + + a[3]->setEnabled(!newState); + if (!newState) + sketchView->GridSize.setValue(sketchView->GridSize.getValue()); //redraw grid. + + pcAction->setProperty("defaultAction", QVariant(0)); + } + else if (iMsg == 3) { + //nothing but don't return either. + } + else + return; + + pcAction->setIcon(Gui::BitmapFactory().iconFromTheme(a[0]->isChecked() ? "Sketcher_GridToggle" : "Sketcher_GridToggle_Deactivated")); +} + +Gui::Action* CmdSketcherCompGrid::createAction() +{ + Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); + pcAction->setDropDownMenu(true); + pcAction->setExclusive(false); + applyCommandData(this->className(), pcAction); + + QAction* a0 = pcAction->addAction(QString()); + QAction* a1 = pcAction->addAction(QString()); + QAction* a2 = pcAction->addAction(QString()); + + GridSpaceAction* a3 = new GridSpaceAction(pcAction); + pcAction->addAction(a3); + + a0->setCheckable(true); + a1->setCheckable(true); + a2->setCheckable(true); + + _pcAction = pcAction; + languageChange(); + + return pcAction; +} + +void CmdSketcherCompGrid::languageChange() +{ + Command::languageChange(); + + if (!_pcAction) + return; + Gui::ActionGroup* pcAction = qobject_cast(_pcAction); + QList a = pcAction->actions(); + + QAction* a0 = a[0]; + a0->setText(QApplication::translate("CmdSketcherCompGrid", "Activate Grid")); + a0->setToolTip(QApplication::translate("CmdSketcherCompGrid", "Activate Grid")); + a0->setStatusTip(a0->toolTip()); + QAction* a1 = a[1]; + a1->setText(QApplication::translate("CmdSketcherCompGrid", "Grid Snap")); + a1->setToolTip(QApplication::translate("CmdSketcherCompGrid", "New points will snap to the nearest grid line.\nPoints must be set closer than a fifth of the grid spacing to a grid line to snap.")); + a1->setStatusTip(a1->toolTip()); + QAction* a2 = a[2]; + a2->setText(QApplication::translate("CmdSketcherCompGrid", "Grid Auto Spacing")); + a2->setToolTip(QApplication::translate("CmdSketcherCompGrid", "Resize grid automatically depending on zoom.")); + a2->setStatusTip(a2->toolTip()); +} + +bool CmdSketcherCompGrid::isActive() +{ + //Initialisation of the commands to the sketch specific settings + Gui::Document* doc = getActiveGuiDocument(); + if (doc && isSketchInEdit(doc)) { + auto* sketchView = dynamic_cast(doc->getInEdit()); + Gui::ActionGroup* pcAction = qobject_cast(getAction()); + if (sketchView && pcAction) { + QList a = pcAction->actions(); + + bool showGrid = sketchView->ShowGrid.getValue(); + bool gridSnap = sketchView->GridSnap.getValue(); + bool gridAuto = sketchView->GridAuto.getValue(); + + a[0]->setChecked(showGrid); + a[1]->setChecked(gridSnap); + a[2]->setChecked(gridAuto); + + //activate/deactivate others + a[1]->setEnabled(showGrid); + a[2]->setEnabled(showGrid); + a[3]->setEnabled(showGrid && !gridAuto); + + pcAction->setIcon(Gui::BitmapFactory().iconFromTheme(showGrid ? "Sketcher_GridToggle" : "Sketcher_GridToggle_Deactivated")); + } + } + + return isSketchInEdit(getActiveGuiDocument()); +} + + void CreateSketcherCommands() { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); @@ -996,4 +1191,5 @@ void CreateSketcherCommands() rcCmdMgr.addCommand(new CmdSketcherMirrorSketch()); rcCmdMgr.addCommand(new CmdSketcherMergeSketches()); rcCmdMgr.addCommand(new CmdSketcherViewSection()); + rcCmdMgr.addCommand(new CmdSketcherCompGrid()); } diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp index 9abd818da6..6de1918122 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp @@ -57,6 +57,14 @@ #include "ViewProviderSketch.h" #include "ViewProviderSketchCoinAttorney.h" +#include "EditModeGridCoinManager.h" + +#include "EditModeGeometryCoinManager.h" +#include "EditModeConstraintCoinManager.h" + +#include "EditModeCoinManager.h" + +#include "Utils.h" using namespace SketcherGui; using namespace Sketcher; @@ -342,6 +350,9 @@ EditModeCoinManager::EditModeCoinManager(ViewProviderSketch &vp):viewProvider(vp analysisResults, editModeScenegraphNodes, coinMapping); + + pEditModeGridCoinManager = std::make_unique( viewProvider, + editModeScenegraphNodes); // Create Edit Mode Scenograph createEditModeInventorNodes(); @@ -573,8 +584,6 @@ void EditModeCoinManager::processGeometryConstraintsInformationOverlay(const Geo updateAxesLength(); - updateGridExtent(); - pEditModeConstraintCoinManager->processConstraints(geolistfacade); } @@ -613,13 +622,6 @@ void EditModeCoinManager::updateAxesLength() editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(3,SbVec3f(0.0f, analysisResults.boundingBoxMagnitudeOrder, zCrossH)); } -void EditModeCoinManager::updateGridExtent() -{ - float dMagF = analysisResults.boundingBoxMagnitudeOrder; - - ViewProviderSketchCoinAttorney::updateGridExtent(viewProvider,-dMagF, dMagF, -dMagF, dMagF); -} - void EditModeCoinManager::updateColor() { auto geolistfacade = ViewProviderSketchCoinAttorney::getGeoListFacade(viewProvider); @@ -657,6 +659,14 @@ void EditModeCoinManager::createEditModeInventorNodes() ViewProviderSketchCoinAttorney::addNodeToRoot(viewProvider, editModeScenegraphNodes.EditRoot); editModeScenegraphNodes.EditRoot->renderCaching = SoSeparator::OFF ; + // Create Grid Coin nodes ++++++++++++++++++++++++++++++++++++++++++ + editModeScenegraphNodes.GridRoot = new SoSeparator(); + editModeScenegraphNodes.GridRoot->ref(); + editModeScenegraphNodes.GridRoot->setName("GridRoot"); + editModeScenegraphNodes.EditRoot->addChild(editModeScenegraphNodes.GridRoot); + if (viewProvider.ShowGrid.getValue()) + pEditModeGridCoinManager->createGrid(); + // Create Geometry Coin nodes ++++++++++++++++++++++++++++++++++++++ pEditModeGeometryCoinManager->createEditModeInventorNodes(); @@ -804,6 +814,13 @@ void EditModeCoinManager::updateVirtualSpace() pEditModeConstraintCoinManager->updateVirtualSpace(); } +void EditModeCoinManager::drawGrid(bool cameraUpdate) { + if (viewProvider.ShowGrid.getValue()) + pEditModeGridCoinManager->createGrid(cameraUpdate); + else + Gui::coinRemoveAllChildren(editModeScenegraphNodes.GridRoot); +} + /************************ Resizing of coin nodes ************************/ int EditModeCoinManager::defaultApplicationFontSizePixels() const { diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.h b/src/Mod/Sketcher/Gui/EditModeCoinManager.h index beb5659e49..d4630fd856 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManager.h +++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.h @@ -60,6 +60,7 @@ namespace SketcherGui { class ViewProviderSketch; class EditModeConstraintCoinManager; class EditModeGeometryCoinManager; +class EditModeGridCoinManager; using GeoList = Sketcher::GeoList; using GeoListFacade = Sketcher::GeoListFacade; @@ -216,6 +217,9 @@ public: void drawConstraintIcons(const GeoListFacade & geolistfacade); //@} + //Draw the grid + void drawGrid(bool cameraUpdate = false); + /** @name coin node access*/ SoSeparator* getRootEditNode(); //@} @@ -226,12 +230,6 @@ public: void updateColor(const GeoListFacade & geolistfacade); // overload to be used with temporal geometry. //@} - - /** @name change coin visualisation and behaviour*/ - //@{ - void updateGridExtent(); - //@} - /** @name change constraints selectability*/ //@{ void setConstraintSelectability(bool enabled = true); @@ -289,6 +287,7 @@ private: // Coin Helpers std::unique_ptr pEditModeConstraintCoinManager; std::unique_ptr pEditModeGeometryCoinManager; + std::unique_ptr pEditModeGridCoinManager; }; diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h b/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h index 9e4781a9d5..3f82baf867 100644 --- a/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h +++ b/src/Mod/Sketcher/Gui/EditModeCoinManagerParameters.h @@ -281,6 +281,11 @@ struct ConstraintParameters { /** @brief Helper struct adapted to store the pointer to edit mode scenegraph objects. */ struct EditModeScenegraphNodes { + /** @name Grid nodes*/ + //@{ + SoSeparator * GridRoot; + //@} + /** @name Point nodes*/ //@{ SoSeparator * EditRoot; diff --git a/src/Mod/Sketcher/Gui/EditModeGridCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeGridCoinManager.cpp new file mode 100644 index 0000000000..3f33775861 --- /dev/null +++ b/src/Mod/Sketcher/Gui/EditModeGridCoinManager.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** + * Copyright (c) 2021 Abdullah Tahiri * + * * + * 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 +#endif // #ifndef _PreComp_ + +#include +#include +#include + +#include "EditModeCoinManager.h" +#include "EditModeGridCoinManager.h" + +using namespace SketcherGui; + +//**************************** EditModeGridCoinManager class ****************************** + +EditModeGridCoinManager::EditModeGridCoinManager( ViewProviderSketch &vp, + EditModeScenegraphNodes & editModeScenegraph): + camCenterOnSketch(SbVec3f(0., 0., 0.)), + camMaxDimension(200.), + viewProvider(vp), + editModeScenegraphNodes(editModeScenegraph) +{ +} + +EditModeGridCoinManager::~EditModeGridCoinManager() +{} + +double EditModeGridCoinManager::getGridSize(const Gui::View3DInventorViewer* viewer) +{ + short pixelWidth = -1; + short pixelHeight = -1; + viewer->getViewportRegion().getViewportSizePixels().getValue(pixelWidth, pixelHeight); + if (pixelWidth < 0 || pixelHeight < 0) + return viewProvider.GridSize.getValue(); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General"); + int numberOfLines = std::max(pixelWidth, pixelHeight) / hGrp->GetInt("GridSizePixelThreshold", 15); + ParameterGrp::handle hGrp2 = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Units"); + int units = hGrp2->GetInt("UserSchema", 0); //2 3 5 7 are imperial schemas. 2 3 inches, 5 7 feet + double unitMultiplier = (units == 2 || units == 3) ? 25.4 : (units == 5 || units == 7) ? 304.8 : 1; + + int subdivisions = hGrp->GetInt("GridNumberSubdivision", 10); + double newGridSize = unitMultiplier * pow(subdivisions, 1 + floor(log(camMaxDimension / unitMultiplier / numberOfLines) / log(subdivisions))); + + //cap the grid size + newGridSize = std::max(newGridSize, 0.000001); + newGridSize = std::min(newGridSize, 10000000.0); + + if (newGridSize != viewProvider.GridSize.getValue()) // protect from recursive calls + viewProvider.GridSize.setValue(newGridSize); //grid size must be set for grid snap. But we need to block it from calling createGrid. + + return newGridSize; +} + +SoSeparator* EditModeGridCoinManager::createGrid(bool cameraUpdate) +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General"); + Gui::MDIView* mdi = Gui::Application::Instance->editDocument()->getActiveView(); + Gui::View3DInventorViewer* viewer = static_cast(mdi)->getViewer(); + + //First check if the user zoomed in or out by getting the camera dimension. + float newCamMaxDimension = viewer->getMaxDimension(); + bool cameraDimensionsChanged = false; + if (fabs(newCamMaxDimension - camMaxDimension) > 0) { //ie if user zoomed. + camMaxDimension = newCamMaxDimension; + cameraDimensionsChanged = true; + } + + //Then we check if user moved by more than 10% of camera dimension (must be after updating camera dimension). + SbVec3f newCamCenterOnSketch = viewer->getCenterPointOnFocalPlane(); + bool cameraCenterMoved = false; + if ((camCenterOnSketch - newCamCenterOnSketch).length() > 0.1 * camMaxDimension) { + camCenterOnSketch = newCamCenterOnSketch; + cameraCenterMoved = true; + } + + bool gridNeedUpdating = cameraDimensionsChanged || cameraCenterMoved; + + if (!gridNeedUpdating && cameraUpdate) + return editModeScenegraphNodes.GridRoot; + + Gui::coinRemoveAllChildren(editModeScenegraphNodes.GridRoot); + + double step; + if (viewProvider.GridAuto.getValue()) + step = getGridSize(viewer); + else + step = viewProvider.GridSize.getValue(); + + int numberSubdivision = hGrp->GetInt("GridNumberSubdivision", 10); + + auto getColor = [](auto prefName) { + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General"); + SoBaseColor* lineColor = new SoBaseColor; + float transparency; + SbColor lineCol(0.7f, 0.7f, 0.7f); + unsigned long lineColorL = hGrp->GetUnsigned(prefName, (unsigned long)(lineCol.getPackedValue())); + lineCol.setPackedValue((uint32_t)lineColorL, transparency); + lineColor->rgb.setValue(lineCol); + return lineColor; + + }; + + //First we create the subdivision lines + createGridPart(step, numberSubdivision, true, (numberSubdivision == 1) ? true : false, + hGrp->GetInt("GridLinePattern", 0x0f0f), getColor("GridLineColor"), hGrp->GetInt("GridLineWidth", 1)); + + //Second we create the wider lines marking every nth lines + if (numberSubdivision > 1) { + createGridPart(step, numberSubdivision, false, true, + hGrp->GetInt("GridDivLinePattern", 0xffff), getColor("GridDivLineColor"), hGrp->GetInt("GridDivLineWidth", 2)); + } + + return editModeScenegraphNodes.GridRoot; +} + +SoSeparator* EditModeGridCoinManager::createGridPart(double Step, int numberSubdiv, bool subDivLines, bool divLines, int pattern, SoBaseColor* color, int lineWidth) +{ + SoGroup* parent = new Gui::SoSkipBoundingGroup(); + editModeScenegraphNodes.GridRoot->addChild(parent); + SoVertexProperty* vts; + + parent->addChild(color); + + if (viewProvider.GridStyle.getValue() == 0) { + SoDrawStyle* DefaultStyle = new SoDrawStyle; + DefaultStyle->lineWidth = lineWidth; + DefaultStyle->linePattern = pattern; + parent->addChild(DefaultStyle); + } + else { + SoMaterial* LightStyle = new SoMaterial; + LightStyle->transparency = 0.7f; + parent->addChild(LightStyle); + } + + SoPickStyle* PickStyle = new SoPickStyle; + PickStyle->style = SoPickStyle::UNPICKABLE; + parent->addChild(PickStyle); + + SoLineSet* grid = new SoLineSet; + vts = new SoVertexProperty; + grid->vertexProperty = vts; + + float gridDimension = 1.5 * camMaxDimension; + int vlines = static_cast(gridDimension / Step); + int nlines = 2 * vlines; + if (nlines > 2000) { + Gui::coinRemoveAllChildren(editModeScenegraphNodes.GridRoot); + return editModeScenegraphNodes.GridRoot; + } + + // set the grid indices + grid->numVertices.setNum(nlines); + int32_t* vertices = grid->numVertices.startEditing(); + for (int i = 0; i < nlines; i++) + vertices[i] = 2; + grid->numVertices.finishEditing(); + + // set the grid coordinates + vts->vertex.setNum(2 * nlines); + SbVec3f* vertex_coords = vts->vertex.startEditing(); + + float minX, minY, maxX, maxY, z; + camCenterOnSketch.getValue(minX, minY, z); + minX -= (gridDimension / 2); + minY -= (gridDimension / 2); + maxX = minX + gridDimension; + maxY = minY + gridDimension; + + // vertical lines + int i_offset_x = static_cast(minX / Step); + for (int i = 0; i < vlines; i++) { + int iStep = (i + i_offset_x); + if (((iStep % numberSubdiv == 0) && divLines) || ((iStep % numberSubdiv != 0) && subDivLines)) { + vertex_coords[2 * i].setValue(iStep * Step, minY, 0); + vertex_coords[2 * i + 1].setValue(iStep * Step, maxY, 0); + } + else { + /*the number of vertices is defined before. To know the number of vertices ahead it would require + to run the loop once before, which would double computation time. + If vertices are not filled then there're visual bugs so there are here filled with dummy values.*/ + vertex_coords[2 * i].setValue(0, 0, 0); + vertex_coords[2 * i + 1].setValue(0, 0, 0); + } + } + + // horizontal lines + int i_offset_y = static_cast(minY / Step) - vlines; + for (int i = vlines; i < nlines; i++) { + int iStep = (i + i_offset_y); + if (((iStep % numberSubdiv == 0) && divLines) || ((iStep % numberSubdiv != 0) && subDivLines)) { + vertex_coords[2 * i].setValue(minX, iStep * Step, 0); + vertex_coords[2 * i + 1].setValue(maxX, iStep * Step, 0); + } + else { + vertex_coords[2 * i].setValue(0, 0, 0); + vertex_coords[2 * i + 1].setValue(0, 0, 0); + } + } + vts->vertex.finishEditing(); + + parent->addChild(vts); + parent->addChild(grid); + + return editModeScenegraphNodes.GridRoot; +} diff --git a/src/Mod/Sketcher/Gui/EditModeGridCoinManager.h b/src/Mod/Sketcher/Gui/EditModeGridCoinManager.h new file mode 100644 index 0000000000..d6147c32a4 --- /dev/null +++ b/src/Mod/Sketcher/Gui/EditModeGridCoinManager.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) 2021 Abdullah Tahiri * + * * + * 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 SKETCHERGUI_EditModeGridCoinManager_H +#define SKETCHERGUI_EditModeGridCoinManager_H + +#include +#include +#include + +#include +#include +#include + +#include "ViewProviderSketch.h" +#include "EditModeCoinManagerParameters.h" + +namespace SketcherGui { + +class ViewProviderSketch; + +/** @brief Class for managing the Edit mode coin nodes of ViewProviderSketch relating to grid. + * @details + * + * EditModeGridCoinManager is a helper of EditModeCoinManager specialised in grid management. + * + * 1. Creation of Edit mode coin nodes to handle grid representation. + * + */ +class SketcherGuiExport EditModeGridCoinManager +{ + +public: + explicit EditModeGridCoinManager( ViewProviderSketch &vp, + EditModeScenegraphNodes & editModeScenegraph); + ~EditModeGridCoinManager(); + + double getGridSize(const Gui::View3DInventorViewer* viewer); + SoSeparator* createGrid(bool cameraUpdate = false); + SoSeparator* createGridPart(double Step, int numberSubdiv, bool divLines, bool subDivLines, int pattern, SoBaseColor* color, int lineWidth = 1); + + SbVec3f camCenterOnSketch; + float camMaxDimension; + +private: + ViewProviderSketch & viewProvider; + + EditModeScenegraphNodes & editModeScenegraphNodes; +}; + + +} // namespace SketcherGui + + +#endif // SKETCHERGUI_EditModeGridCoinManager_H + diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index 19bef56ed0..0807935add 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -104,6 +104,12 @@ icons/general/Sketcher_ValidateSketch.svg icons/general/Sketcher_ViewSection.svg icons/general/Sketcher_ViewSketch.svg + icons/general/Sketcher_GridToggle.svg + icons/general/Sketcher_GridToggle_Deactivated.svg + icons/general/Sketcher_GridSnap.svg + icons/general/Sketcher_GridSnap_Deactivated.svg + icons/general/Sketcher_GridAuto.svg + icons/general/Sketcher_GridAuto_Deactivated.svg icons/geometry/Sketcher_AlterFillet.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto.svg b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto.svg new file mode 100644 index 0000000000..24a23e6f30 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto.svg @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Section.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + A + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto_Deactivated.svg b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto_Deactivated.svg new file mode 100644 index 0000000000..6dbd46f8de --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridAuto_Deactivated.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Section.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap.svg b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap.svg new file mode 100644 index 0000000000..69e273e5c7 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap.svg @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Section.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap_Deactivated.svg b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap_Deactivated.svg new file mode 100644 index 0000000000..0d21fbdd21 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridSnap_Deactivated.svg @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Section.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle.svg b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle.svg new file mode 100644 index 0000000000..df3dcb116e --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle.svg @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Section.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle_Deactivated.svg b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle_Deactivated.svg new file mode 100644 index 0000000000..c92a87f4b0 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/general/Sketcher_GridToggle_Deactivated.svg @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + 2011-10-10 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Section.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/SketcherSettings.cpp b/src/Mod/Sketcher/Gui/SketcherSettings.cpp index 6cfdda8bb1..39f99b9d53 100644 --- a/src/Mod/Sketcher/Gui/SketcherSettings.cpp +++ b/src/Mod/Sketcher/Gui/SketcherSettings.cpp @@ -34,6 +34,8 @@ #include "SketcherSettings.h" #include "ui_SketcherSettings.h" +#include "ui_SketcherSettingsGrid.h" +#include "ui_SketcherSettingsDisplay.h" #include "ui_SketcherSettingsColors.h" #include "ui_SketcherSettingsDisplay.h" #include "TaskSketcherGeneral.h" @@ -99,23 +101,23 @@ void SketcherSettings::changeEvent(QEvent *e) } } +/* TRANSLATOR SketcherGui::SketcherSettingsGrid */ -/* TRANSLATOR SketcherGui::SketcherSettingsDisplay */ - -SketcherSettingsDisplay::SketcherSettingsDisplay(QWidget* parent) - : PreferencePage(parent), ui(new Ui_SketcherSettingsDisplay) +SketcherSettingsGrid::SketcherSettingsGrid(QWidget* parent) + : PreferencePage(parent), ui(new Ui_SketcherSettingsGrid) { ui->setupUi(this); QList < QPair > styles; styles << qMakePair(Qt::SolidLine, 0xffff) - << qMakePair(Qt::DashLine, 0x0f0f) - << qMakePair(Qt::DotLine, 0xaaaa); -// << qMakePair(Qt::DashDotLine, 0x????) -// << qMakePair(Qt::DashDotDotLine, 0x????); - ui->comboBox->setIconSize (QSize(80, 12)); + << qMakePair(Qt::DashLine, 0x0f0f) + << qMakePair(Qt::DotLine, 0xaaaa); + // << qMakePair(Qt::DashDotLine, 0x????) + // << qMakePair(Qt::DashDotDotLine, 0x????); + ui->gridLinePattern->setIconSize(QSize(80, 12)); + ui->gridDivLinePattern->setIconSize(QSize(80, 12)); for (QList < QPair >::iterator it = styles.begin(); it != styles.end(); ++it) { - QPixmap px(ui->comboBox->iconSize()); + QPixmap px(ui->gridLinePattern->iconSize()); px.fill(Qt::transparent); QBrush brush(Qt::black); QPen pen(it->first); @@ -124,12 +126,86 @@ SketcherSettingsDisplay::SketcherSettingsDisplay(QWidget* parent) QPainter painter(&px); painter.setPen(pen); - double mid = ui->comboBox->iconSize().height() / 2.0; - painter.drawLine(0, mid, ui->comboBox->iconSize().width(), mid); + double mid = ui->gridLinePattern->iconSize().height() / 2.0; + painter.drawLine(0, mid, ui->gridLinePattern->iconSize().width(), mid); painter.end(); - ui->comboBox->addItem(QIcon(px), QString(), QVariant(it->second)); + ui->gridLinePattern->addItem(QIcon(px), QString(), QVariant(it->second)); + ui->gridDivLinePattern->addItem(QIcon(px), QString(), QVariant(it->second)); } +} + +SketcherSettingsGrid::~SketcherSettingsGrid() +{ + // no need to delete child widgets, Qt does it all for us +} + +void SketcherSettingsGrid::saveSettings() +{ + ui->checkBoxShowGrid->onSave(); + ui->gridSize->onSave(); + ui->checkBoxGridSnap->onSave(); + ui->checkBoxGridAuto->onSave(); + ui->gridSizePixelThreshold->onSave(); + ui->gridLineColor->onSave(); + ui->gridDivLineColor->onSave(); + ui->gridLineWidth->onSave(); + ui->gridDivLineWidth->onSave(); + ui->gridNumberSubdivision->onSave(); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General"); + QVariant data = ui->gridLinePattern->itemData(ui->gridLinePattern->currentIndex()); + int pattern = data.toInt(); + hGrp->SetInt("GridLinePattern", pattern); + + data = ui->gridDivLinePattern->itemData(ui->gridDivLinePattern->currentIndex()); + pattern = data.toInt(); + hGrp->SetInt("GridDivLinePattern", pattern); +} + +void SketcherSettingsGrid::loadSettings() +{ + ui->checkBoxShowGrid->onRestore(); + ui->gridSize->onRestore(); + ui->checkBoxGridSnap->onRestore(); + ui->checkBoxGridAuto->onRestore(); + ui->gridSizePixelThreshold->onRestore(); + ui->gridLineColor->onRestore(); + ui->gridDivLineColor->onRestore(); + ui->gridLineWidth->onRestore(); + ui->gridDivLineWidth->onRestore(); + ui->gridNumberSubdivision->onRestore(); + + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General"); + int pattern = hGrp->GetInt("GridLinePattern", 0x0f0f); + int index = ui->gridLinePattern->findData(QVariant(pattern)); + if (index < 0) index = 1; + ui->gridLinePattern->setCurrentIndex(index); + pattern = hGrp->GetInt("GridDivLinePattern", 0xffff); + index = ui->gridDivLinePattern->findData(QVariant(pattern)); + if (index < 0) index = 0; + ui->gridDivLinePattern->setCurrentIndex(index); +} + +/** + * Sets the strings of the subwidgets using the current language. + */ +void SketcherSettingsGrid::changeEvent(QEvent* e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + } + else { + QWidget::changeEvent(e); + } +} + +/* TRANSLATOR SketcherGui::SketcherSettingsDisplay */ + +SketcherSettingsDisplay::SketcherSettingsDisplay(QWidget* parent) + : PreferencePage(parent), ui(new Ui_SketcherSettingsDisplay) +{ + ui->setupUi(this); connect(ui->btnTVApply, &QPushButton::clicked, this, &SketcherSettingsDisplay::onBtnTVApplyClicked); } @@ -161,11 +237,6 @@ void SketcherSettingsDisplay::saveSettings() ui->checkBoxTVRestoreCamera->onSave(); ui->checkBoxTVForceOrtho->onSave(); ui->checkBoxTVSectionView->onSave(); - - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part"); - QVariant data = ui->comboBox->itemData(ui->comboBox->currentIndex()); - int pattern = data.toInt(); - hGrp->SetInt("GridLinePattern", pattern); } void SketcherSettingsDisplay::loadSettings() @@ -188,12 +259,6 @@ void SketcherSettingsDisplay::loadSettings() ui->checkBoxTVForceOrtho->onRestore(); this->ui->checkBoxTVForceOrtho->setEnabled(this->ui->checkBoxTVRestoreCamera->isChecked()); ui->checkBoxTVSectionView->onRestore(); - - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part"); - int pattern = hGrp->GetInt("GridLinePattern", 0x0f0f); - int index = ui->comboBox->findData(QVariant(pattern)); - if (index <0) index = 1; - ui->comboBox->setCurrentIndex(index); } /** diff --git a/src/Mod/Sketcher/Gui/SketcherSettings.h b/src/Mod/Sketcher/Gui/SketcherSettings.h index 08804130a5..968097dbc0 100644 --- a/src/Mod/Sketcher/Gui/SketcherSettings.h +++ b/src/Mod/Sketcher/Gui/SketcherSettings.h @@ -29,6 +29,7 @@ namespace SketcherGui { class Ui_SketcherSettings; +class Ui_SketcherSettingsGrid; class Ui_SketcherSettingsDisplay; class Ui_SketcherSettingsColors; class SketcherGeneralWidget; @@ -55,6 +56,27 @@ private: SketcherGeneralWidget* form; }; +/** + * The SketcherSettings class implements a preference page to change sketcher grid settings. + */ +class SketcherSettingsGrid : public Gui::Dialog::PreferencePage +{ + Q_OBJECT + +public: + explicit SketcherSettingsGrid(QWidget* parent = nullptr); + ~SketcherSettingsGrid() override; + + void saveSettings() override; + void loadSettings() override; + +protected: + void changeEvent(QEvent *e) override; + +private: + std::unique_ptr ui; +}; + /** * The SketcherSettings class implements a preference page to change sketcher display settings. * @author Werner Mayer diff --git a/src/Mod/Sketcher/Gui/SketcherSettingsDisplay.ui b/src/Mod/Sketcher/Gui/SketcherSettingsDisplay.ui index 5f6527407d..4b4efdd5a2 100644 --- a/src/Mod/Sketcher/Gui/SketcherSettingsDisplay.ui +++ b/src/Mod/Sketcher/Gui/SketcherSettingsDisplay.ui @@ -67,7 +67,7 @@ - + The number of polygons used for geometry approximation. @@ -86,7 +86,7 @@ - + If checked, displays the name on dimensional constraints (if exists). @@ -102,7 +102,7 @@ - + The format of the dimensional constraint string presentation. @@ -125,7 +125,7 @@ Defaults to: %N = %V - + Segments per geometry @@ -135,7 +135,7 @@ Defaults to: %N = %V - + The current sketcher creation tool will remain active after creation. @@ -179,7 +179,7 @@ Defaults to: %N = %V - + Base length units will not be displayed in constraints or cursor coordinates. @@ -212,27 +212,7 @@ Supports all unit systems except 'US customary' and 'Building US/Euro'. - - - - Grid line pattern - - - comboBox - - - - - - - Line pattern used for grid lines. - - - -1 - - - - + The current constraint creation tool will remain active after creation. @@ -251,7 +231,7 @@ Supports all unit systems except 'US customary' and 'Building US/Euro'. - + Cursor position coordinates will be displayed beside cursor while editing sketch. @@ -270,7 +250,7 @@ Supports all unit systems except 'US customary' and 'Building US/Euro'. - + A dialog will pop up to input a value for new dimensional constraints. @@ -289,7 +269,7 @@ Supports all unit systems except 'US customary' and 'Building US/Euro'. - + Cursor coordinates will use the system decimals setting instead of the short form. diff --git a/src/Mod/Sketcher/Gui/SketcherSettingsGrid.ui b/src/Mod/Sketcher/Gui/SketcherSettingsGrid.ui new file mode 100644 index 0000000000..21f23aee06 --- /dev/null +++ b/src/Mod/Sketcher/Gui/SketcherSettingsGrid.ui @@ -0,0 +1,471 @@ + + + SketcherGui::SketcherSettingsGrid + + + + 0 + 0 + 500 + 664 + + + + Grid + + + + + + Grid settings + + + + 0 + 0 + + + + + + + true + + + A grid will be shown + + + Grid + + + false + + + ShowGrid + + + Mod/Sketcher/General + + + + + + + true + + + New points will snap to the nearest grid line. +Points must be set closer than a fifth of the grid spacing to a grid line to snap. + + + Grid snap + + + GridSnap + + + Mod/Sketcher/General + + + + + + + true + + + Automatically adapt grid spacing based on the viewer dimensions. + + + Grid Auto Spacing + + + GridAuto + + + Mod/Sketcher/General + + + + + + + Grid spacing (if auto disabled) + + + gridSize + + + + + + + Distance between two subsequent grid lines + + + mm + + + 0.001000000000000 + + + 99999999.000000000000000 + + + 1.000000000000000 + + + 10.000000000000000 + + + GridSize + + + Mod/Sketcher/General/GridSize + + + 3 + + + + + + + Pixel size threshold + + + gridNumberSubdivision + + + + + + + While using 'Grid Auto Spacing' this sets a threshold in pixel to the grid spacing. The grid spacing change if it becomes smaller than this number of pixel. + + + 3 + + + 10000 + + + 15 + + + GridSizePixelThreshold + + + Mod/Sketcher/General + + + + + + + + + + Grid display + + + + 0 + 0 + + + + + + + Subdivision lines + + + + 0 + 0 + + + + + + + Line pattern + + + gridLinePattern + + + + + + + Line pattern used for grid lines. + + + -1 + + + + + + + Line width + + + gridLineWidth + + + + + + + Distance between two subsequent grid lines + + + mm + + + 1 + + + 99 + + + 1 + + + GridLineWidth + + + Mod/Sketcher/General + + + + + + + Line color + + + gridLineColor + + + + + + + + 0 + 0 + + + + + + + + 178 + 178 + 178 + + + + GridLineColor + + + Mod/Sketcher/General + + + + + + + + + + Division lines + + + + 0 + 0 + + + + + + + Number of subdivisions per division + + + gridNumberSubdivision + + + + + + + Number of subdivisions of each grid division. Set to 1 to disable divisions. + + + 1 + + + 10000 + + + 10 + + + GridNumberSubdivision + + + Mod/Sketcher/General + + + + + + + Line pattern + + + gridDivLinePattern + + + + + + + Line pattern used for grid division. + + + -1 + + + + + + + Line width + + + gridDivLineWidth + + + + + + + Distance between two subsequent division lines + + + 1 + + + 99 + + + 2 + + + GridDivLineWidth + + + Mod/Sketcher/General + + + + + + + Line color + + + gridDivLineColor + + + + + + + + 0 + 0 + + + + + + + + 178 + 178 + 178 + + + + GridDivLineColor + + + Mod/Sketcher/General + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Gui::PrefSpinBox + QSpinBox +
Gui/PrefWidgets.h
+
+ + Gui::PrefCheckBox + QCheckBox +
Gui/PrefWidgets.h
+
+ + Gui::PrefQuantitySpinBox + Gui::QuantitySpinBox +
Gui/PrefWidgets.h
+
+ + Gui::QuantitySpinBox + QAbstractSpinBox +
Gui/QuantitySpinBox.h
+
+ + Gui::PrefColorButton + Gui::ColorButton +
Gui/PrefWidgets.h
+
+ + Gui::ColorButton + QPushButton +
Gui/Widgets.h
+
+
+ + +
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 6f77c5599f..ebfc00cd7a 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -201,14 +201,16 @@ void ViewProviderSketch::ParameterObserver::initParameters() {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, false);}, &Client.ForceOrtho }}, {"SectionView", {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, false);}, &Client.SectionView }}, - {"ShowGrid", - {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, false);}, &Client.ShowGrid }}, - {"GridSnap", - {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, false);}, &Client.GridSnap }}, {"AutoConstraints", {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, true);}, &Client.Autoconstraints }}, {"AvoidRedundantAutoconstraints", {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, true);}, &Client.AvoidRedundant }}, + {"ShowGrid", + {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, false);}, &Client.ShowGrid }}, + {"GridSnap", + {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, false);}, &Client.GridSnap }}, + {"GridAuto", + {[this](const std::string & string, App::Property * property){ updateBoolProperty(string, property, true); }, &Client.GridAuto }}, {"GridSize", {[this](const std::string & string, App::Property * property){ updateGridSize(string, property);}, &Client.GridSize }}, {"SketchEdgeColor", @@ -260,8 +262,10 @@ SbVec2s ViewProviderSketch::DoubleClick::newCursorPos; // Construction/Destruction /* TRANSLATOR SketcherGui::ViewProviderSketch */ +const char* ViewProviderSketch::GridStyleEnums[] = { "Dashed","Light",nullptr }; +App::PropertyQuantityConstraint::Constraints ViewProviderSketch::GridSizeRange = { 0.001,DBL_MAX,1.0 }; -PROPERTY_SOURCE_WITH_EXTENSIONS(SketcherGui::ViewProviderSketch, PartGui::ViewProvider2DObjectGrid) +PROPERTY_SOURCE_WITH_EXTENSIONS(SketcherGui::ViewProviderSketch, PartGui::ViewProvider2DObject) ViewProviderSketch::ViewProviderSketch() @@ -285,6 +289,11 @@ ViewProviderSketch::ViewProviderSketch() ADD_PROPERTY_TYPE(ForceOrtho,(false),"Visibility automation",(App::PropertyType)(App::Prop_ReadOnly),"If true, camera type will be forced to orthographic view when entering editing mode."); ADD_PROPERTY_TYPE(SectionView,(false),"Visibility automation",(App::PropertyType)(App::Prop_ReadOnly),"If true, only objects (or part of) located behind the sketch plane are visible."); ADD_PROPERTY_TYPE(EditingWorkbench,("SketcherWorkbench"),"Visibility automation",(App::PropertyType)(App::Prop_ReadOnly),"Name of the workbench to activate when editing this sketch."); + ADD_PROPERTY_TYPE(ShowGrid, (false), "Grid", (App::PropertyType)(App::Prop_None), "Switch the grid on/off"); + ADD_PROPERTY_TYPE(GridSize, (10.0), "Grid", (App::PropertyType)(App::Prop_None), "Gap size of the grid"); + ADD_PROPERTY_TYPE(GridStyle, (0L), "Grid", (App::PropertyType)(App::Prop_None), "Appearance style of the grid"); + ADD_PROPERTY_TYPE(GridSnap, (false), "Grid", (App::PropertyType)(App::Prop_None), "Switch the grid snap on/off"); + ADD_PROPERTY_TYPE(GridAuto, (true), "Grid", (App::PropertyType)(App::Prop_None), "Change size of grid based on view area."); // Default values that will be overridden by preferences (if existing) PointSize.setValue(4); @@ -293,7 +302,8 @@ ViewProviderSketch::ViewProviderSketch() pObserver->initParameters(); pObserver->subscribeToParameters(); - this->GridAutoSize.setValue(false); //Grid size is managed by this class + GridStyle.setEnums(GridStyleEnums); + GridSize.setConstraints(&GridSizeRange); sPixmap = "Sketcher_Sketch"; @@ -1553,7 +1563,7 @@ bool ViewProviderSketch::isSelectable() const if (isEditing()) return false; else - return PartGui::ViewProvider2DObjectGrid::isSelectable(); + return PartGui::ViewProvider2DObject::isSelectable(); } void ViewProviderSketch::onSelectionChanged(const Gui::SelectionChanges& msg) @@ -2686,7 +2696,12 @@ void ViewProviderSketch::drawEditMarkers(const std::vector &Edit void ViewProviderSketch::updateData(const App::Property *prop) { - ViewProvider2DObjectGrid::updateData(prop); + ViewProvider2DObject::updateData(prop); + + if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId()) { + if (isInEditMode()) + editCoinManager->drawGrid(); + } // In the case of an undo/redo transaction, updateData is triggered by SketchObject::onUndoRedoFinished() in the solve() // In the case of an internal transaction, touching the geometry results in a call to updateData. @@ -2721,7 +2736,16 @@ void ViewProviderSketch::updateData(const App::Property *prop) void ViewProviderSketch::onChanged(const App::Property *prop) { // call father - PartGui::ViewProvider2DObjectGrid::onChanged(prop); + ViewProviderPart::onChanged(prop); + + if (prop == &ShowGrid && isInEditMode()) + editCoinManager->drawGrid(); + + if (prop == &GridSize && isInEditMode()) + editCoinManager->drawGrid(); + + if (prop == &GridStyle && isInEditMode()) + editCoinManager->drawGrid(); } void ViewProviderSketch::attach(App::DocumentObject *pcFeat) @@ -2853,10 +2877,6 @@ bool ViewProviderSketch::setEdit(int ModNum) Base::Console().Warning("ViewProviderSketch::setEdit: could not import Show module. Visibility automation will not work.\n"); } - TightGrid.setValue(false); - - ViewProvider2DObjectGrid::setEdit(ModNum); // notify to handle grid according to edit mode property - // start the edit dialog if (sketchDlg) Gui::Control().showDialog(sketchDlg); @@ -3044,8 +3064,6 @@ void ViewProviderSketch::unsetEdit(int ModNum) Gui::ToolBarManager::getInstance()->setToolbarVisibility(false, editModeToolbarNames()); Gui::ToolBarManager::getInstance()->setToolbarVisibility(true, nonEditModeToolbarNames()); - TightGrid.setValue(true); - if(listener) { Gui::getMainWindow()->removeEventFilter(listener); delete listener; @@ -3098,8 +3116,6 @@ void ViewProviderSketch::unsetEdit(int ModNum) Base::Console().Error("ViewProviderSketch::unsetEdit: visibility automation failed with an error: \n"); e.ReportException(); } - - ViewProvider2DObjectGrid::unsetEdit(ModNum); // notify grid that edit mode is being left } void ViewProviderSketch::setEditViewer(Gui::View3DInventorViewer* viewer, int ModNum) @@ -3207,24 +3223,31 @@ void ViewProviderSketch::camSensCB(void *data, SoSensor *) auto vp = proxyVPrdr->vp; auto cam = proxyVPrdr->renderMgr->getCamera(); - auto rotSk = Base::Rotation(vp->getDocument()->getEditingTransform()); //sketch orientation + vp->onCameraChanged(cam); +} + +void ViewProviderSketch::onCameraChanged(SoCamera* cam) +{ + auto rotSk = Base::Rotation(getDocument()->getEditingTransform()); //sketch orientation auto rotc = cam->orientation.getValue().getValue(); auto rotCam = Base::Rotation(rotc[0], rotc[1], rotc[2], rotc[3]); // camera orientation (needed because float to double conversion) // Is camera in the same hemisphere as positive sketch normal ? - auto orientation = (rotCam.invert()*rotSk).multVec(Base::Vector3d(0,0,1)); - auto tmpFactor = orientation.z<0?-1:1; + auto orientation = (rotCam.invert() * rotSk).multVec(Base::Vector3d(0, 0, 1)); + auto tmpFactor = orientation.z < 0 ? -1 : 1; - if (tmpFactor != vp->viewOrientationFactor) { // redraw only if viewing side changed + if (tmpFactor != viewOrientationFactor) { // redraw only if viewing side changed Base::Console().Log("Switching side, now %s, redrawing\n", tmpFactor < 0 ? "back" : "front"); - vp->viewOrientationFactor = tmpFactor; - vp->draw(); + viewOrientationFactor = tmpFactor; + draw(); QString cmdStr = QStringLiteral( "ActiveSketch.ViewObject.TempoVis.sketchClipPlane(ActiveSketch, ActiveSketch.ViewObject.SectionView, %1)\n") - .arg(tmpFactor<0?QLatin1String("True"):QLatin1String("False")); + .arg(tmpFactor < 0 ? QLatin1String("True") : QLatin1String("False")); Base::Interpreter().runStringObject(cmdStr.toLatin1()); } + + editCoinManager->drawGrid(true); } int ViewProviderSketch::getPreselectPoint() const @@ -3466,6 +3489,28 @@ QIcon ViewProviderSketch::mergeColorfulOverlayIcons (const QIcon & orig) const return Gui::ViewProvider::mergeColorfulOverlayIcons (mergedicon); } +void ViewProviderSketch::handleChangedPropertyType(Base::XMLReader& reader, + const char* TypeName, + App::Property* prop) +{ + Base::Type inputType = Base::Type::fromName(TypeName); + if (prop->getTypeId().isDerivedFrom(App::PropertyFloat::getClassTypeId()) && + inputType.isDerivedFrom(App::PropertyFloat::getClassTypeId())) { + // Do not directly call the property's Restore method in case the implementation + // has changed. So, create a temporary PropertyFloat object and assign the value. + App::PropertyFloat floatProp; + floatProp.Restore(reader); + static_cast(prop)->setValue(floatProp.getValue()); + } + else { + ViewProviderPart::handleChangedPropertyType(reader, TypeName, prop); + } +} + +void ViewProviderSketch::Restore(Base::XMLReader& reader) +{ + ViewProviderPart::Restore(reader); +} /*************************** functions ViewProviderSketch offers to friends such as DrawHandlerSketch ************************/ diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index daf4ae1daa..8debb6828b 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -135,7 +135,7 @@ using GeoListFacade = Sketcher::GeoListFacade; * concentrating the coupling in a single point (and code reuse). * */ -class SketcherGuiExport ViewProviderSketch : public PartGui::ViewProvider2DObjectGrid +class SketcherGuiExport ViewProviderSketch : public PartGui::ViewProvider2DObject , public PartGui::ViewProviderAttachExtension , public Gui::SelectionObserver { @@ -412,6 +412,11 @@ public: App::PropertyBool ForceOrtho; App::PropertyBool SectionView; App::PropertyString EditingWorkbench; + App::PropertyBool ShowGrid; + App::PropertyLength GridSize; + App::PropertyEnumeration GridStyle; + App::PropertyBool GridSnap; + App::PropertyBool GridAuto; //@} // TODO: It is difficult to imagine that these functions are necessary in the public interface. This requires review at a second stage and possibly @@ -532,6 +537,7 @@ public: bool mouseButtonPressed(int Button, bool pressed, const SbVec2s& cursorPos, const Gui::View3DInventorViewer* viewer) override; bool mouseWheelEvent(int delta, const SbVec2s &cursorPos, const Gui::View3DInventorViewer* viewer) override; //@} + /// Control the overlays appearing on the Tree and reflecting different sketcher states QIcon mergeColorfulOverlayIcons (const QIcon & orig) const override; @@ -560,6 +566,7 @@ protected: void setEditViewer(Gui::View3DInventorViewer*, int ModNum) override; void unsetEditViewer(Gui::View3DInventorViewer*) override; static void camSensCB(void *data, SoSensor *); // camera sensor callback + void onCameraChanged(SoCamera* cam); //@} /** @name miscelanea editing functions */ @@ -775,6 +782,12 @@ private: SoNodeSensor cameraSensor; int viewOrientationFactor; // stores if sketch viewed from front or back + + void Restore(Base::XMLReader& reader) override; + void handleChangedPropertyType(Base::XMLReader& reader, const char* TypeName, App::Property* prop) override; + + static const char* GridStyleEnums[]; + static App::PropertyQuantityConstraint::Constraints GridSizeRange; }; } // namespace PartGui diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketchCoinAttorney.h b/src/Mod/Sketcher/Gui/ViewProviderSketchCoinAttorney.h index 387ba8e6f6..888c09b2bb 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketchCoinAttorney.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketchCoinAttorney.h @@ -80,7 +80,6 @@ private: static inline const GeoList getGeoList(const ViewProviderSketch & vp); static inline const GeoListFacade getGeoListFacade(const ViewProviderSketch & vp); static inline Base::Placement getEditingPlacement(const ViewProviderSketch & vp); - static inline void updateGridExtent(ViewProviderSketch & vp, float minx, float maxx, float miny, float maxy); static inline bool isShownVirtualSpace(const ViewProviderSketch & vp); static inline std::unique_ptr getRayPickAction(const ViewProviderSketch & vp); @@ -114,6 +113,7 @@ private: friend class EditModeCoinManager; friend class EditModeConstraintCoinManager; friend class EditModeGeometryCoinManager; + friend class EditModeGridCoinManager; friend class EditModeInformationOverlayCoinConverter; friend class EditModeGeometryCoinConverter; }; @@ -143,11 +143,6 @@ inline Base::Placement ViewProviderSketchCoinAttorney::getEditingPlacement(const return vp.getEditingPlacement(); } -inline void ViewProviderSketchCoinAttorney::updateGridExtent(ViewProviderSketch & vp, float minx, float maxx, float miny, float maxy) -{ - vp.updateGridExtent(minx, maxx, miny, maxy); -} - inline bool ViewProviderSketchCoinAttorney::isShownVirtualSpace(const ViewProviderSketch & vp) { return vp.viewProviderParameters.isShownVirtualSpace; diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 9e153970f5..1725d467b4 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -187,7 +187,8 @@ inline void SketcherAddWorkbenchSketchEditModeActions(Gui::ToolBarItem& sketch) { sketch << "Sketcher_LeaveSketch" << "Sketcher_ViewSketch" - << "Sketcher_ViewSection"; + << "Sketcher_ViewSection" + << "Sketcher_CompGrid"; } template