From 4193e85f866ae9f97250569e9c5801263cb95980 Mon Sep 17 00:00:00 2001 From: nds Date: Wed, 5 Nov 2014 08:57:05 +0300 Subject: [PATCH] Regression during edit operation. Edit sketch, select a line, as a result the property panel is filled and closed during this action. The OperationFeatureEditMulti remove. It is deleted, but in the FeatureEdit operation the flag isMultiOperation provide this operation algorithms. --- src/PartSet/CMakeLists.txt | 2 - src/PartSet/PartSet_Module.cpp | 3 - src/PartSet/PartSet_OperationFeatureEdit.cpp | 73 ++++- src/PartSet/PartSet_OperationFeatureEdit.h | 1 + .../PartSet_OperationFeatureEditMulti.cpp | 266 ------------------ .../PartSet_OperationFeatureEditMulti.h | 138 --------- src/PartSet/PartSet_OperationSketch.cpp | 7 +- 7 files changed, 66 insertions(+), 424 deletions(-) delete mode 100644 src/PartSet/PartSet_OperationFeatureEditMulti.cpp delete mode 100644 src/PartSet/PartSet_OperationFeatureEditMulti.h diff --git a/src/PartSet/CMakeLists.txt b/src/PartSet/CMakeLists.txt index de011a1b9..dae5c3b4f 100644 --- a/src/PartSet/CMakeLists.txt +++ b/src/PartSet/CMakeLists.txt @@ -10,7 +10,6 @@ SET(PROJECT_HEADERS PartSet_Module.h PartSet_OperationFeatureCreate.h PartSet_OperationFeatureEdit.h - PartSet_OperationFeatureEditMulti.h PartSet_OperationSketchBase.h PartSet_OperationSketch.h PartSet_OperationFeatureBase.h @@ -25,7 +24,6 @@ SET(PROJECT_SOURCES PartSet_Module.cpp PartSet_OperationFeatureCreate.cpp PartSet_OperationFeatureEdit.cpp - PartSet_OperationFeatureEditMulti.cpp PartSet_OperationSketchBase.cpp PartSet_OperationSketch.cpp PartSet_OperationFeatureBase.cpp diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 501105c4f..ad9210e3f 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -402,8 +401,6 @@ ModuleBase_Operation* PartSet_Module::createOperation(const std::string& theCmdI } if (PartSet_OperationFeatureCreate::canProcessKind(theCmdId)) { anOperation = new PartSet_OperationFeatureCreate(theCmdId.c_str(), this, aSketch); - } else if (theCmdId == PartSet_OperationFeatureEditMulti::Type()) { - anOperation = new PartSet_OperationFeatureEditMulti(theCmdId.c_str(), this, aSketch); } else if (theCmdId == PartSet_OperationFeatureEdit::Type()) { anOperation = new PartSet_OperationFeatureEdit(theCmdId.c_str(), this, aSketch); } diff --git a/src/PartSet/PartSet_OperationFeatureEdit.cpp b/src/PartSet/PartSet_OperationFeatureEdit.cpp index dcc8db879..c8a2712db 100644 --- a/src/PartSet/PartSet_OperationFeatureEdit.cpp +++ b/src/PartSet/PartSet_OperationFeatureEdit.cpp @@ -5,8 +5,6 @@ #include #include #include -#include - #include #include @@ -48,7 +46,7 @@ PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId, QObject* theParent, CompositeFeaturePtr theFeature) : PartSet_OperationFeatureBase(theId, theParent, theFeature), - myIsBlockedSelection(false) + myIsBlockedSelection(false), myIsMultiOperation(false) { myIsEditing = true; } @@ -70,11 +68,12 @@ void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelec if (!PartSet_Tools::isContainPresentation(aFeatures, aPrs)) aFeatures.append(aPrs); } + myIsMultiOperation = aFeatures.size() > 1; // 1. find all features with skipping features with selected vertex shapes myFeature2Attribute.clear(); // firstly, collect the features without local selection - /*foreach (ModuleBase_ViewerPrs aPrs, aFeatures) { + foreach (ModuleBase_ViewerPrs aPrs, aFeatures) { const TopoDS_Shape& aShape = aPrs.shape(); if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape); @@ -93,7 +92,7 @@ void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelec myFeature2Attribute[aFeature] = aList; } } - }*/ + } // 2. collect the features with a local selection on them. // if the list already has this feature, the local selection is skipped // that means that if the selection contains a feature and a feature with local selected point, @@ -134,6 +133,9 @@ void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelec void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection) { + if (myIsMultiOperation) + return; + ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget(); if(aActiveWgt && aActiveWgt->isViewerSelector()) { // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased @@ -186,9 +188,7 @@ void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBas // emit setSelection(aSelected); //} else if (aFeature) { - std::string anOperationType = - (aSelected.size() > 1) ? - PartSet_OperationFeatureEditMulti::Type() : PartSet_OperationFeatureEdit::Type(); + std::string anOperationType = PartSet_OperationFeatureEdit::Type(); restartOperation(anOperationType, aFeature); } //} @@ -216,6 +216,36 @@ void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_ double aDeltaX = aX - aCurX; double aDeltaY = anY - aCurY; + if (myIsMultiOperation) { + std::map>::iterator aFeatIter = myFeature2Attribute.begin(); + while (aFeatIter != myFeature2Attribute.end()) { + FeaturePtr aFeature = aFeatIter->first; + std::list anAttributes = aFeatIter->second; + // perform edit for the feature + if (anAttributes.empty()) { + boost::shared_ptr aSketchFeature = + boost::dynamic_pointer_cast(aFeature); + if (aSketchFeature) { + aSketchFeature->move(aDeltaX, aDeltaY); + } + } + // perform edit for the feature's attribute + else { + std::list::const_iterator anAttrIter = anAttributes.begin(), + anAttrEnd = anAttributes.end(); + for (; anAttrIter != anAttrEnd; anAttrIter++) { + boost::shared_ptr aPointAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter)); + if (aPointAttr) { + aPointAttr->move(aDeltaX, aDeltaY); + } + } + } + aFeatIter++; + } + } + else { // multieditoperation + boost::shared_ptr aSketchFeature = boost::dynamic_pointer_cast< SketchPlugin_Feature>(feature()); @@ -259,6 +289,7 @@ void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_ ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent); } } + } // multieditoperation } sendFeatures(); @@ -270,6 +301,19 @@ void PartSet_OperationFeatureEdit::mouseReleased( ModuleBase_ISelection* theSelection) { theViewer->enableSelection(true); + if (myIsMultiOperation) { + if (commit()) { + std::map>::iterator aFeatIter = myFeature2Attribute.begin(); + while (aFeatIter != myFeature2Attribute.end()) { + FeaturePtr aFeature = aFeatIter->first; + if (aFeature) { + emit featureConstructed(aFeature, FM_Deactivation); + } + aFeatIter++; + } + } + } + else { // multieditoperation ModuleBase_ModelWidget* aActiveWgt = 0; if (myPropertyPanel) aActiveWgt = myPropertyPanel->activeWidget(); @@ -279,6 +323,7 @@ void PartSet_OperationFeatureEdit::mouseReleased( }// else { //blockSelection(false); //} + } // multieditoperation } void PartSet_OperationFeatureEdit::mouseDoubleClick( @@ -318,6 +363,8 @@ void PartSet_OperationFeatureEdit::stopOperation() //emit multiSelectionEnabled(true); //blockSelection(false, false); + + myFeature2Attribute.clear(); } //void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection) @@ -350,8 +397,14 @@ void PartSet_OperationFeatureEdit::sendFeatures() { static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - FeaturePtr aFeature = feature(); - ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); + std::map>::iterator aFeatIter = myFeature2Attribute.begin(); + while (aFeatIter != myFeature2Attribute.end()) { + FeaturePtr aFeature = aFeatIter->first; + if (aFeature) { + ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); + } + aFeatIter++; + } Events_Loop::loop()->flush(anEvent); flushUpdated(); diff --git a/src/PartSet/PartSet_OperationFeatureEdit.h b/src/PartSet/PartSet_OperationFeatureEdit.h index 5e612c2ef..682cf91ff 100644 --- a/src/PartSet/PartSet_OperationFeatureEdit.h +++ b/src/PartSet/PartSet_OperationFeatureEdit.h @@ -140,6 +140,7 @@ Q_OBJECT Point myCurPoint; ///< the current 3D point clicked or moved bool myIsBlockedSelection; ///< the state of the last state of selection blocked signal + bool myIsMultiOperation; // the state whether the operation is used for some features }; #endif diff --git a/src/PartSet/PartSet_OperationFeatureEditMulti.cpp b/src/PartSet/PartSet_OperationFeatureEditMulti.cpp deleted file mode 100644 index ddf9b8d47..000000000 --- a/src/PartSet/PartSet_OperationFeatureEditMulti.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// File: PartSet_OperationFeatureEditMulti.h -// Created: 05 May 2014 -// Author: Natalia ERMOLAEVA - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -#include - -#include - -#include -#include -#include -#include - -#include -#ifdef _DEBUG -#include -#endif - -//using namespace std; - -PartSet_OperationFeatureEditMulti::PartSet_OperationFeatureEditMulti(const QString& theId, - QObject* theParent, - CompositeFeaturePtr theFeature) - : PartSet_OperationSketchBase(theId, theParent), - mySketch(theFeature), - myIsBlockedSelection(false) -{ - myIsEditing = true; -} - -PartSet_OperationFeatureEditMulti::~PartSet_OperationFeatureEditMulti() -{ -} - -void PartSet_OperationFeatureEditMulti::initSelection(ModuleBase_ISelection* theSelection, - ModuleBase_IViewer* theViewer) -{ - // 1. unite selected and hightlighted objects in order to have an opportunity to drag - // by the highlighted object - QList aFeatures; - aFeatures = theSelection->getSelected(); - QList aHighlighted = theSelection->getHighlighted(); - // add highlighted elements if they are not selected - foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) { - if (!PartSet_Tools::isContainPresentation(aFeatures, aPrs)) - aFeatures.append(aPrs); - } - - // 1. find all features with skipping features with selected vertex shapes - myFeature2Attribute.clear(); - // firstly, collect the features without local selection - foreach (ModuleBase_ViewerPrs aPrs, aFeatures) { - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected - const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape); - if (!aVertex.IsNull()) { - continue; - } - } - else { - ObjectPtr aObject = aPrs.object(); - if (!aObject) - continue; - FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - if (aFeature && myFeature2Attribute.find(aFeature) == myFeature2Attribute.end()) { - std::list aList; - // using an empty list as a sign, that this feature should be moved itself - myFeature2Attribute[aFeature] = aList; - } - } - } - // 2. collect the features with a local selection on them. - // if the list already has this feature, the local selection is skipped - // that means that if the selection contains a feature and a feature with local selected point, - // the edit is performed for a full feature - Handle(V3d_View) aView = theViewer->activeView(); - foreach (ModuleBase_ViewerPrs aPrs, aFeatures) { - const TopoDS_Shape& aShape = aPrs.shape(); - if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX) { // a point is selected - const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape); - if (aVertex.IsNull()) - continue; - ObjectPtr aObject = aPrs.object(); - if (!aObject) - continue; - FeaturePtr aFeature = ModelAPI_Feature::feature(aObject); - if (!aFeature) - continue; - // if the feature is already moved, do nothing for this feature local selection - if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end()) - continue; - - // append the attribute of the vertex if it is found on the current feature - gp_Pnt aPoint = BRep_Tool::Pnt(aVertex); - double aVX, aVY; - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aVX, aVY); - boost::shared_ptr aPoint2D = PartSet_Tools::getFeaturePoint( - aFeature, aVX, aVY); - std::string anAttribute = aFeature->data()->id(aPoint2D); - std::list aList; - if (myFeature2Attribute.find(aFeature) != myFeature2Attribute.end()) - aList = myFeature2Attribute[aFeature]; - - aList.push_back(anAttribute); - myFeature2Attribute[aFeature] = aList; - } - } -} - -CompositeFeaturePtr PartSet_OperationFeatureEditMulti::sketch() const -{ - return mySketch; -} - -//void PartSet_OperationFeatureEditMulti::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection) -//{ -//} - -void PartSet_OperationFeatureEditMulti::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer) -{ - if (!(theEvent->buttons() & Qt::LeftButton)) - return; - - if (theViewer->isSelectionEnabled()) - theViewer->enableSelection(false); - - Handle(V3d_View) aView = theViewer->activeView(); - gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView); - - //blockSelection(true); - if (myCurPoint.myIsInitialized) { - double aCurX, aCurY; - PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), aView, aCurX, aCurY); - - double aX, anY; - PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY); - - double aDeltaX = aX - aCurX; - double aDeltaY = anY - aCurY; - - std::map>::iterator aFeatIter = myFeature2Attribute.begin(); - while (aFeatIter != myFeature2Attribute.end()) { - FeaturePtr aFeature = aFeatIter->first; - std::list anAttributes = aFeatIter->second; - // perform edit for the feature - if (anAttributes.empty()) { - boost::shared_ptr aSketchFeature = - boost::dynamic_pointer_cast(aFeature); - if (aSketchFeature) { - aSketchFeature->move(aDeltaX, aDeltaY); - } - } - // perform edit for the feature's attribute - else { - std::list::const_iterator anAttrIter = anAttributes.begin(), - anAttrEnd = anAttributes.end(); - for (; anAttrIter != anAttrEnd; anAttrIter++) { - boost::shared_ptr aPointAttr = boost::dynamic_pointer_cast< - GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter)); - if (aPointAttr) { - aPointAttr->move(aDeltaX, aDeltaY); - } - } - } - aFeatIter++; - } - } - sendFeatures(); - - myCurPoint.setPoint(aPoint); -} - -void PartSet_OperationFeatureEditMulti::mouseReleased( - QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection) -{ - theViewer->enableSelection(true); - if (commit()) { - std::map>::iterator aFeatIter = myFeature2Attribute.begin(); - while (aFeatIter != myFeature2Attribute.end()) { - FeaturePtr aFeature = aFeatIter->first; - if (aFeature) { - emit featureConstructed(aFeature, FM_Deactivation); - } - aFeatIter++; - } - } -} - -void PartSet_OperationFeatureEditMulti::startOperation() -{ - PartSet_OperationSketchBase::startOperation(); - //emit multiSelectionEnabled(false); - - //blockSelection(true); - - myCurPoint.clear(); -} - -void PartSet_OperationFeatureEditMulti::stopOperation() -{ - //emit multiSelectionEnabled(true); - - //blockSelection(false, true); - - myFeature2Attribute.clear(); -} - -//void PartSet_OperationFeatureEditMulti::blockSelection(bool isBlocked, -// const bool isRestoreSelection) -//{ -// if (myIsBlockedSelection == isBlocked) -// return; -// -// myIsBlockedSelection = isBlocked; -// QList aFeatureList; -//// std::list::const_iterator anIt = myFeatures.begin(), aLast = -//// myFeatures.end(); -// /*for(; anIt != aLast; anIt++) -// aFeatureList.append((*anIt).feature());*/ -// //if (isBlocked) { -// // emit setSelection(QList()); -// // emit stopSelection(aFeatureList, true); -// //} else { -// // emit stopSelection(aFeatureList, false); -// // if (isRestoreSelection) { -// // emit setSelection(aFeatureList); -// // } -// //} -//} - -void PartSet_OperationFeatureEditMulti::sendFeatures() -{ - static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED); - - std::map>::iterator aFeatIter = myFeature2Attribute.begin(); - while (aFeatIter != myFeature2Attribute.end()) { - FeaturePtr aFeature = aFeatIter->first; - if (aFeature) { - ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); - } - aFeatIter++; - } - - Events_Loop::loop()->flush(anEvent); - flushUpdated(); -} - diff --git a/src/PartSet/PartSet_OperationFeatureEditMulti.h b/src/PartSet/PartSet_OperationFeatureEditMulti.h deleted file mode 100644 index 5b50a7bd6..000000000 --- a/src/PartSet/PartSet_OperationFeatureEditMulti.h +++ /dev/null @@ -1,138 +0,0 @@ -// File: PartSet_OperationFeatureEditMulti.h -// Created: 05 May 2014 -// Author: Natalia ERMOLAEVA - -#ifndef PartSet_OperationFeatureEditMulti_H -#define PartSet_OperationFeatureEditMulti_H - -#include "PartSet.h" - -#include -#include -#include - -#include -#include - -class QMouseEvent; - -/*! - \class PartSet_OperationFeatureEditMulti - * \brief The operation for the sketch feature creation - */ -class PARTSET_EXPORT PartSet_OperationFeatureEditMulti : public PartSet_OperationSketchBase -{ -Q_OBJECT - /// Struct to define gp point, with the state is the point is initialized - struct Point - { - /// Constructor - Point() - { - } - /// Constructor - /// \param thePoint the point - Point(gp_Pnt thePoint) - { - setPoint(thePoint); - } - ~Point() - { - } - - /// clear the initialized flag. - void clear() - { - myIsInitialized = false; - } - /// set the point and switch on the initialized flag - /// \param thePoint the point - void setPoint(const gp_Pnt& thePoint) - { - myIsInitialized = true; - myPoint = thePoint; - } - - bool myIsInitialized; /// the state whether the point is set - gp_Pnt myPoint; /// the point - }; - - public: - /// Returns the operation type key - static std::string Type() - { - return "EditMulti"; - } - - public: - /// Constructor - /// \param theId the feature identifier - /// \param theParent the operation parent - /// \param theFeature the parent feature - PartSet_OperationFeatureEditMulti(const QString& theId, QObject* theParent, - CompositeFeaturePtr theFeature); - /// Destructor - virtual ~PartSet_OperationFeatureEditMulti(); - - /// Initialisation of operation with preliminary selection - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - /// \param theViewer a viewer to have the viewer the eye position - virtual void initSelection(ModuleBase_ISelection* theSelection, - ModuleBase_IViewer* theViewer); - - /// Returns the operation sketch feature - /// \returns the sketch instance - virtual CompositeFeaturePtr sketch() const; - - /// Processes the mouse pressed in the point - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - //virtual void mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection); - - /// Gives the current mouse point in the viewer - /// \param theEvent the mouse event - /// \param theView a viewer to have the viewer the eye position - virtual void mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer); - - /// Gives the current selected objects to be processed by the operation - /// \param thePoint a point clicked in the viewer - /// \param theEvent the mouse event - /// \param theSelected the list of selected presentations - /// \param theHighlighted the list of highlighted presentations - virtual void mouseReleased(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, - ModuleBase_ISelection* theSelection); - - protected: - /// \brief Virtual method called when operation is started - /// Virtual method called when operation started (see start() method for more description) - /// Switch off the multi selection state - virtual void startOperation(); - - /// Virtual method called when operation stopped - committed or aborted. - /// Restore the multi selection state - virtual void stopOperation(); - - protected: - /// Emits a signal about the selection blocking. Emits a signal to change the selection. - /// If the block is true, the signal clear selection, otherwise if restore selection flag allows, - /// the internal operation features are to be selected - /// \param isBlocked the state whether the operation is blocked or unblocked - /// \param isRestoreSelection the state whether the selected objects should be reselected - //void blockSelection(bool isBlocked, const bool isRestoreSelection = true); - - /// Sends the features - void sendFeatures(); - -private: - // the next map should be removed when selection is processed in the move function - std::map > myFeature2Attribute; /// a map of a feature to attributes - - CompositeFeaturePtr mySketch; ///< the sketch feature - Point myCurPoint; ///< the current 3D point clicked or moved - bool myIsBlockedSelection; ///< the state of the last state of selection blocked signal -}; - -#endif diff --git a/src/PartSet/PartSet_OperationSketch.cpp b/src/PartSet/PartSet_OperationSketch.cpp index 7f5dcd758..29889ab5d 100644 --- a/src/PartSet/PartSet_OperationSketch.cpp +++ b/src/PartSet/PartSet_OperationSketch.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -76,9 +75,7 @@ void PartSet_OperationSketch::mousePressed(QMouseEvent* theEvent, ModuleBase_IVi //if (aSelected.size() > 0) { ObjectPtr aFeature = aSelected.first().object(); if (aFeature) { - std::string anOperationType = - (aSelected.size() > 1) ? - PartSet_OperationFeatureEditMulti::Type() : PartSet_OperationFeatureEdit::Type(); + std::string anOperationType = PartSet_OperationFeatureEdit::Type(); restartOperation(anOperationType, aFeature); } } @@ -154,7 +151,7 @@ void PartSet_OperationSketch::mouseMoved(QMouseEvent* theEvent, ModuleBase_IView FeaturePtr aFeature = PartSet_Tools::nearestFeature(theEvent->pos(), aView, feature(), myFeatures); if (aFeature) - restartOperation(PartSet_OperationFeatureEditMulti::Type(), aFeature); + restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature); } } -- 2.39.2