0027285: Visualization - selection of AIS_MultipleConnectedInteractive is broken
[occt.git] / src / SelectMgr / SelectMgr_SelectableObject.cxx
index 4a0d3a7..6a96a33 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <Standard_NotImplemented.hxx>
 
-#include <SelectMgr_SelectableObject.ixx>
-#include <Standard_NoSuchObject.hxx>
-#include <SelectMgr_Selection.hxx>
-#include <Select3D_SensitiveEntity.hxx>
-#include <SelectBasics_EntityOwner.hxx>
-#include <SelectMgr_EntityOwner.hxx>
-#include <PrsMgr_PresentationManager3d.hxx>
-#include <Prs3d_Drawer.hxx>
-#include <Prs3d_LineAspect.hxx>
-#include <Prs3d_PointAspect.hxx>
 #include <Aspect_TypeOfMarker.hxx>
-#include <Prs3d_PlaneAspect.hxx>
+#include <Bnd_Box.hxx>
+#include <gp_Pnt.hxx>
 #include <Graphic3d_AspectLine3d.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
-
+#include <Prs3d_Drawer.hxx>
+#include <Prs3d_LineAspect.hxx>
+#include <Prs3d_PlaneAspect.hxx>
+#include <Prs3d_PointAspect.hxx>
+#include <Prs3d_Presentation.hxx>
+#include <PrsMgr_PresentableObjectPointer.hxx>
+#include <PrsMgr_PresentationManager3d.hxx>
+#include <Select3D_SensitiveEntity.hxx>
+#include <SelectBasics_EntityOwner.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <SelectMgr_IndexedMapOfOwner.hxx>
+#include <SelectMgr_SelectableObject.hxx>
+#include <SelectMgr_Selection.hxx>
+#include <SelectMgr_SelectionManager.hxx>
+#include <Standard_NoSuchObject.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Standard_Type.hxx>
 #include <TopLoc_Location.hxx>
-#include <gp_Pnt.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_SelectableObject,PrsMgr_PresentableObject)
 
 static Standard_Integer Search (const SelectMgr_SequenceOfSelection& seq,
                                 const Handle (SelectMgr_Selection)& theSel)
