From 86ba800ae833ecaa0f4e76a08b6b4821ca3d19cc Mon Sep 17 00:00:00 2001 From: nds Date: Tue, 20 Aug 2019 15:16:34 +0300 Subject: [PATCH] 0030737: Visualization - implementing new selection schemes in context (cherry picked from commit 8ac88685123f50caef2b53010da626b4682d9bd4) --- src/AIS/AIS_InteractiveContext.hxx | 26 ++++ src/AIS/AIS_InteractiveContext_1.cxx | 215 +++++++++++---------------- src/AIS/AIS_Selection.cxx | 70 +++++++++ src/AIS/AIS_Selection.hxx | 24 +++ src/AIS/AIS_SelectionScheme.hxx | 34 +++++ src/AIS/FILES | 1 + 6 files changed, 243 insertions(+), 127 deletions(-) create mode 100644 src/AIS/AIS_SelectionScheme.hxx diff --git a/src/AIS/AIS_InteractiveContext.hxx b/src/AIS/AIS_InteractiveContext.hxx index 42b89bbd27..a5e6298160 100644 --- a/src/AIS/AIS_InteractiveContext.hxx +++ b/src/AIS/AIS_InteractiveContext.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -470,6 +471,24 @@ public: //! @name Selection management return AddSelect (theObject->GlobalSelOwner()); } + //! Selects everything found in the bounding rectangle defined by the pixel minima and maxima, XPMin, YPMin, XPMax, and YPMax in the view. + //! The objects detected are passed to the main viewer, which is then updated. + Standard_EXPORT AIS_StatusOfPick Select (const Standard_Integer theXPMin, + const Standard_Integer theYPMin, + const Standard_Integer theXPMax, + const Standard_Integer theYPMax, + const Handle(V3d_View)& theView, + const AIS_SelectionScheme theSelScheme); + + //! polyline selection; clears the previous picked list + Standard_EXPORT AIS_StatusOfPick Select (const TColgp_Array1OfPnt2d& thePolyline, + const Handle(V3d_View)& theView, + const AIS_SelectionScheme theSelScheme); + + //! Stores and hilights the previous detected; Unhilights the previous picked. + //! @sa MoveTo(). + Standard_EXPORT AIS_StatusOfPick Select (const AIS_SelectionScheme theSelScheme); + //! Selects everything found in the bounding rectangle defined by the pixel minima and maxima, XPMin, YPMin, XPMax, and YPMax in the view. //! The objects detected are passed to the main viewer, which is then updated. Standard_EXPORT AIS_StatusOfPick Select (const Standard_Integer theXPMin, @@ -511,6 +530,13 @@ public: //! @name Selection management //! Returns bounding box of selected objects. Standard_EXPORT Bnd_Box BoundingBoxOfSelection() const; + //! Sets list of owner selected/deselected using selection scheme + //! It is possible that selection of other objects is changed relatively selection scheme . + //! \param theOwner owners to change selection state + //! \param theSelScheme selection scheme + Standard_EXPORT AIS_StatusOfPick Select (const AIS_NListOfEntityOwner& theOwners, + const AIS_SelectionScheme theSelScheme); + //! Fits the view correspondingly to the bounds of selected objects. //! Infinite objects are ignored if infinite state of AIS_InteractiveObject is set to true. Standard_EXPORT void FitSelected (const Handle(V3d_View)& theView, diff --git a/src/AIS/AIS_InteractiveContext_1.cxx b/src/AIS/AIS_InteractiveContext_1.cxx index 70ba165da4..699a871126 100644 --- a/src/AIS/AIS_InteractiveContext_1.cxx +++ b/src/AIS/AIS_InteractiveContext_1.cxx @@ -490,38 +490,37 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Integer theXPMi const Standard_Integer theXPMax, const Standard_Integer theYPMax, const Handle(V3d_View)& theView, - const Standard_Boolean toUpdateViewer) + const AIS_SelectionScheme theSelScheme) { if (theView->Viewer() != myMainVwr) { throw Standard_ProgramError ("AIS_InteractiveContext::Select() - invalid argument"); } - // all objects detected by the selector are taken, previous current objects are emptied, - // new objects are put... - ClearSelected (Standard_False); myLastActiveView = theView.get(); - myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView); - for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) + if (!myLastPicked.IsNull()) { - const Handle(SelectMgr_EntityOwner)& aCurOwner = myMainSel->Picked (aPickIter); - if (aCurOwner.IsNull() || !aCurOwner->HasSelectable() || !myFilters->IsOk (aCurOwner)) - continue; - - mySelection->Select (aCurOwner); + Graphic3d_Vec2i aMousePos (-1, -1); + if (myMainSel->GetManager().GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point) + { + aMousePos.SetValues ((Standard_Integer )myMainSel->GetManager().GetMousePosition().X(), + (Standard_Integer )myMainSel->GetManager().GetMousePosition().Y()); + } + if (myLastPicked->HandleMouseClick (aMousePos, Aspect_VKeyMouse_LeftButton, Aspect_VKeyFlags_NONE, false)) + { + return AIS_SOP_NothingSelected; + } } - if (myAutoHilight) + myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView); + + AIS_NListOfEntityOwner aPickedOwners; + for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) { - HilightSelected (toUpdateViewer); + aPickedOwners.Append (myMainSel->Picked (aPickIter)); } - Standard_Integer aSelNum = NbSelected(); - - return (aSelNum == 0) ? AIS_SOP_NothingSelected - : (aSelNum == 1) ? AIS_SOP_OneSelected - : AIS_SOP_SeveralSelected; - + return Select (aPickedOwners, theSelScheme); } //======================================================================= @@ -530,48 +529,38 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Integer theXPMi //======================================================================= AIS_StatusOfPick AIS_InteractiveContext::Select (const TColgp_Array1OfPnt2d& thePolyline, const Handle(V3d_View)& theView, - const Standard_Boolean toUpdateViewer) + const AIS_SelectionScheme theSelScheme) { if (theView->Viewer() != myMainVwr) { throw Standard_ProgramError ("AIS_InteractiveContext::Select() - invalid argument"); } - // all objects detected by the selector are taken, previous current objects are emptied, - // new objects are put... - ClearSelected (Standard_False); - myLastActiveView = theView.get(); myMainSel->Pick (thePolyline, theView); - for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) - { - const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter); - if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner)) - continue; - mySelection->Select (anOwner); - } - - if (myAutoHilight) + AIS_NListOfEntityOwner aPickedOwners; + for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) { - HilightSelected (toUpdateViewer); + aPickedOwners.Append (myMainSel->Picked (aPickIter)); } - Standard_Integer aSelNum = NbSelected(); - - return (aSelNum == 0) ? AIS_SOP_NothingSelected - : (aSelNum == 1) ? AIS_SOP_OneSelected - : AIS_SOP_SeveralSelected; - + return Select (aPickedOwners, theSelScheme); } //======================================================================= //function : Select //purpose : //======================================================================= -AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Boolean toUpdateViewer) +AIS_StatusOfPick AIS_InteractiveContext::Select (const AIS_SelectionScheme theSelScheme) { - if (!myLastPicked.IsNull()) + // special case: single selection of detected owner - is it necessary ? + /*if (myWasLastMain && !myLastinMain.IsNull() && !myAutoHilight && + (myLastinMain->IsSelected() + && !myLastinMain->IsForcedHilight() + && NbSelected() <= 1)) { + mySelection->selectOwner(myLastinMain, aPrevSelected, theSelScheme); + Graphic3d_Vec2i aMousePos (-1, -1); if (myMainSel->GetManager().GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Point) { @@ -582,54 +571,56 @@ AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Boolean toUpdate { return AIS_SOP_NothingSelected; } + return getStatusOfPick (NbSelected()); + }*/ - if (myAutoHilight) - { - clearDynamicHighlight(); - } - if (!myLastPicked->IsSelected() - || myLastPicked->IsForcedHilight() - || NbSelected() > 1) - { - SetSelected (myLastPicked, Standard_False); - if(toUpdateViewer) - { - UpdateCurrentViewer(); - } - } - } - else - { - ClearSelected (toUpdateViewer); - } - - Standard_Integer aSelNum = NbSelected(); + AIS_NListOfEntityOwner aPickedOwners; + aPickedOwners.Append (myLastPicked); - return (aSelNum == 0) ? AIS_SOP_NothingSelected - : (aSelNum == 1) ? AIS_SOP_OneSelected - : AIS_SOP_SeveralSelected; + return Select (aPickedOwners, theSelScheme); } //======================================================================= -//function : ShiftSelect +//function : Select //purpose : //======================================================================= -AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Boolean toUpdateViewer) +AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Integer theXPMin, + const Standard_Integer theYPMin, + const Standard_Integer theXPMax, + const Standard_Integer theYPMax, + const Handle(V3d_View)& theView, + const Standard_Boolean) { - if (myAutoHilight) - { - clearDynamicHighlight(); - } - if (!myLastPicked.IsNull()) - { - AddOrRemoveSelected (myLastPicked, toUpdateViewer); - } + return Select (theXPMin, theYPMin, theXPMax, theYPMax, theView, AIS_SelectionScheme_ClearAndAdd); +} - Standard_Integer aSelNum = NbSelected(); +//======================================================================= +//function : Select +//purpose : Selection by polyline +//======================================================================= +AIS_StatusOfPick AIS_InteractiveContext::Select (const TColgp_Array1OfPnt2d& thePolyline, + const Handle(V3d_View)& theView, + const Standard_Boolean) +{ + return Select (thePolyline, theView, AIS_SelectionScheme_ClearAndAdd); +} - return (aSelNum == 0) ? AIS_SOP_NothingSelected - : (aSelNum == 1) ? AIS_SOP_OneSelected - : AIS_SOP_SeveralSelected; +//======================================================================= +//function : Select +//purpose : +//======================================================================= +AIS_StatusOfPick AIS_InteractiveContext::Select (const Standard_Boolean) +{ + return Select (AIS_SelectionScheme_ClearAndAdd); +} + +//======================================================================= +//function : ShiftSelect +//purpose : +//======================================================================= +AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Boolean) +{ + return Select (AIS_SelectionScheme_Switch); } //======================================================================= @@ -641,39 +632,9 @@ AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Integer the const Standard_Integer theXPMax, const Standard_Integer theYPMax, const Handle(V3d_View)& theView, - const Standard_Boolean toUpdateViewer) + const Standard_Boolean) { - if (theView->Viewer() != myMainVwr) - { - throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument"); - } - - myLastActiveView = theView.get(); - if (myAutoHilight) - { - UnhilightSelected (Standard_False); - } - myMainSel->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView); - for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) - { - const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter); - if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner)) - continue; - - mySelection->Select (anOwner); - } - - if (myAutoHilight) - { - HilightSelected (toUpdateViewer); - } - - Standard_Integer aSelNum = NbSelected(); - - return (aSelNum == 0) ? AIS_SOP_NothingSelected - : (aSelNum == 1) ? AIS_SOP_OneSelected - : AIS_SOP_SeveralSelected; - + return Select (theXPMin, theYPMin, theXPMax, theYPMax, theView, AIS_SelectionScheme_Switch); } //======================================================================= @@ -682,31 +643,31 @@ AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const Standard_Integer the //======================================================================= AIS_StatusOfPick AIS_InteractiveContext::ShiftSelect (const TColgp_Array1OfPnt2d& thePolyline, const Handle(V3d_View)& theView, - const Standard_Boolean toUpdateViewer) + const Standard_Boolean) { - if (theView->Viewer() != myMainVwr) - { - throw Standard_ProgramError ("AIS_InteractiveContext::ShiftSelect() - invalid argument"); - } + return Select (thePolyline, theView, AIS_SelectionScheme_Switch); +} - myLastActiveView = theView.get(); +//======================================================================= +//function : Select +//purpose : +//======================================================================= +AIS_StatusOfPick AIS_InteractiveContext::Select (const AIS_NListOfEntityOwner& theOwners, + const AIS_SelectionScheme theSelScheme) +{ + // all objects detected by the selector are taken, previous current objects are emptied, + // new objects are put... if (myAutoHilight) { + clearDynamicHighlight(); UnhilightSelected (Standard_False); } - myMainSel->Pick (thePolyline, theView); - for (Standard_Integer aPickIter = 1; aPickIter <= myMainSel->NbPicked(); ++aPickIter) - { - const Handle(SelectMgr_EntityOwner) anOwner = myMainSel->Picked (aPickIter); - if (anOwner.IsNull() || !anOwner->HasSelectable() || !myFilters->IsOk (anOwner)) - continue; - mySelection->Select (anOwner); - } + mySelection->SelectOwners (theOwners, theSelScheme, myFilters); if (myAutoHilight) { - HilightSelected (toUpdateViewer); + HilightSelected (Standard_False); } Standard_Integer aSelNum = NbSelected(); diff --git a/src/AIS/AIS_Selection.cxx b/src/AIS/AIS_Selection.cxx index e26bddf828..8569e8a2b7 100644 --- a/src/AIS/AIS_Selection.cxx +++ b/src/AIS/AIS_Selection.cxx @@ -15,6 +15,8 @@ #include #include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(AIS_Selection, Standard_Transient) @@ -130,3 +132,71 @@ AIS_SelectStatus AIS_Selection::AddSelect (const Handle(SelectMgr_EntityOwner)& theObject->SetSelected (Standard_True); return AIS_SS_Added; } + +//======================================================================= +//function : SelectOwners +//purpose : +//======================================================================= +void AIS_Selection::SelectOwners (const AIS_NListOfEntityOwner& thePickedOwners, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter) +{ + int aSelScheme = theSelScheme; + AIS_NListOfEntityOwner aPrevSelected = Objects(); + if (theSelScheme & AIS_SelectionScheme_Clear) + { + Clear(); + + if (theSelScheme & AIS_SelectionScheme_Switch && + theSelScheme & AIS_SelectionScheme_PickedIfEmpty && + thePickedOwners.Size() < aPrevSelected.Size()) + { + // check if all picked objects are in previous selected list, if so, all objects will be deselected, + // but in mode AIS_SelectionScheme_PickedIfEmpty new picked objects should be selected, here, after Clear, Add + Standard_Boolean anOtherFound = Standard_False; + for (AIS_NListOfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next()) + { + anOtherFound = !aPrevSelected.Contains (aSelIter.Value()); + if (anOtherFound) + break; + } + if (!anOtherFound) + aSelScheme = AIS_SelectionScheme_Add; + } + } + + for (AIS_NListOfEntityOwner::Iterator aSelIter (thePickedOwners); aSelIter.More(); aSelIter.Next()) + { + selectOwner(aSelIter.Value(), aPrevSelected, aSelScheme, theFilter); + } +} + +//======================================================================= +//function : selectOwner +//purpose : +//======================================================================= +AIS_SelectStatus AIS_Selection::selectOwner (const Handle(SelectMgr_EntityOwner)& theOwner, + const AIS_NListOfEntityOwner& thePreviousSelected, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter) +{ + if (theOwner.IsNull() || !theOwner->HasSelectable() || !theFilter->IsOk (theOwner)) + return AIS_SS_NotDone; + + if (theSelScheme & AIS_SelectionScheme_Add) + { + return AddSelect (theOwner); + } + else if (theSelScheme & AIS_SelectionScheme_Switch) + { + if (thePreviousSelected.Contains (theOwner)) // was selected, should not be now + { + if (theOwner->IsSelected()) + return Select (theOwner); // deselect + } + else + return AddSelect (theOwner); // was not selected, should be now + } + + return AIS_SS_NotDone; +} diff --git a/src/AIS/AIS_Selection.hxx b/src/AIS/AIS_Selection.hxx index 8e7cf50e91..dc56d6dad6 100644 --- a/src/AIS/AIS_Selection.hxx +++ b/src/AIS/AIS_Selection.hxx @@ -22,6 +22,8 @@ #include #include +class SelectMgr_Filter; + //! Class holding the list of selected owners. class AIS_Selection : public Standard_Transient { @@ -75,6 +77,28 @@ public: //! Return selected object at iterator position. const Handle(SelectMgr_EntityOwner)& Value() const { return myIterator.Value(); } + //! Select or deselect owners depending on the selection scheme + //! \param theOwners elements to change selection state + //! \param theSelScheme selection scheme, defines how owner is selected + //! \param theFilter context filter to skip not acceptable owners + //! \return result of selection + Standard_EXPORT virtual void SelectOwners (const AIS_NListOfEntityOwner& thePickedOwners, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter); + +protected: + //! Select or deselect owner depending on the selection scheme + //! \param theOwner element to change selection state + //! \param thePreviousSelected previous selected objects + //! \param theSelScheme selection scheme, defines how owner is selected + //! \param theFilter context filter to skip not acceptable owners + //! \return result of selection + Standard_EXPORT virtual AIS_SelectStatus selectOwner (const Handle(SelectMgr_EntityOwner)& theOwner, + const AIS_NListOfEntityOwner& thePreviousSelected, + const int theSelScheme, + const Handle(SelectMgr_Filter)& theFilter); + + private: AIS_NListOfEntityOwner myresult; diff --git a/src/AIS/AIS_SelectionScheme.hxx b/src/AIS/AIS_SelectionScheme.hxx new file mode 100644 index 0000000000..0dc03a367c --- /dev/null +++ b/src/AIS/AIS_SelectionScheme.hxx @@ -0,0 +1,34 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#ifndef _AIS_SelectionScheme_HeaderFile +#define _AIS_SelectionScheme_HeaderFile + + +//! Sets selection schemes for interactive contexts. +//! It is possible to use combination of schemes. +enum AIS_SelectionScheme +{ + AIS_SelectionScheme_Empty = 0x0000, // do nothing + AIS_SelectionScheme_Clear = 0x0001, // clears current selection + AIS_SelectionScheme_Add = 0x0002, // add detected object to current selection + AIS_SelectionScheme_Switch = 0x0004, // switch selection state in values selected/deselected + AIS_SelectionScheme_PickedIfEmpty = 0x0008, // if after switch, result selection is empty, select picked objects + AIS_SelectionScheme_ClearAndSwitch = AIS_SelectionScheme_Clear | AIS_SelectionScheme_Switch, + AIS_SelectionScheme_ClearAndAdd = AIS_SelectionScheme_Clear | AIS_SelectionScheme_Add, + AIS_SelectionScheme_ClearAndSwitchAndPicked = AIS_SelectionScheme_ClearAndSwitch | AIS_SelectionScheme_PickedIfEmpty, + AIS_SelectionScheme_Custom // reserved item for custom selection scheme +}; + +#endif // _AIS_SelectionScheme_HeaderFile diff --git a/src/AIS/FILES b/src/AIS/FILES index e5bebe3142..1f9b18b48f 100644 --- a/src/AIS/FILES +++ b/src/AIS/FILES @@ -88,6 +88,7 @@ AIS_Selection.cxx AIS_Selection.hxx AIS_SelectStatus.hxx AIS_SelectionModesConcurrency.hxx +AIS_SelectionScheme.hxx AIS_SequenceOfInteractive.hxx AIS_Shape.cxx AIS_Shape.hxx -- 2.39.5