1 // Created on: 1996-10-30
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified by rob Thu Apr 02 1998
18 // - use of optimisation in SelectMgr_ViewerSelector
19 // -> Best management in detected entities...
21 #include <AIS_InteractiveContext.hxx>
22 #include <AIS_InteractiveObject.hxx>
23 #include <AIS_LocalContext.hxx>
24 #include <AIS_LocalStatus.hxx>
25 #include <AIS_Selection.hxx>
26 #include <AIS_Shape.hxx>
27 #include <Aspect_Grid.hxx>
28 #include <Geom_Transformation.hxx>
29 #include <Graphic3d_ArrayOfTriangles.hxx>
30 #include <Graphic3d_Group.hxx>
31 #include <NCollection_Map.hxx>
32 #include <OSD_Environment.hxx>
33 #include <Prs3d_Drawer.hxx>
34 #include <Prs3d_Presentation.hxx>
35 #include <Prs3d_ShadingAspect.hxx>
36 #include <Select3D_SensitiveTriangulation.hxx>
37 #include <SelectBasics_SensitiveEntity.hxx>
38 #include <SelectMgr_EntityOwner.hxx>
39 #include <SelectMgr_Filter.hxx>
40 #include <SelectMgr_OrFilter.hxx>
41 #include <SelectMgr_SelectableObject.hxx>
42 #include <SelectMgr_Selection.hxx>
43 #include <SelectMgr_SelectionManager.hxx>
44 #include <SelectMgr_SequenceOfOwner.hxx>
45 #include <Standard_Transient.hxx>
46 #include <StdSelect_BRepOwner.hxx>
47 #include <StdSelect_ViewerSelector3d.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <TColStd_ListIteratorOfListOfInteger.hxx>
50 #include <TColStd_ListOfInteger.hxx>
51 #include <TColStd_MapIteratorOfMapOfTransient.hxx>
52 #include <TColStd_MapOfTransient.hxx>
53 #include <V3d_View.hxx>
57 TopoDS_Shape AIS_myDummyShape;
60 static Standard_Integer GetHiMod(const Handle(AIS_InteractiveObject)& IO)
62 return IO->HasHilightMode() ? IO->HilightMode():0;
65 //==================================================
68 //==================================================
69 AIS_StatusOfDetection AIS_LocalContext::MoveTo (const Standard_Integer theXpix,
70 const Standard_Integer theYpix,
71 const Handle(V3d_View)& theView,
72 const Standard_Boolean theToRedrawImmediate)
74 // check that ViewerSelector gives
75 if (theView->Viewer() != myCTX->CurrentViewer())
81 myAISDetectedSeq.Clear();
84 myDetectedSeq.Clear();
85 myFilters->SetDisabledObjects (theView->View()->HiddenObjects());
86 myMainVS->Pick (theXpix, theYpix, theView);
88 const Standard_Integer aDetectedNb = myMainVS->NbPicked();
89 for (Standard_Integer aDetIter = 1; aDetIter <= aDetectedNb; ++aDetIter)
91 Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (aDetIter);
93 || !myFilters->IsOk (anOwner))
98 myDetectedSeq.Append (aDetIter); // normally they are already arranged in correct order...
99 Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
102 myAISDetectedSeq.Append (anObj);
106 // result of courses..
107 if (aDetectedNb == 0 || myDetectedSeq.IsEmpty())
109 if (mylastindex != 0 && mylastindex <= myMapOfOwner->Extent())
111 myMainPM->ClearImmediateDraw();
112 Unhilight (myMapOfOwner->FindKey (mylastindex), theView);
113 if (theToRedrawImmediate)
115 theView->RedrawImmediate();
120 return aDetectedNb == 0
125 // all owners detected by the selector are passed to the
126 // filters and correct ones are preserved...
128 Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
129 manageDetected (anOwner, theView, theToRedrawImmediate);
130 if (myDetectedSeq.Length() == 1)
132 return aDetectedNb == 1
133 ? AIS_SOD_OnlyOneDetected
134 : AIS_SOD_OnlyOneGood;
138 return AIS_SOD_SeveralGood;
142 //=======================================================================
143 //function : AddSelect
145 //=======================================================================
146 AIS_StatusOfPick AIS_LocalContext::AddSelect (const Handle(SelectMgr_EntityOwner)& theObject)
148 mySelection->AddSelect (theObject);
150 Standard_Integer aSelNum = mySelection->Extent();
151 return (aSelNum == 1) ? AIS_SOP_OneSelected
152 : (aSelNum > 1) ? AIS_SOP_SeveralSelected
156 //=======================================================================
159 //=======================================================================
160 AIS_StatusOfPick AIS_LocalContext::Select (const Standard_Boolean toUpdateViewer)
164 UnhilightPicked (Standard_False);
167 Standard_Integer aDetIndex = DetectedIndex();
170 ClearSelected (toUpdateViewer);
171 return mySelection->IsEmpty() ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
174 const Handle(SelectMgr_EntityOwner)& anOwner = myMapOfOwner->FindKey (aDetIndex);
176 ClearSelected (Standard_False);
178 if (!anOwner->IsSelected()) // anOwner is not selected
180 anOwner->SetSelected (Standard_True);
181 mySelection->Select (anOwner);
186 const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
187 for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
189 Unhilight (anOwner, anActiveViewIter.Value());
192 // advanced selection highlighting mechanism
193 if (!anOwner->IsAutoHilight() && anOwner->HasSelectable())
195 Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
196 UpdateSelected (anIO, Standard_False);
201 myCTX->CurrentViewer()->Update();
205 return (mySelection->Extent() == 1) ? AIS_SOP_OneSelected : AIS_SOP_SeveralSelected;
208 //=======================================================================
211 //=======================================================================
212 AIS_StatusOfPick AIS_LocalContext::Select (const Standard_Integer theXPMin,
213 const Standard_Integer theYPMin,
214 const Standard_Integer theXPMax,
215 const Standard_Integer theYPMax,
216 const Handle(V3d_View)& theView,
217 const Standard_Boolean toUpdateViewer)
219 if (theView->Viewer() == myCTX->CurrentViewer())
221 myMainVS->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
224 UnhilightPicked (Standard_False);
227 Standard_Integer aSelNum = mySelection->Extent();
228 if (myMainVS->NbPicked() == 0)
230 ClearSelected (toUpdateViewer);
232 return aSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
235 ClearSelected (Standard_False);
237 for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
239 const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
240 if (myFilters->IsOk (anOwner))
242 // it can be helpful to classify this owner immediately...
243 if (!anOwner->IsSelected())
245 anOwner->SetSelected (Standard_True);
246 mySelection->Select (anOwner);
253 HilightPicked (toUpdateViewer);
257 Standard_Integer aSelNum = mySelection->Extent();
259 return (aSelNum == 1) ? AIS_SOP_OneSelected
260 : (aSelNum > 1) ? AIS_SOP_SeveralSelected
264 //==================================================
266 // Purpose : Selection by polyline
267 //==================================================
268 AIS_StatusOfPick AIS_LocalContext::Select (const TColgp_Array1OfPnt2d& thePolyline,
269 const Handle(V3d_View)& theView,
270 const Standard_Boolean toUpdateViewer)
272 if (theView->Viewer() == myCTX->CurrentViewer())
274 myMainVS->Pick (thePolyline, theView);
276 Standard_Integer aLastSelNum = mySelection->Extent();
277 if (myMainVS->NbPicked() == 0)
279 // Nothing is selected clear selection.
280 ClearSelected (toUpdateViewer);
283 // Return state to know if something was unselected
284 return aLastSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
289 UnhilightPicked (Standard_False);
292 // Clear previous selection without update to process this selection
293 ClearSelected (Standard_False);
295 for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
297 const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
298 if (myFilters->IsOk (anOwner))
300 // it can be helpful to classify this owner immediately...
301 if (!anOwner->IsSelected())
303 mySelection->AddSelect (anOwner);
304 anOwner->SetSelected (Standard_True);
311 HilightPicked (toUpdateViewer);
315 Standard_Integer aSelNum = mySelection->Extent();
316 return (aSelNum == 1) ? AIS_SOP_OneSelected
317 : (aSelNum > 1) ? AIS_SOP_SeveralSelected
321 //=======================================================================
322 //function : ShiftSelect
324 //=======================================================================
325 AIS_StatusOfPick AIS_LocalContext::ShiftSelect (const Standard_Boolean toUpdateViewer)
327 Standard_Integer aDetIndex = DetectedIndex();
331 Standard_Integer aSelNum = mySelection->Extent();
332 const Handle(SelectMgr_EntityOwner)& anOwner = myMapOfOwner->FindKey (aDetIndex);
333 Standard_Boolean toSelect = anOwner->IsSelected() ? Standard_False : Standard_True;
334 mySelection->Select (anOwner);
335 anOwner->SetSelected (toSelect);
339 myMainPM->ClearImmediateDraw();
340 const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
341 for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
343 Unhilight (anOwner, anActiveViewIter.Value());
346 // advanced selection highlighting mechanism
347 if (!anOwner->IsAutoHilight() && anOwner->HasSelectable())
349 Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
350 UpdateSelected (anIO, Standard_False);
355 myCTX->CurrentViewer()->Update();
359 Standard_Integer NS = mySelection->Extent();
360 if( NS == 1 ) return AIS_SOP_OneSelected;
361 else if( NS > 1 ) return AIS_SOP_SeveralSelected;
362 return aSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
364 return AIS_SOP_Error;
367 //=======================================================================
368 //function : ShiftSelect
370 //=======================================================================
371 AIS_StatusOfPick AIS_LocalContext::ShiftSelect (const Standard_Integer theXPMin,
372 const Standard_Integer theYPMin,
373 const Standard_Integer theXPMax,
374 const Standard_Integer theYPMax,
375 const Handle(V3d_View)& theView,
376 const Standard_Boolean toUpdateViewer)
378 myMainPM->ClearImmediateDraw();
380 if (theView->Viewer() == myCTX->CurrentViewer())
382 myMainVS->Pick (theXPMin, theYPMin, theXPMax, theYPMax, theView);
384 Standard_Integer aLastSelNum = mySelection->Extent();
385 if (myMainVS->NbPicked() == 0)
387 // Nothing is selected clear selection, but don't clear the selection
388 // as it is shift selection and previous selection matters.
389 // Return state to know if something was unselected
390 return aLastSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
395 UnhilightPicked (Standard_False);
398 for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
400 const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
401 if(myFilters->IsOk (anOwner))
403 Standard_Boolean toSelect = anOwner->IsSelected() ? Standard_False : Standard_True;
404 mySelection->Select (anOwner);
405 anOwner->SetSelected (toSelect);
411 HilightPicked (toUpdateViewer);
415 Standard_Integer aSelNum = mySelection->Extent();
417 return (aSelNum == 1) ? AIS_SOP_OneSelected
418 : (aSelNum > 1) ? AIS_SOP_SeveralSelected
422 //==================================================
424 // Purpose : Selection by polyline
425 //==================================================
426 AIS_StatusOfPick AIS_LocalContext::ShiftSelect (const TColgp_Array1OfPnt2d& thePolyline,
427 const Handle(V3d_View)& theView,
428 const Standard_Boolean toUpdateViewer)
430 if (theView->Viewer() == myCTX->CurrentViewer())
432 myMainVS->Pick (thePolyline, theView);
434 Standard_Integer aLastSelNum = mySelection->Extent();
435 if (myMainVS->NbPicked() == 0)
437 // Nothing is selected clear selection, but don't clear the selection
438 // as it is shift selection and previous selection matters.
439 // Return state to know if something was unselected
440 return aLastSelNum == 0 ? AIS_SOP_NothingSelected : AIS_SOP_Removed;
445 UnhilightPicked (Standard_False);
448 for (Standard_Integer aPickIter = 1; aPickIter <= myMainVS->NbPicked(); ++aPickIter)
450 const Handle(SelectMgr_EntityOwner)& anOwner = myMainVS->Picked (aPickIter);
451 if (myFilters->IsOk (anOwner))
453 Standard_Boolean toSelect = anOwner->IsSelected() ? Standard_False : Standard_True;
454 mySelection->Select (anOwner);
455 anOwner->SetSelected (toSelect);
460 HilightPicked (toUpdateViewer);
464 Standard_Integer aSelNum = mySelection->Extent();
466 return (aSelNum == 1) ? AIS_SOP_OneSelected
467 : (aSelNum > 1) ? AIS_SOP_SeveralSelected
471 //==================================================
474 //==================================================
475 void AIS_LocalContext::Hilight (const Handle(SelectMgr_EntityOwner)& theOwner,
476 const Handle(V3d_View)& theView)
478 if (theView.IsNull())
483 const Standard_Integer aHilightMode = GetHiMod (Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable()));
484 myMainPM->BeginImmediateDraw();
485 theOwner->HilightWithColor (myMainPM, myCTX->HilightColor(), aHilightMode);
486 myMainPM->EndImmediateDraw (theView->Viewer());
489 //==================================================
490 // Function: Unhilight
492 //==================================================
493 void AIS_LocalContext::Unhilight (const Handle(SelectMgr_EntityOwner)& theOwner,
494 const Handle(V3d_View)& theView)
496 if (theView.IsNull())
501 const Standard_Integer aHilightMode = GetHiMod (Handle(AIS_InteractiveObject)::DownCast (theOwner->Selectable()));
502 if (IsSelected (theOwner))
504 if (theOwner->IsAutoHilight())
506 theOwner->HilightWithColor (myMainPM, myCTX->SelectionColor(), aHilightMode);
511 theOwner->Unhilight (myMainPM, aHilightMode);
515 //=======================================================================
516 //function : HilightPicked
518 //=======================================================================
519 void AIS_LocalContext::HilightPicked (const Standard_Boolean theToUpdateviewer)
521 if (mySelection.IsNull())
526 typedef NCollection_Shared<SelectMgr_SequenceOfOwner> SelectMgr_HSequenceOfOwner;
527 typedef NCollection_DataMap <Handle(SelectMgr_SelectableObject), Handle(SelectMgr_HSequenceOfOwner) > SelectMgr_DataMapOfObjectOwners;
528 SelectMgr_DataMapOfObjectOwners aMap;
530 // to avoid problems when there is a loop searching for selected objects...
531 for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
533 const Handle(SelectMgr_EntityOwner)& anOwner = aSelIter.Value();
534 Handle(SelectMgr_SelectableObject) aSelObj = anOwner->Selectable();
535 if (anOwner->IsAutoHilight())
537 Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(aSelObj);
538 const Standard_Integer aHighMode = GetHiMod (anIO);
539 anOwner->HilightWithColor (myMainPM, myCTX->SelectionColor(), aHighMode);
543 Handle(SelectMgr_HSequenceOfOwner) aSeq;
544 if (aMap.Find (aSelObj, aSeq))
546 aSeq->Append (anOwner);
550 aSeq = new SelectMgr_HSequenceOfOwner();
551 aSeq->Append (anOwner);
552 aMap.Bind (aSelObj, aSeq);
556 for (SelectMgr_DataMapOfObjectOwners::Iterator aMapIter (aMap); aMapIter.More(); aMapIter.Next())
558 aMapIter.Key()->HilightSelected (myMainPM, *aMapIter.Value());
561 if (theToUpdateviewer)
563 myCTX->CurrentViewer()->Update();
567 //==================================================
568 // Function: UnhilightPicked
570 //==================================================
571 void AIS_LocalContext::UnhilightPicked (const Standard_Boolean theToUpdateViewer)
573 myMainPM->ClearImmediateDraw();
574 if (mySelection.IsNull())
579 NCollection_Map<Handle(SelectMgr_SelectableObject)> anObjMap;
580 for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
582 const Handle(SelectMgr_EntityOwner)& anOwner = aSelIter.Value();
583 Handle(SelectMgr_SelectableObject) aSelObj = anOwner->Selectable();
584 Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (aSelObj);
585 anObjMap.Add (aSelObj);
586 Standard_Integer aHighMode = GetHiMod (anIO);
587 anOwner->Unhilight (myMainPM, aHighMode);
590 for (NCollection_Map<Handle(SelectMgr_SelectableObject)>::Iterator aMapIter (anObjMap);
591 aMapIter.More(); aMapIter.Next())
593 if (!aMapIter.Key()->IsAutoHilight())
595 aMapIter.Key()->ClearSelected();
599 if (theToUpdateViewer)
601 myCTX->CurrentViewer()->Update();
605 //=======================================================================
606 //function : IsSelected
608 //=======================================================================
609 Standard_Boolean AIS_LocalContext::IsSelected(const Handle(AIS_InteractiveObject)& anIObj) const
611 return (!FindSelectedOwnerFromIO(anIObj).IsNull());
614 //=======================================================================
615 //function : IsSelected
617 //=======================================================================
619 Standard_Boolean AIS_LocalContext::IsSelected (const Handle(SelectMgr_EntityOwner)& theOwner) const
621 return !theOwner.IsNull() && theOwner->IsSelected();
624 //==================================================
627 //==================================================
628 void AIS_LocalContext::
634 //==================================================
637 //==================================================
638 Standard_Boolean AIS_LocalContext::
641 return mySelection->More();
644 //==================================================
647 //==================================================
648 void AIS_LocalContext::
654 //==================================================
655 // Function: HasShape
657 //==================================================
658 Standard_Boolean AIS_LocalContext::HasShape() const
660 if (!mySelection->More())
662 return Standard_False;
665 Handle(StdSelect_BRepOwner) aBROwner = Handle(StdSelect_BRepOwner)::DownCast(mySelection->Value());
666 return !aBROwner.IsNull()
667 && aBROwner->HasShape()
668 && aBROwner->ComesFromDecomposition();
671 //================================================================
672 // Function : HasSelectedShape
673 // Purpose : Checks if there is a selected shape regardless of its decomposition status
674 //================================================================
675 Standard_Boolean AIS_LocalContext::HasSelectedShape() const
677 if (!mySelection->More())
679 return Standard_False;
682 Handle(StdSelect_BRepOwner) aBrepOwner = Handle(StdSelect_BRepOwner)::DownCast (mySelection->Value());
683 return !aBrepOwner.IsNull()
684 && aBrepOwner->HasShape();
687 //==================================================
688 // Function: SelectedShape
690 //==================================================
691 TopoDS_Shape AIS_LocalContext::SelectedShape() const
693 if (!mySelection->More())
695 return TopoDS_Shape();
698 Handle(StdSelect_BRepOwner) aBRO = Handle(StdSelect_BRepOwner)::DownCast(mySelection->Value());
701 return TopoDS_Shape();
704 return aBRO->Shape().Located (aBRO->Location() * aBRO->Shape().Location());
707 //==================================================
708 // Function: SelectedInteractive
710 //==================================================
711 Handle(AIS_InteractiveObject) AIS_LocalContext::SelectedInteractive() const
713 return !mySelection->More()
714 ? Handle(AIS_InteractiveObject)()
715 : Handle(AIS_InteractiveObject)::DownCast (mySelection->Value()->Selectable());
718 //==================================================
719 // Function: SelectedOwner
721 //==================================================
722 Handle(SelectMgr_EntityOwner) AIS_LocalContext::SelectedOwner() const
724 return !mySelection->More()
725 ? Handle(SelectMgr_EntityOwner)()
726 : mySelection->Value();
729 //==================================================
732 //==================================================
733 Standard_Boolean AIS_LocalContext::HasApplicative() const
735 Handle(AIS_InteractiveObject) anIO = SelectedInteractive();
736 return !anIO.IsNull()
740 //==================================================
743 //==================================================
744 const Handle(Standard_Transient)& AIS_LocalContext::
745 SelectedApplicative() const
747 return SelectedInteractive()->GetOwner();
752 //=======================================================================
753 //function : UpdateSelection
754 //purpose : should disappear...
755 //=======================================================================
756 void AIS_LocalContext::UpdateSelected(const Standard_Boolean updateviewer)
758 UnhilightPicked(Standard_False);
759 HilightPicked(updateviewer);
762 //================================================================
763 // Function : UpdateSelected
764 // Purpose : Part of advanced selection mechanism.
765 // Highlightes or clears selection presentation for the given IO
766 //================================================================
767 void AIS_LocalContext::UpdateSelected(const Handle(AIS_InteractiveObject)& anobj,
768 const Standard_Boolean updateviewer)
770 if (anobj.IsNull() || anobj->IsAutoHilight())
773 SelectMgr_SequenceOfOwner aSeq;
774 for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
776 if (aSelIter.Value()->Selectable() == anobj)
778 aSeq.Append (aSelIter.Value());
783 anobj->HilightSelected( myMainPM, aSeq );
785 anobj->ClearSelected();
788 myCTX->CurrentViewer()->Update();
792 //==================================================
793 // Function: ClearSelected
795 //==================================================
796 void AIS_LocalContext::ClearSelected (const Standard_Boolean updateviewer)
798 UnhilightPicked(updateviewer);
799 for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
801 aSelIter.Value()->SetSelected (Standard_False);
803 mySelection->Clear();
807 //==================================================
808 // Function: ClearOutdatedSelection
810 //==================================================
811 void AIS_LocalContext::ClearOutdatedSelection (const Handle(AIS_InteractiveObject)& theIO,
812 const Standard_Boolean toClearDeactivated)
814 // 1. Collect selectable entities
815 SelectMgr_IndexedMapOfOwner aValidOwners;
817 const TColStd_ListOfInteger& aModes = SelectionModes (theIO);
819 TColStd_ListIteratorOfListOfInteger aModeIter (aModes);
820 for (; aModeIter.More(); aModeIter.Next())
822 int aMode = aModeIter.Value();
823 if (!theIO->HasSelection(aMode))
828 if (toClearDeactivated && !mySM->IsActivated(theIO, aMode, myMainVS))
833 Handle(SelectMgr_Selection) aSelection = theIO->Selection(aMode);
834 for (aSelection->Init(); aSelection->More(); aSelection->Next())
836 Handle(SelectBasics_SensitiveEntity) anEntity = aSelection->Sensitive()->BaseSensitive();
837 if (anEntity.IsNull())
842 Handle(SelectMgr_EntityOwner) anOwner =
843 Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId());
845 if (anOwner.IsNull())
850 aValidOwners.Add(anOwner);
854 // 2. Refresh context's detection and selection and keep only active owners.
855 // Keep last detected object for lastindex initialization.
856 Handle(SelectMgr_EntityOwner) aLastPicked;
857 if (IsValidIndex (mylastindex))
859 aLastPicked = myMapOfOwner->FindKey (mylastindex);
862 // Remove entity owners from detected sequences
863 for (Standard_Integer anIdx = 1; anIdx <= myDetectedSeq.Length(); ++anIdx)
865 Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (anIdx));
866 if (anOwner.IsNull() || anOwner->Selectable() != theIO || aValidOwners.Contains (anOwner))
871 myDetectedSeq.Remove (anIdx--);
873 if (anIdx < myCurDetected)
878 myCurDetected = Max (myCurDetected, 1);
880 Standard_Boolean isAISRemainsDetected = Standard_False;
882 // 3. AIS_Selection : remove entity owners from AIS_Selection
883 const Handle(V3d_Viewer)& aViewer = myCTX->CurrentViewer();
884 NCollection_List<Handle(SelectMgr_EntityOwner)> aRemoveEntites;
885 for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
887 Handle(SelectMgr_EntityOwner) anOwner = aSelIter.Value();
888 if (anOwner->Selectable() != theIO)
893 if (aValidOwners.Contains (anOwner))
895 isAISRemainsDetected = Standard_True;
899 aRemoveEntites.Append (anOwner);
900 anOwner->SetSelected (Standard_False);
901 for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
903 Unhilight (anOwner, anActiveViewIter.Value());
908 for (NCollection_List<Handle(SelectMgr_EntityOwner)>::Iterator anIterRemove (aRemoveEntites);
909 anIterRemove.More(); anIterRemove.Next())
911 mySelection->Select (anIterRemove.Value());
914 // 4. AIS_LocalContext - myMapOfOwner : remove entity owners from myMapOfOwner
915 SelectMgr_IndexedMapOfOwner anOwnersToKeep;
916 for (Standard_Integer anIdx = 1; anIdx <= myMapOfOwner->Extent(); anIdx++)
918 Handle(SelectMgr_EntityOwner) anOwner = myMapOfOwner->FindKey (anIdx);
919 if (anOwner.IsNull())
924 if (anOwner->Selectable() != theIO || aValidOwners.Contains (anOwner))
926 anOwnersToKeep.Add (anOwner);
930 for (V3d_ListOfViewIterator anActiveViewIter (aViewer->ActiveViewIterator()); anActiveViewIter.More(); anActiveViewIter.Next())
932 Unhilight (anOwner, anActiveViewIter.Value());
936 myMapOfOwner->Clear();
937 myMapOfOwner->Assign (anOwnersToKeep);
939 if (myDetectedSeq.IsEmpty() && !aLastPicked.IsNull())
941 myMainPM->ClearImmediateDraw();
944 else if (!aLastPicked.IsNull())
946 // For a case when the last detected owner was unhilighted and removed as outdated we
947 // need to check if there were other detected owners with less priority. If yes then
948 // one from the remaining should be treated.
949 Standard_Integer anIndex = 1, aDetectedSeqLength = myDetectedSeq.Length();
950 for (; anIndex <= aDetectedSeqLength; anIndex++)
952 if (aLastPicked == myMainVS->Picked (myDetectedSeq.Value(anIndex)))
954 break; // detected owner was not removed
957 if (anIndex <= aDetectedSeqLength)
959 // Last detected owner was not removed, update mylastindex variable
960 mylastindex = myMapOfOwner->FindIndex (aLastPicked);
964 // Last detected owner was removed. First object from sequence become detected.
965 // Pass any active view because in current implementation the highlighting is
966 // synchronized in all view.
967 manageDetected (myMainVS->Picked (myDetectedSeq.First()),
968 aViewer->ActiveViewIterator().Value(),
973 // Renew iterator of ::DetectedCurrentObject()
974 if (!isAISRemainsDetected)
976 // Remove the interactive object from detected sequences
977 for (Standard_Integer anIdx = 1; anIdx <= myAISDetectedSeq.Length(); ++anIdx)
979 Handle(AIS_InteractiveObject) aDetectedIO = myAISDetectedSeq.Value (anIdx);
980 if (aDetectedIO.IsNull() || aDetectedIO != theIO)
985 myAISDetectedSeq.Remove (anIdx--);
987 if (anIdx < myAISCurDetected)
992 myAISCurDetected = Max (myAISCurDetected, 1);
996 //=======================================================================
997 //function : SetSelected
999 //=======================================================================
1000 void AIS_LocalContext::SetSelected(const Handle(AIS_InteractiveObject)& anIObj,
1001 const Standard_Boolean updateviewer)
1003 if(!IsValidForSelection(anIObj)) return;
1004 UnhilightPicked(Standard_False);
1006 //1st case, owner already <anIObj> as owner
1007 // and not separated is found...
1009 Handle(SelectMgr_EntityOwner) EO = FindSelectedOwnerFromIO(anIObj);
1011 //check if in selection number 0 there is an owner that can be triturated...
1012 if(anIObj->HasSelection(0)){
1013 const Handle(SelectMgr_Selection)& SIOBJ = anIObj->Selection(0);
1016 Handle(SelectBasics_EntityOwner) BO = SIOBJ->Sensitive()->BaseSensitive()->OwnerId();
1017 EO = Handle(SelectMgr_EntityOwner)::DownCast (BO);
1021 EO = new SelectMgr_EntityOwner((const Handle(SelectMgr_SelectableObject)&)anIObj);
1024 ClearSelected(Standard_False);
1026 mySelection->Select(EO);
1027 EO->SetSelected (Standard_True);
1029 HilightPicked(updateviewer);
1032 //=======================================================================
1033 //function : AddOrRemoveSelected
1035 //=======================================================================
1037 void AIS_LocalContext::AddOrRemoveSelected(const Handle(AIS_InteractiveObject)& anIObj,
1038 const Standard_Boolean updateviewer)
1040 if(!IsValidForSelection(anIObj)) return;
1041 UnhilightPicked(Standard_False);
1042 // first check if it is selected...
1043 Handle(SelectMgr_EntityOwner) EO;
1045 EO = FindSelectedOwnerFromIO(anIObj);
1049 if(anIObj->HasSelection(0))
1051 const Handle(SelectMgr_Selection)& SIOBJ = anIObj->Selection(0);
1054 Handle(SelectBasics_EntityOwner) BO = SIOBJ->Sensitive()->BaseSensitive()->OwnerId();
1055 EO = Handle(SelectMgr_EntityOwner)::DownCast (BO);
1060 EO = new SelectMgr_EntityOwner((const Handle(SelectMgr_SelectableObject)&)anIObj);
1064 if (!mySelection.IsNull())
1066 AIS_SelectStatus aStatus = mySelection->Select(EO);
1067 EO->SetSelected (aStatus == AIS_SS_Added);
1070 HilightPicked(updateviewer);
1073 //=======================================================================
1074 //function : AddOrRemoveSelected
1075 //purpose : To check...
1076 //=======================================================================
1077 void AIS_LocalContext::AddOrRemoveSelected(const TopoDS_Shape& Sh,
1078 const Standard_Boolean updateviewer)
1080 UnhilightPicked (Standard_False);
1081 Handle(SelectMgr_EntityOwner) EO = FindSelectedOwnerFromShape(Sh);
1084 mySelection->Select(EO);
1085 EO->SetSelected (Standard_True);
1087 HilightPicked (updateviewer);
1090 void AIS_LocalContext::AddOrRemoveSelected (const Handle(SelectMgr_EntityOwner)& theOwner,
1091 const Standard_Boolean toUpdateViewer)
1095 UnhilightPicked (Standard_False);
1098 Standard_Boolean toSelect = theOwner->IsSelected() ? Standard_False : Standard_True;
1100 mySelection->Select(theOwner);
1101 theOwner->SetSelected (toSelect);
1105 HilightPicked (toUpdateViewer);
1109 //==================================================
1110 // Function: manageDetected
1112 //==================================================
1113 void AIS_LocalContext::manageDetected (const Handle(SelectMgr_EntityOwner)& thePickOwner,
1114 const Handle(V3d_View)& theView,
1115 const Standard_Boolean theToRedrawImmediate)
1117 if (thePickOwner.IsNull())
1119 myMainPM->ClearImmediateDraw();
1120 if (theToRedrawImmediate)
1122 theView->RedrawImmediate();
1127 if (!myFilters->IsOk (thePickOwner))
1129 if (mylastindex != 0)
1131 mylastgood = mylastindex;
1133 if (theToRedrawImmediate)
1135 theView->RedrawImmediate();
1140 //=======================================================================================================
1141 // 2 cases : a- object is in the map of picks:
1142 // 1. this is the same index as the last detected: -> Do nothing
1144 // - if lastindex = 0 (no object was detected at the last step)
1145 // the object presentation is highlighted and lastindex = index(objet)
1147 // the presentation of the object corresponding to lastindex is "unhighlighted"
1148 // it is removed if the object is not visualized but only active
1149 // then the presentation of the detected object is highlighted and lastindex = index(objet)
1150 // b- the object is not in the map of picked objects
1151 // - if lastindex != 0 (object detected at the last step) it is unhighlighted ...
1152 // if the object was decomposed, presentation is created for the detected shape and the couple
1153 // (Proprietaire,Prs)is added in the map.
1154 // otherwise the couple(proprietaire, NullPrs) is placed in the map and the interactive object
1155 // itself is highlighted.
1157 //=======================================================================================================
1159 const Standard_Integer aNewIndex = myMapOfOwner->Contains (thePickOwner)
1160 ? myMapOfOwner->FindIndex (thePickOwner)
1161 : myMapOfOwner->Add (thePickOwner);
1163 // For the advanced mesh selection mode the owner indices comparison
1164 // is not effective because in that case only one owner manage the
1165 // selection in current selection mode. It is necessary to check the current detected
1166 // entity and hilight it only if the detected entity is not the same as
1167 // previous detected (IsForcedHilight call)
1168 if (aNewIndex != mylastindex
1169 || thePickOwner->IsForcedHilight())
1171 myMainPM->ClearImmediateDraw();
1172 if (mylastindex != 0
1173 && mylastindex <= myMapOfOwner->Extent())
1175 const Handle(SelectMgr_EntityOwner)& aLastOwner = myMapOfOwner->FindKey (mylastindex);
1176 Unhilight (aLastOwner, theView);
1181 if (!thePickOwner->IsSelected() || myCTX->ToHilightSelected())
1183 Hilight (thePickOwner, theView);
1185 if (theToRedrawImmediate)
1187 theView->RedrawImmediate();
1191 mylastindex = aNewIndex;
1194 if (mylastindex != 0)
1196 mylastgood = mylastindex;
1200 //=======================================================================
1201 //function : HasDetectedShape
1203 //=======================================================================
1205 Standard_Boolean AIS_LocalContext::HasDetectedShape() const
1207 if(mylastindex==0) return Standard_False;
1208 return IsShape(mylastindex);
1211 //=======================================================================
1212 //function : DetectedShape
1214 //=======================================================================
1217 AIS_LocalContext::DetectedShape() const
1219 if(mylastindex != 0)
1221 Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(myMapOfOwner->FindKey (mylastindex));
1222 if(BROwnr.IsNull()) return AIS_myDummyShape;
1223 return BROwnr->Shape();
1225 return AIS_myDummyShape;
1228 //=======================================================================
1229 //function : DetectedInteractive
1231 //=======================================================================
1233 Handle(AIS_InteractiveObject)
1234 AIS_LocalContext::DetectedInteractive() const
1236 Handle(AIS_InteractiveObject) Iobj;
1237 if(IsValidIndex(mylastindex)){
1238 Handle(SelectMgr_SelectableObject) SO = myMapOfOwner->FindKey(mylastindex)->Selectable();
1239 Iobj = Handle(AIS_InteractiveObject)::DownCast (SO);
1243 //=======================================================================
1244 //function : DetectedInteractive
1246 //=======================================================================
1247 Handle(SelectMgr_EntityOwner) AIS_LocalContext::DetectedOwner() const
1249 Handle(SelectMgr_EntityOwner) bid;
1250 if(!IsValidIndex(mylastindex)) return bid;
1251 return myMapOfOwner->FindKey(mylastindex);
1255 //=======================================================================
1256 //function : ComesFromDecomposition
1258 //=======================================================================
1260 Standard_Boolean AIS_LocalContext::ComesFromDecomposition(const Standard_Integer PickedIndex) const
1262 const Handle(SelectMgr_EntityOwner)& OWN = myMapOfOwner->FindKey(PickedIndex);
1263 Handle(SelectMgr_SelectableObject) aSel = OWN->Selectable();
1264 if (myActiveObjects.IsBound (aSel)) { // debug of jmi
1265 const Handle(AIS_LocalStatus)& Stat = myActiveObjects(aSel);
1266 return Stat->Decomposed();
1268 return Standard_False;
1271 //=======================================================================
1272 //function : DisplaySensitive
1274 //=======================================================================
1276 void AIS_LocalContext::DisplaySensitive(const Handle(V3d_View)& aviou)
1278 myMainVS->DisplaySensitive(aviou);
1281 //=======================================================================
1282 //function : ClearSensitive
1284 //=======================================================================
1286 void AIS_LocalContext::ClearSensitive(const Handle(V3d_View)& aviou)
1288 myMainVS->ClearSensitive(aviou);
1292 //=======================================================================
1293 //function : IsShape
1295 //=======================================================================
1296 Standard_Boolean AIS_LocalContext::IsShape(const Standard_Integer Index) const
1298 Handle(SelectMgr_EntityOwner) aEO (myMapOfOwner->FindKey(Index));
1299 if (aEO.IsNull() || ! aEO->IsKind(STANDARD_TYPE(StdSelect_BRepOwner)))
1300 return Standard_False;
1302 ComesFromDecomposition(Index);
1305 Standard_Boolean AIS_LocalContext::IsValidForSelection(const Handle(AIS_InteractiveObject)& anIObj) const
1307 const Handle(SelectMgr_SelectableObject)& aSelObj = anIObj; // to avoid ambiguity
1308 // Shape was not transfered from AIS_Shape to EntityOwner
1309 Handle(AIS_Shape) shape = Handle(AIS_Shape)::DownCast(anIObj);
1310 if( !shape.IsNull() )
1311 return myFilters->IsOk(new StdSelect_BRepOwner(shape->Shape(), aSelObj));
1312 return myFilters->IsOk(new SelectMgr_EntityOwner(aSelObj));
1316 //=======================================================================
1317 //function : HilightNextDetected
1319 //=======================================================================
1320 Standard_Integer AIS_LocalContext::HilightNextDetected (const Handle(V3d_View)& theView,
1321 const Standard_Boolean theToRedrawImmediate)
1323 // go to the next owner
1324 if (myDetectedSeq.IsEmpty())
1329 const Standard_Integer aLen = myDetectedSeq.Length();
1330 if (++myCurDetected > aLen)
1334 Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
1335 if (anOwner.IsNull())
1339 manageDetected (anOwner, theView, theToRedrawImmediate);
1340 return myCurDetected;
1343 //=======================================================================
1344 //function : HilightPreviousDetected
1346 //=======================================================================
1347 Standard_Integer AIS_LocalContext::HilightPreviousDetected (const Handle(V3d_View)& theView,
1348 const Standard_Boolean theToRedrawImmediate)
1350 if (myDetectedSeq.IsEmpty())
1355 const Standard_Integer aLen = myDetectedSeq.Length();
1356 if (--myCurDetected < 1)
1358 myCurDetected = aLen;
1360 Handle(SelectMgr_EntityOwner) anOwner = myMainVS->Picked (myDetectedSeq (myCurDetected));
1361 if (anOwner.IsNull())
1366 manageDetected (anOwner, theView, theToRedrawImmediate);
1367 return myCurDetected;
1370 //=======================================================================
1371 //function : UnhilightLastDetected
1373 //=======================================================================
1374 Standard_Boolean AIS_LocalContext::UnhilightLastDetected (const Handle(V3d_View)& theView)
1376 if (!IsValidIndex (mylastindex))
1378 return Standard_False;
1381 myMainPM->BeginImmediateDraw();
1382 const Handle(SelectMgr_EntityOwner)& anOwner = myMapOfOwner->FindKey (mylastindex);
1383 const Standard_Integer aHilightMode = anOwner->HasSelectable()
1384 ? GetHiMod (Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable()))
1387 myMapOfOwner->FindKey (mylastindex)->Unhilight (myMainPM, aHilightMode);
1388 myMainPM->EndImmediateDraw (theView->Viewer());
1390 return Standard_True;
1393 //=======================================================================
1394 //function : FindSelectedOwnerFromIO
1395 //purpose : it is checked if one of the selected owners really presents IObj
1396 //=======================================================================
1397 Handle(SelectMgr_EntityOwner) AIS_LocalContext::FindSelectedOwnerFromIO (const Handle(AIS_InteractiveObject)& theObj) const
1399 Handle(SelectMgr_EntityOwner) EO,bid;
1401 || mySelection.IsNull())
1403 return Handle(SelectMgr_EntityOwner)();
1406 for (AIS_NListOfEntityOwner::Iterator aSelIter (mySelection->Objects()); aSelIter.More(); aSelIter.Next())
1408 if (theObj != aSelIter.Value()->Selectable())
1413 Handle(StdSelect_BRepOwner) aBROwner = Handle(StdSelect_BRepOwner)::DownCast(aSelIter.Value());
1414 if (aBROwner.IsNull()
1415 || !aBROwner->ComesFromDecomposition())
1417 return aSelIter.Value();
1420 return Handle(SelectMgr_EntityOwner)();
1423 //=======================================================================
1424 //function : FindSelectedOwnerFromShape
1425 //purpose : it is checked if one of the selected owners really presents IObj
1426 //=======================================================================
1427 Handle(SelectMgr_EntityOwner) AIS_LocalContext::FindSelectedOwnerFromShape(const TopoDS_Shape& sh) const
1429 Handle(SelectMgr_EntityOwner) EO, bid;
1430 if (sh.IsNull()) return EO;
1432 if(mySelection.IsNull()) {
1436 Standard_Boolean found(Standard_False);
1439 NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
1440 myMainVS->ActiveOwners (anActiveOwners);
1441 for (NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (anActiveOwners); anOwnersIt.More(); anOwnersIt.Next())
1443 EO = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value());
1444 Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(EO);
1445 if (!BROwnr.IsNull() && BROwnr->HasShape() && BROwnr->Shape() == sh) {
1446 found = Standard_True;
1452 if(found) return EO;
1456 //=======================================================================
1457 //function : AIS_LocalContext::InitDetected
1459 //=======================================================================
1460 void AIS_LocalContext::InitDetected()
1462 myAISCurDetected = myAISDetectedSeq.Length()? 1 : 0;
1465 //=======================================================================
1466 //function : AIS_LocalContext::MoreDetected
1468 //=======================================================================
1469 Standard_Boolean AIS_LocalContext::MoreDetected() const
1471 return (myAISCurDetected > 0 && myAISCurDetected <= myAISDetectedSeq.Length());
1474 //=======================================================================
1475 //function : AIS_LocalContext::NextDetected
1477 //=======================================================================
1478 void AIS_LocalContext::NextDetected()
1483 //=======================================================================
1484 //function : DetectedCurrentShape
1486 //=======================================================================
1487 const TopoDS_Shape& AIS_LocalContext::DetectedCurrentShape() const
1489 Handle(AIS_Shape) aCurrentShape = Handle(AIS_Shape)::DownCast (DetectedCurrentObject());
1491 if (aCurrentShape.IsNull())
1493 return AIS_myDummyShape;
1496 return aCurrentShape->Shape();
1498 //=======================================================================
1499 //function : DetectedCurrentObject
1501 //=======================================================================
1502 Handle(AIS_InteractiveObject) AIS_LocalContext::DetectedCurrentObject() const
1504 return MoreDetected() ? myAISDetectedSeq(myAISCurDetected) : NULL;
1507 //=======================================================================
1508 //function : RestoreActivatedModes
1510 //=======================================================================
1511 void AIS_LocalContext::RestoreActivatedModes() const
1513 for (AIS_DataMapOfSelStat::Iterator anIter (myActiveObjects); anIter.More(); anIter.Next())
1515 const TColStd_ListOfInteger& anActivatedModes = anIter.Value()->SelectionModes();
1516 for (TColStd_ListIteratorOfListOfInteger aModesIter (anActivatedModes); aModesIter.More(); aModesIter.Next())
1518 mySM->Activate (anIter.Key(), aModesIter.Value(), myMainVS);