@@ -50,11 +57,13 @@ static Standard_Integer Search (const SelectMgr_SequenceOfSelection& seq,
 // Purpose :
 //==================================================
 
-SelectMgr_SelectableObject::SelectMgr_SelectableObject( const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d):
-  PrsMgr_PresentableObject (aTypeOfPresentation3d),
+SelectMgr_SelectableObject::SelectMgr_SelectableObject (const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d)
+: PrsMgr_PresentableObject (aTypeOfPresentation3d),
   myDrawer                 (new Prs3d_Drawer()),
   myHilightDrawer          (new Prs3d_Drawer()),
-  myAutoHilight            (Standard_True)
+  myAssemblyOwner          (NULL),
+  myAutoHilight            (Standard_True),
+  myGlobalSelMode          (0)
 {
   InitDefaultHilightAttributes (myHilightDrawer);
   myHilightDrawer->Link (myDrawer);
@@ -62,56 +71,80 @@ SelectMgr_SelectableObject::SelectMgr_SelectableObject( const PrsMgr_TypeOfPrese
 
 
 //==================================================
-// Function: 
+// Function: HasSelection
 // Purpose :
 //==================================================
-
-Standard_Boolean SelectMgr_SelectableObject
-::HasSelection(const Standard_Integer aMode) const
+Standard_Boolean SelectMgr_SelectableObject::HasSelection (const Standard_Integer theMode) const
 {
-  Standard_Boolean Found=Standard_False;
-  for (Standard_Integer I=1;I<= myselections.Length() && !Found;I++)
-    { if(((myselections.Value(I))->Mode())==aMode) 
-        return Standard_True;
-    }
+  for (Standard_Integer aSelIdx = 1; aSelIdx <= myselections.Length(); ++aSelIdx)
+  {
+    if (((myselections.Value (aSelIdx))->Mode()) == theMode)
+      return Standard_True;
+  }
   return Standard_False;
 }
 
 //==================================================
-// Function: UpdateSelection
-// Purpose :
+// Function: RecomputePrimitives
+// Purpose : IMPORTANT: Do not use this method to update
+//           selection primitives except implementing custom
+//           selection manager! This method does not take
+//           into account necessary BVH updates, but may
+//           invalidate the pointers it refers to.
+//           TO UPDATE SELECTION properly from outside classes,
+//           use method UpdateSelection.
 //==================================================
-void SelectMgr_SelectableObject::UpdateSelection()
+void SelectMgr_SelectableObject::RecomputePrimitives()
 {
-  for (Standard_Integer I=1;I<=myselections.Length();I++)
+  for (Standard_Integer aSelIdx = 1; aSelIdx <= myselections.Length(); aSelIdx++)
     {
-      UpdateSelection(myselections.ChangeValue(I)->Mode());
+      RecomputePrimitives (myselections.ChangeValue (aSelIdx)->Mode());
     }
 }
 
-Standard_Integer  SelectMgr_SelectableObject::NbPossibleSelection() const
-{return 0;}
-
 //==================================================
-// Function: UpdateSelection
-// Purpose :
+// Function: RecomputePrimitives
+// Purpose : IMPORTANT: Do not use this method to update
+//           selection primitives except implementing custom
+//           selection manager! This method does not take
+//           into account necessary BVH updates, but may
+//           invalidate the pointers it refers to.
+//           TO UPDATE SELECTION properly from outside classes,
+//           use method UpdateSelection.
 //==================================================
-void SelectMgr_SelectableObject::UpdateSelection(const Standard_Integer aMode)
+void SelectMgr_SelectableObject::RecomputePrimitives (const Standard_Integer theMode)
 {
-  for (Standard_Integer i =1; i<= myselections.Length(); i++ ) {
-    if (myselections.Value(i)->Mode() == aMode) {
-      myselections(i)->Clear();
-      ComputeSelection(myselections(i),aMode);
-      myselections(i)->UpdateStatus(SelectMgr_TOU_Partial);
+  Handle(PrsMgr_PresentableObject) aPrsParent (Parent());
+  Handle(SelectMgr_SelectableObject) aSelParent = Handle(SelectMgr_SelectableObject)::DownCast (aPrsParent);
+
+  for (Standard_Integer aSelIdx =1; aSelIdx <= myselections.Length(); aSelIdx++ )
+  {
+    if (myselections.Value (aSelIdx)->Mode() == theMode)
+    {
+      myselections (aSelIdx)->Clear();
+      ComputeSelection (myselections (aSelIdx), theMode);
+      myselections (aSelIdx)->UpdateStatus (SelectMgr_TOU_Partial);
+      myselections (aSelIdx)->UpdateBVHStatus (SelectMgr_TBU_Renew);
+      if (theMode == 0 && ! aSelParent.IsNull() && ! aSelParent->GetAssemblyOwner().IsNull())
+      {
+        SetAssemblyOwner (aSelParent->GetAssemblyOwner(), theMode);
+      }
       return;
     }
   }
-  Handle(SelectMgr_Selection) S = new SelectMgr_Selection(aMode);
-  ComputeSelection(S,aMode);
-  S->UpdateStatus(SelectMgr_TOU_Partial);
-  
-  myselections.Append(S);
-  
+
+  Handle(SelectMgr_Selection) aNewSel = new SelectMgr_Selection (theMode);
+  ComputeSelection (aNewSel, theMode);
+
+  if (theMode == 0 && ! aSelParent.IsNull() && ! aSelParent->GetAssemblyOwner().IsNull())
+  {
+    SetAssemblyOwner (aSelParent->GetAssemblyOwner(), theMode);
+  }
+
+  aNewSel->UpdateStatus (SelectMgr_TOU_Partial);
+  aNewSel->UpdateBVHStatus (SelectMgr_TBU_Add);
+
+  myselections.Append (aNewSel);
 }
 
 //==================================================
@@ -122,8 +155,11 @@ void SelectMgr_SelectableObject::ClearSelections(const Standard_Boolean update)
 {
   for (Standard_Integer i =1; i<= myselections.Length(); i++ ) {
     myselections.Value(i)->Clear();
+    myselections.Value (i)->UpdateBVHStatus (SelectMgr_TBU_Remove);
     if(update)
+    {
       myselections.Value(i)->UpdateStatus(SelectMgr_TOU_Full);
+    }
   }
 }
 
@@ -156,18 +192,39 @@ void SelectMgr_SelectableObject
 ::AddSelection(const Handle(SelectMgr_Selection)& aSel,
                const Standard_Integer aMode)
 {
-  if(aSel->IsEmpty()){
-    ComputeSelection(aSel,aMode);
+  Standard_Boolean isReplaced = Standard_False;
+  if(aSel->IsEmpty())
+  {
+    ComputeSelection(aSel, aMode);
     aSel->UpdateStatus(SelectMgr_TOU_Partial);
+    aSel->UpdateBVHStatus (SelectMgr_TBU_Add);
   }
-  if(HasSelection(aMode))
+  if (HasSelection(aMode))
+  {
+    const Handle(SelectMgr_Selection)& temp= Selection(aMode);
+    Standard_Integer I = Search(myselections,temp);
+    if(I!=0)
     {
-      const Handle(SelectMgr_Selection)& temp= Selection(aMode);
-      Standard_Integer I = Search(myselections,temp);
-      if(I!=0) myselections.Remove(I);
+      myselections.Remove(I);
+      isReplaced = Standard_True;
     }
+  }
+
   myselections.Append(aSel);
-  
+  if (isReplaced)
+  {
+    myselections.Last()->UpdateBVHStatus (SelectMgr_TBU_Renew);
+  }
+
+  if (aMode == 0)
+  {
+    Handle(PrsMgr_PresentableObject) aPrsParent (Parent());
+    Handle(SelectMgr_SelectableObject) aSelParent = Handle(SelectMgr_SelectableObject)::DownCast (aPrsParent);
+    if (! aSelParent.IsNull() && ! aSelParent->GetAssemblyOwner().IsNull())
+    {
+      SetAssemblyOwner (aSelParent->GetAssemblyOwner(), aMode);
+    }
+  }
 }
 
 
@@ -178,54 +235,33 @@ void SelectMgr_SelectableObject
 //=======================================================================
 void SelectMgr_SelectableObject::ResetTransformation() 
 {
-  TopLoc_Location aLoc;
-
-  TopLoc_Location aSelfLocation (Transformation());
-
-  // les selections
-  Handle(Select3D_SensitiveEntity) SE;
-  for(Init();More();Next()){
-    const Handle(SelectMgr_Selection) & Sel =  CurrentSelection();
-    for(Sel->Init();Sel->More();Sel->Next()){
-      SE =  *((Handle(Select3D_SensitiveEntity)*) &(Sel->Sensitive()));
-      if(!SE.IsNull()){
-        if(SE->HasLocation()) {
-          if( SE->Location()==aSelfLocation){
-            SE->ResetLocation();
-            const Handle(SelectBasics_EntityOwner)& EO = SE->OwnerId();
-            (*((Handle(SelectMgr_EntityOwner)*)&EO))->ResetLocation();}
-          else{
-            const TopLoc_Location& iniloc =SE->Location();
-            SE->SetLocation(iniloc*aSelfLocation.Inverted());
-            const Handle(SelectBasics_EntityOwner)& EO = SE->OwnerId();
-            (*((Handle(SelectMgr_EntityOwner)*)&EO))->SetLocation(SE->Location());}
-        }
-      }
+  for (Init(); More(); Next())
+  {
+    const Handle(SelectMgr_Selection) & aSel = CurrentSelection();
+    for (aSel->Init(); aSel->More(); aSel->Next())
+    {
+      aSel->UpdateStatus(SelectMgr_TOU_Partial);
+      aSel->UpdateBVHStatus (SelectMgr_TBU_None);
     }
-    Sel->UpdateStatus(SelectMgr_TOU_None);
   }
 
   PrsMgr_PresentableObject::ResetTransformation();
 }
 
-
 //=======================================================================
 //function : UpdateTransformation
 //purpose  : 
 //=======================================================================
-void SelectMgr_SelectableObject::UpdateTransformation() 
+void SelectMgr_SelectableObject::UpdateTransformation()
 {
-  
-  Handle(Select3D_SensitiveEntity) SE;
-  for(Init();More();Next()){
-    const Handle(SelectMgr_Selection) & Sel =  CurrentSelection();
-    Sel->UpdateStatus(SelectMgr_TOU_Partial);
+  for (Init(); More(); Next())
+  {
+    CurrentSelection()->UpdateStatus (SelectMgr_TOU_Partial);
   }
-  PrsMgr_PresentableObject::UpdateTransformation();
 
+  PrsMgr_PresentableObject::UpdateTransformation();
 }
 
-
 //=======================================================================
 //function : UpdateTransformation
 //purpose  : 
@@ -236,9 +272,8 @@ void SelectMgr_SelectableObject::UpdateTransformations(const Handle(SelectMgr_Se
   Handle(Select3D_SensitiveEntity) SE;
   if(aSelfLocation.IsIdentity()) return;
   for(Sel->Init();Sel->More();Sel->Next()){
-    SE =  Handle(Select3D_SensitiveEntity)::DownCast(Sel->Sensitive());
+    SE =  Handle(Select3D_SensitiveEntity)::DownCast (Sel->Sensitive()->BaseSensitive());
     if(!SE.IsNull()){
-      SE->UpdateLocation(aSelfLocation);
       const Handle(SelectBasics_EntityOwner)& aEOwner = SE->OwnerId();
       Handle(SelectMgr_EntityOwner) aMgrEO =
                               Handle(SelectMgr_EntityOwner)::DownCast (aEOwner);
@@ -353,7 +388,7 @@ void SelectMgr_SelectableObject::SetZLayer (const Graphic3d_ZLayerId theLayerId)
     for (aSel->Init (); aSel->More (); aSel->Next ())
     {
       Handle(Select3D_SensitiveEntity) aEntity = 
-        Handle(Select3D_SensitiveEntity)::DownCast (aSel->Sensitive());
+        Handle(Select3D_SensitiveEntity)::DownCast (aSel->Sensitive()->BaseSensitive());
       if (!aEntity.IsNull())
       {
         Handle(SelectMgr_EntityOwner) aOwner = 
@@ -365,6 +400,35 @@ void SelectMgr_SelectableObject::SetZLayer (const Graphic3d_ZLayerId theLayerId)
   }
 }
 
+//=======================================================================
+//function : UpdateSelection
+//purpose  : Sets update status FULL to selections of the object. Must be
+//           used as the only method of UpdateSelection from outer classes
+//           to prevent BVH structures from being outdated.
+//=======================================================================
+void SelectMgr_SelectableObject::UpdateSelection (const Standard_Integer theMode)
+{
+  if (theMode == -1)
+  {
+    for (Init(); More(); Next())
+    {
+      const Handle(SelectMgr_Selection)& aSel = CurrentSelection();
+      aSel->UpdateStatus (SelectMgr_TOU_Full);
+    }
+
+    return;
+  }
+
+  for (Init(); More(); Next())
+  {
+    if (CurrentSelection()->Mode() == theMode)
+    {
+      CurrentSelection()->UpdateStatus (SelectMgr_TOU_Full);
+      return;
+    }
+  }
+}
+
 //=======================================================================
 //function : SetAttributes
 //purpose  : 
@@ -478,3 +542,118 @@ void SelectMgr_SelectableObject::InitDefaultHilightAttributes (const Handle(Prs3
   // computed in ::Compute() call for whole shape and stored in base drawer.
   theDrawer->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
 }
+
+//=======================================================================
+//function : SetAssemblyOwner
+//purpose  : Sets common entity owner for assembly sensitive object entities
+//=======================================================================
+void SelectMgr_SelectableObject::SetAssemblyOwner (const Handle(SelectMgr_EntityOwner)& theOwner,
+                                                   const Standard_Integer theMode)
+{
+  if (theMode == -1)
+  {
+    for (Standard_Integer aModeIter = 1; aModeIter <= myselections.Length(); ++aModeIter)
+    {
+      Handle(SelectMgr_Selection)& aSel = myselections.ChangeValue (aModeIter);
+      for (aSel->Init(); aSel->More(); aSel->Next())
+      {
+        aSel->Sensitive()->BaseSensitive()->Set (theOwner);
+      }
+    }
+
+    return;
+  }
+
+  if (!HasSelection (theMode))
+    return;
+
+  for (Standard_Integer aModeIter = 1; aModeIter <= myselections.Length(); ++aModeIter)
+  {
+    if (myselections.Value (aModeIter)->Mode() == theMode)
+    {
+      Handle(SelectMgr_Selection)& aSel = myselections.ChangeValue (aModeIter);
+      for (aSel->Init(); aSel->More(); aSel->Next())
+      {
+        aSel->Sensitive()->BaseSensitive()->Set (theOwner);
+      }
+      return;
+    }
+  }
+}
+
+//=======================================================================
+//function : GetAssemblyOwner
+//purpose  : Returns common entity owner if it is an assembly
+//=======================================================================
+const Handle(SelectMgr_EntityOwner)& SelectMgr_SelectableObject::GetAssemblyOwner() const
+{
+  return myAssemblyOwner;
+}
+
+//=======================================================================
+//function : BndBoxOfSelected
+//purpose  : Returns a bounding box of sensitive entities with the owners given
+//           if they are a part of activated selection
+//=======================================================================
+Bnd_Box SelectMgr_SelectableObject::BndBoxOfSelected (Handle(SelectMgr_IndexedMapOfOwner)& theOwners)
+{
+  Bnd_Box aBnd;
+
+  if (theOwners->IsEmpty())
+    return aBnd;
+
+  for (Init(); More(); Next())
+  {
+    const Handle(SelectMgr_Selection)& aSel = CurrentSelection();
+    if (aSel->GetSelectionState() != SelectMgr_SOS_Activated)
+      continue;
+
+    for (aSel->Init(); aSel->More(); aSel->Next())
+    {
+      const Handle(SelectMgr_EntityOwner) anOwner =
+        Handle(SelectMgr_EntityOwner)::DownCast (aSel->Sensitive()->BaseSensitive()->OwnerId());
+      if (theOwners->Contains (anOwner))
+      {
+        Select3D_BndBox3d aBox = aSel->Sensitive()->BaseSensitive()->BoundingBox();
+        Bnd_Box aTmpBnd;
+        aTmpBnd.Update (aBox.CornerMin().x(), aBox.CornerMin().y(), aBox.CornerMin().z(),
+                        aBox.CornerMax().x(), aBox.CornerMax().y(), aBox.CornerMax().z());
+        aBnd.Add (aTmpBnd);
+
+        Standard_Integer anOwnerIdx = theOwners->FindIndex (anOwner);
+        if (theOwners->Size() != anOwnerIdx)
+        {
+          theOwners->Swap (anOwnerIdx, theOwners->Size());
+        }
+        theOwners->RemoveLast();
+
+        if (theOwners->IsEmpty())
+          return aBnd;
+      }
+    }
+  }
+
+  return aBnd;
+}
+
+//=======================================================================
+//function : GlobalSelOwner
+//purpose  : Returns entity owner corresponding to selection of the object as a whole
+//=======================================================================
+Handle(SelectMgr_EntityOwner) SelectMgr_SelectableObject::GlobalSelOwner() const
+{
+   Handle(SelectMgr_EntityOwner) anOwner;
+
+  if (!HasSelection (myGlobalSelMode))
+    return anOwner;
+
+  const Handle(SelectMgr_Selection)& aGlobalSel = Selection (myGlobalSelMode);
+  if (aGlobalSel->IsEmpty())
+    return anOwner;
+
+  aGlobalSel->Init();
+  anOwner =
+    Handle(SelectMgr_EntityOwner)::DownCast (aGlobalSel->Sensitive()->BaseSensitive()->OwnerId());
+
+  return anOwner;
+}