0022368: AIS_Trihedron's highlight presentation isn't updated on trihedron relocation
authorAPL <>
Fri, 21 Oct 2011 16:07:55 +0000 (16:07 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:30:48 +0000 (19:30 +0400)
src/AIS/AIS_Trihedron.cdl
src/AIS/AIS_Trihedron.cxx
src/SelectMgr/SelectMgr_SelectableObject.cxx
src/StdSelect/StdSelect_BRepOwner.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx

index 9cb3e1f..8b5ad47 100755 (executable)
@@ -28,7 +28,11 @@ class Trihedron from AIS inherits InteractiveObject from AIS
        -- for length are stocked. For trihedra, this is
        -- AIS_Drawer_FirstAxisAspect. You change the
        -- values inside this Aspect and recalculate the presentation.
-       --  
+       -- If you want to use extended selection modes, different than 0,
+       -- you should take care of removing of the shapes from the interactive
+        -- context that has been computed for selection; it might be necessary
+        -- when you change selection mode. You can use methods Axis, Point,
+        -- Plane to retrieve the shapes.
 
 uses 
     Axis2Placement        from Geom,
@@ -46,7 +50,8 @@ uses
     Plane                 from AIS,
     KindOfInteractive     from AIS,
     InteractiveContext    from AIS,
-    Array1OfPnt           from  TColgp
+    Array1OfPnt           from  TColgp,
+    Location              from TopLoc
 is
 
     Create(aComponent : Axis2Placement from Geom)
@@ -140,6 +145,12 @@ is
        --          WARNING :<aTrsf> must be applied
        --           to the object to display before computation  !!!
 
+-- Methods from PresentableObject
+
+    SetLocation(me              : mutable;
+               aLoc            : Location from TopLoc)
+    is redefined static;
+
 -- Methods from SelectableObject
 
     ComputeSelection(me         : mutable;
index 03c08ca..5b0ad1b 100755 (executable)
@@ -71,9 +71,41 @@ myHasOwnSize(Standard_False)
 void AIS_Trihedron::SetComponent(const Handle(Geom_Axis2Placement)& aComponent)
 {
   myComponent = aComponent;
+
+  // Remove from current context and nullify objects to update
+  Handle(AIS_InteractiveContext) anAISContext = GetContext();
+  Standard_Boolean hasContext = (anAISContext.IsNull() == Standard_False);
+  Standard_Integer anIdx;
+  for (anIdx = 0; anIdx < 7; anIdx++)
+  {
+    // Deselect object
+    if (hasContext)
+    {
+      if (anAISContext->IsSelected (myShapes[anIdx]))
+        anAISContext->AddOrRemoveSelected (myShapes[anIdx], Standard_False);
+
+      anAISContext->Remove (myShapes[anIdx], Standard_False);
+    }
+    myShapes[anIdx].Nullify();
+  }
+
   LoadSubObjects();
 }
 
+//=======================================================================
+//function : SetLocation
+//purpose  : 
+//=======================================================================
+
+void AIS_Trihedron::SetLocation(const TopLoc_Location& aLoc)
+{
+  // Update location to the subshapes
+  Standard_Integer anIdx;
+  for (anIdx = 0; anIdx < 7; anIdx++)
+    myShapes[anIdx]->SetLocation (aLoc);
+
+  AIS_InteractiveObject::SetLocation (aLoc);
+}
 
 //=======================================================================
 //function : SetSize
@@ -266,10 +298,23 @@ void AIS_Trihedron::ComputeSelection(const Handle(SelectMgr_Selection)& aSelecti
                                      const Standard_Integer aMode)
 {
   // retrieve the tops of the trihedron.
-  Standard_Integer Prior;
+  Standard_Integer Prior, anIdx;
   Handle(SelectMgr_EntityOwner) eown;
   TColgp_Array1OfPnt PP(1,4),PO(1,4);
   ExtremityPoints(PP);
+
+  // remove shapes from active selections
+  Handle(AIS_InteractiveContext) anAISContext = GetContext();
+  if (!anAISContext.IsNull())
+    for (anIdx = 0; anIdx < 7; anIdx++)
+    {
+      // Deselect object
+      if (anAISContext->IsSelected (myShapes[anIdx]))
+        anAISContext->AddOrRemoveSelected (myShapes[anIdx], Standard_False);
+
+      anAISContext->Remove (myShapes[anIdx], Standard_False);
+    }
+  
   switch (aMode) {
   case 0:
     {   // complete triedron only 1 owner : this... priority 5 (same as faces)
@@ -285,7 +330,15 @@ void AIS_Trihedron::ComputeSelection(const Handle(SelectMgr_Selection)& aSelecti
       eown= new SelectMgr_EntityOwner(myShapes[0],Prior);
       
       aSelection->Add(new Select3D_SensitivePoint (eown,myComponent->Location()));
-
+      // If the trihedron's shapes display and selection modes are the same
+      // the shapes are still displayed after selection, so we need to
+      // use different presentation and hide it by nullifying
+      if (!anAISContext.IsNull())
+      {
+        anAISContext->Display (myShapes[0], 1, 0, Standard_False);
+        anAISContext->ClearPrs (myShapes[0], 1, Standard_False);
+      }
+      
       break;
     }
   case 2:
@@ -296,6 +349,29 @@ void AIS_Trihedron::ComputeSelection(const Handle(SelectMgr_Selection)& aSelecti
        aSelection->Add(new Select3D_SensitiveSegment(eown,PP(1),PP(i+1)));
 
       }
+
+      // If the trihedron's shapes display and selection modes are the same
+      // the shapes are still displayed after selection, so we need to
+      // use different presentation and hide it by nullifying
+      AIS_TypeOfAxis anAxisType;
+      if (!anAISContext.IsNull())
+        for (anIdx = 1; anIdx <= 3; anIdx++)
+        {
+          // update AIS_Axis for selection
+          Handle(AIS_Axis) anAxis = Handle(AIS_Axis)::DownCast(myShapes[anIdx]);
+          Handle(AIS_Drawer) aDrawer = anAxis->Attributes();
+          Handle(Prs3d_DatumAspect) aDatum = myDrawer->DatumAspect();
+          aDrawer->DatumAspect()->SetAxisLength (aDatum->FirstAxisLength(),
+                                                 aDatum->SecondAxisLength(),
+                                                 aDatum->ThirdAxisLength());
+          anAxisType = anAxis->TypeOfAxis();
+          anAxis->SetAxis2Placement (myComponent, anAxisType);
+
+          // display
+          anAISContext->Display (myShapes[anIdx], 1, 0, Standard_False);
+          anAISContext->ClearPrs (myShapes[anIdx], 1, Standard_False);
+        }
+      
       break;
     }
     
@@ -318,6 +394,15 @@ void AIS_Trihedron::ComputeSelection(const Handle(SelectMgr_Selection)& aSelecti
 //      PO(2) = PP(4);PO(3) = PP(2);
       aSelection->Add(new Select3D_SensitiveTriangle(eown,PP(1),PP(3),PP(4)));
       
+      // If the trihedron's shapes display and selection modes are the same
+      // the shapes are still displayed after selection, so we need to
+      // use different presentation and hide it by nullifying
+      if (!anAISContext.IsNull())
+        for (anIdx = 4; anIdx < 7; anIdx++)
+       {
+          anAISContext->Display (myShapes[anIdx], 1, 0, Standard_False);
+          anAISContext->ClearPrs (myShapes[anIdx], 1, Standard_False);
+        }
     }
   }
   
@@ -550,9 +635,26 @@ void AIS_Trihedron::SetContext(const Handle(AIS_InteractiveContext)& Ctx)
 {
 //  Standard_Boolean same_DA = myDrawer->Link() == Ctx->DefaultDrawer();
 
-  AIS_InteractiveObject::SetContext(Ctx);
+  // Remove subobjects from current context
+  Handle(AIS_InteractiveContext) anAISContext = GetContext();
+  Standard_Boolean hasContext = (anAISContext.IsNull() == Standard_False);
+  Standard_Integer anIdx;
+  for (anIdx = 0; anIdx < 7; anIdx++)
+    {
+      // Deselect object
+      if (hasContext)
+       {
+         if (anAISContext->IsSelected (myShapes[anIdx]))
+           anAISContext->AddOrRemoveSelected (myShapes[anIdx]);
+         
+         anAISContext->Remove (myShapes[anIdx], Standard_False);
+       }
+      myShapes[anIdx].Nullify();
+    }
+
+  AIS_InteractiveObject::SetContext (Ctx);
   
   LoadSubObjects();
   for(Standard_Integer i= 0;i<=6;i++)
-    myShapes[i]->SetContext(Ctx);
+    myShapes[i]->SetContext (Ctx);
 }
index adef86b..ac0dbea 100755 (executable)
@@ -216,6 +216,11 @@ void SelectMgr_SelectableObject::UpdateLocation(const Handle(SelectMgr_Selection
     SE =  *((Handle(Select3D_SensitiveEntity)*) &(Sel->Sensitive()));
     if(!SE.IsNull()){
       SE->UpdateLocation(myLocation);
+      const Handle(SelectBasics_EntityOwner)& aEOwner = SE->OwnerId();
+      Handle(SelectMgr_EntityOwner) aMgrEO =
+                              Handle(SelectMgr_EntityOwner)::DownCast (aEOwner);
+      if (!aMgrEO.IsNull())
+        aMgrEO->SetLocation (myLocation);
     }
   }
 }
index 7e3bd1b..706f5ff 100755 (executable)
@@ -78,10 +78,21 @@ void StdSelect_BRepOwner::Hilight(const Handle(PrsMgr_PresentationManager)& PM,
 #else
   Standard_Integer M = (myCurMode==-1) ? aMode:myCurMode;
 #endif
-  if(myFromDecomposition)
+  if (myFromDecomposition)
+  {
+    // do the update flag check
+    if (!myPrsSh.IsNull())
+    {
+      TColStd_ListOfInteger aModesList;
+      myPrsSh->ToBeUpdated (aModesList);
+      if (!aModesList.IsEmpty())
+        myPrsSh.Nullify();
+    }
+
     if(myPrsSh.IsNull())
-      myPrsSh = new StdSelect_Shape(myShape);
-  
+      myPrsSh = new StdSelect_Shape (myShape);
+  }  
+
   if(myPrsSh.IsNull())
     PM->Highlight(Selectable(),M);
   else
@@ -100,7 +111,17 @@ void StdSelect_BRepOwner::HilightWithColor(const Handle(PrsMgr_PresentationManag
 #else
   Standard_Integer M = (myCurMode==-1) ? aMode:myCurMode;
 #endif
-  if(myFromDecomposition){
+  if (myFromDecomposition)
+  {
+    // do the update flag check
+    if (!myPrsSh.IsNull())
+    {
+      TColStd_ListOfInteger aModesList;
+      myPrsSh->ToBeUpdated (aModesList);
+      if (!aModesList.IsEmpty())
+        myPrsSh.Nullify();
+    }
+
     if(myPrsSh.IsNull()){
       if(HasLocation()){
        TopLoc_Location lbid = Location() * myShape.Location();
@@ -147,13 +168,20 @@ void StdSelect_BRepOwner::Clear(const Handle(PrsMgr_PresentationManager)& PM,
 void StdSelect_BRepOwner::SetLocation(const TopLoc_Location& aLoc)
 {
   SelectMgr_EntityOwner::SetLocation(aLoc);
-  if(!myPrsSh.IsNull())
-    myPrsSh.Nullify();
-  
+  // we must not nullify the myPrsSh here, because unhilight method
+  // will be working with wrong entity in this case, the best is to
+  // set the update flag and then recompute myPrsSh on hilighting
+  if (!myPrsSh.IsNull())
+    myPrsSh->SetToUpdate();
 }
 void StdSelect_BRepOwner::ResetLocation()
 {
   SelectMgr_EntityOwner::ResetLocation();
-  if(!myPrsSh.IsNull())
-    myPrsSh.Nullify(); 
+  // we must not nullify the myPrsSh here, because unhilight method
+  // will be working with wrong entity in this case, the best is to
+  // set the update flag and then recompute myPrsSh on hilighting
+  if (!myPrsSh.IsNull())
+    myPrsSh->SetToUpdate();
+
 }
index d60832b..98f06a7 100755 (executable)
@@ -76,6 +76,8 @@
 #include <Geom_Axis1Placement.hxx>
 #include <AIS_Trihedron.hxx>
 #include <AIS_Axis.hxx>
+#include <gp_Trsf.hxx>
+#include <TopLoc_Location.hxx>
 
 #include <HLRAlgo_Projector.hxx>
 #include <HLRBRep_PolyAlgo.hxx>
@@ -3198,6 +3200,62 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char*
 }
 
 //=======================================================================
+//function : VSetLocation
+//purpose  : Change location of AIS interactive object
+//=======================================================================
+
+static Standard_Integer VSetLocation (Draw_Interpretor& di,
+                                      Standard_Integer argc,
+                                      const char ** argv)
+{
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
+  {
+    di << argv[0] << "ERROR : use 'vinit' command before " << "\n";
+    return 1;
+  }
+
+  if (argc != 5)
+  {
+    di << "ERROR : Usage : " << argv[0] << " name x y z; new location" << "\n";
+    return 1;
+  }
+
+  TCollection_AsciiString aName (argv[1]);
+  Standard_Real aX = atof (argv[2]);
+  Standard_Real aY = atof (argv[3]);
+  Standard_Real aZ = atof (argv[4]);
+
+  // find object
+  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
+  Handle(AIS_InteractiveObject) anIObj;
+  if (!aMap.IsBound2 (aName))
+  {
+    di << "Use 'vdisplay' before" << "\n";
+    return 1;
+  }
+  else
+  {
+    anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
+
+    // not an AIS_InteractiveObject
+    if (anIObj.IsNull())
+    {
+      di << argv[1] << " : Not an AIS interactive object" << "\n";
+      return 1;
+    }
+
+    gp_Trsf aTrsf;
+    aTrsf.SetTranslation (gp_Vec (aX, aY, aZ));
+    TopLoc_Location aLocation (aTrsf);
+    aContext->SetLocation (anIObj, aLocation);
+    aContext->UpdateCurrentViewer();
+  }
+
+  return 0;
+}
+
+//=======================================================================
 //function : ObjectsCommands
 //purpose  :
 //=======================================================================
@@ -3269,6 +3327,10 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
     "vclipplane : vclipplane [x y z dx dy dz] [planeId {on/off/del/display/hide}]",
     __FILE__,VClipPlane,group);
 
+  theCommands.Add ("vsetlocation",
+        "vsetlocation : name x y z; set new location for an interactive object",
+        __FILE__, VSetLocation, group);
+
   theCommands.Add (
     "vcomputehlr",
     "vcomputehlr: shape hlrname [ eyex eyey eyez lookx looky lookz ]",