0025316: Draw viewer commands - display (erase) objects in local selection context
[occt.git] / src / ViewerTest / ViewerTest.cxx
index 7698ebd..a1597da 100644 (file)
 #include <Standard_Stream.hxx>
 
 #include <ViewerTest.hxx>
+
 #include <TopLoc_Location.hxx>
 #include <TopTools_HArray1OfShape.hxx>
 #include <TColStd_HArray1OfTransient.hxx>
+#include <TColStd_SequenceOfAsciiString.hxx>
 #include <TColStd_HSequenceOfAsciiString.hxx>
+#include <TColStd_MapOfTransient.hxx>
 #include <OSD_Timer.hxx>
 #include <Geom_Axis2Placement.hxx>
 #include <Geom_Axis1Placement.hxx>
 #include <Image_AlienPixMap.hxx>
 #include <Prs3d_ShadingAspect.hxx>
 #include <Prs3d_IsoAspect.hxx>
+#include <Select3D_SensitiveWire.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <StdSelect_BRepOwner.hxx>
+#include <StdSelect_ViewerSelector3d.hxx>
+#include <Select3D_Projector.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <ViewerTest_AutoUpdater.hxx>
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
 #include <stdio.h>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
 
 #include <Draw_Interpretor.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <Draw_PluginMacro.hxx>
-#include <ViewerTest.hxx>
 
 // avoid warnings on 'extern "C"' functions returning C++ classes
 #ifdef WNT
@@ -90,34 +92,6 @@ extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
 #define DEFAULT_COLOR    Quantity_NOC_GOLDENROD
 #define DEFAULT_MATERIAL Graphic3d_NOM_BRASS
 
-enum ViewerTest_RedrawMode
-{
-  ViewerTest_RM_Auto = -1,
-  ViewerTest_RM_RedrawForce,
-  ViewerTest_RM_RedrawSuppress
-};
-
-//! Auxiliary method to parse redraw mode argument
-static Standard_Boolean parseRedrawMode (const TCollection_AsciiString& theArg,
-                                         ViewerTest_RedrawMode&         theMode)
-{
-  TCollection_AsciiString anArgCase (theArg);
-  anArgCase.LowerCase();
-  if (anArgCase == "-update"
-   || anArgCase == "-redraw")
-  {
-    theMode = ViewerTest_RM_RedrawForce;
-    return Standard_True;
-  }
-  else if (anArgCase == "-noupdate"
-        || anArgCase == "-noredraw")
-  {
-    theMode = ViewerTest_RM_RedrawSuppress;
-    return Standard_True;
-  }
-  return Standard_False;
-}
-
 //=======================================================================
 //function : GetColorFromName
 //purpose  : get the Quantity_NameOfColor from a string
@@ -125,16 +99,9 @@ static Standard_Boolean parseRedrawMode (const TCollection_AsciiString& theArg,
 
 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
 {
-  for (Standard_Integer anIter = Quantity_NOC_BLACK; anIter <= Quantity_NOC_WHITE; ++anIter)
-  {
-    Standard_CString aColorName = Quantity_Color::StringName (Quantity_NameOfColor (anIter));
-    if (strcasecmp (theName, aColorName) == 0)
-    {
-      return Quantity_NameOfColor (anIter);
-    }
-  }
-
-  return DEFAULT_COLOR;
+  Quantity_NameOfColor aColor = DEFAULT_COLOR;
+  Quantity_Color::ColorFromName (theName, aColor);
+  return aColor;
 }
 
 //=======================================================================
@@ -1319,17 +1286,17 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI,
                               const char**      theArgVec)
 {
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cerr << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  Standard_Integer      anArgIter = 1;
+  Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
     {
       break;
     }
@@ -1403,15 +1370,6 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI,
       aCtx->RecomputePrsOnly (anIO, Standard_False, Standard_True);
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
   return 0;
 }
 
@@ -1496,19 +1454,19 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
 {
   TCollection_AsciiString aCmdName (theArgVec[0]);
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cerr << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  Standard_Integer      anArgIter = 1;
+  Standard_Integer anArgIter = 1;
   NCollection_Sequence<TCollection_AsciiString> aNames;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
     TCollection_AsciiString anArg = theArgVec[anArgIter];
-    if (parseRedrawMode (anArg, aToUpdate))
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
       continue;
     }
@@ -1552,8 +1510,50 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
       return 1;
     }
     aChangeSet->ToSetColor = 1;
-    aChangeSet->Color  = ViewerTest::GetColorFromName (aNames.Last().ToCString());
-    aNames.Remove (aNames.Length());
+
+    Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
+    Standard_Boolean     isOk   = Standard_False;
+    if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
+    {
+      aChangeSet->Color = aColor;
+      aNames.Remove (aNames.Length());
+      isOk = Standard_True;
+    }
+    else if (aNames.Length() >= 3)
+    {
+      const TCollection_AsciiString anRgbStr[3] =
+      {
+        aNames.Value (aNames.Upper() - 2),
+        aNames.Value (aNames.Upper() - 1),
+        aNames.Value (aNames.Upper() - 0)
+      };
+      isOk = anRgbStr[0].IsRealValue()
+          && anRgbStr[1].IsRealValue()
+          && anRgbStr[2].IsRealValue();
+      if (isOk)
+      {
+        Graphic3d_Vec4d anRgb;
+        anRgb.x() = anRgbStr[0].RealValue();
+        anRgb.y() = anRgbStr[1].RealValue();
+        anRgb.z() = anRgbStr[2].RealValue();
+        if (anRgb.x() < 0.0 || anRgb.x() > 1.0
+         || anRgb.y() < 0.0 || anRgb.y() > 1.0
+         || anRgb.z() < 0.0 || anRgb.z() > 1.0)
+        {
+          std::cout << "Error: RGB color values should be within range 0..1!\n";
+          return 1;
+        }
+        aChangeSet->Color.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
+        aNames.Remove (aNames.Length());
+        aNames.Remove (aNames.Length());
+        aNames.Remove (aNames.Length());
+      }
+    }
+    if (!isOk)
+    {
+      std::cout << "Error: not enough arguments!\n";
+      return 1;
+    }
   }
   else if (aCmdName == "vunsetcolor")
   {
@@ -1672,13 +1672,53 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
     }
     else if (anArg == "-setcolor")
     {
-      if (++anArgIter >= theArgNb)
+      Standard_Integer aNbComps  = 0;
+      Standard_Integer aCompIter = anArgIter + 1;
+      for (; aCompIter < theArgNb; ++aCompIter, ++aNbComps)
       {
-        std::cout << "Error: wrong syntax at " << anArg << "\n";
-        return 1;
+        if (theArgVec[aCompIter][0] == '-')
+        {
+          break;
+        }
+      }
+      switch (aNbComps)
+      {
+        case 1:
+        {
+          Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
+          Standard_CString     aName  = theArgVec[anArgIter + 1];
+          if (!Quantity_Color::ColorFromName (aName, aColor))
+          {
+            std::cout << "Error: unknown color name '" << aName << "'\n";
+            return 1;
+          }
+          aChangeSet->Color = aColor;
+          break;
+        }
+        case 3:
+        {
+          Graphic3d_Vec3d anRgb;
+          anRgb.x() = Draw::Atof (theArgVec[anArgIter + 1]);
+          anRgb.y() = Draw::Atof (theArgVec[anArgIter + 2]);
+          anRgb.z() = Draw::Atof (theArgVec[anArgIter + 3]);
+          if (anRgb.x() < 0.0 || anRgb.x() > 1.0
+           || anRgb.y() < 0.0 || anRgb.y() > 1.0
+           || anRgb.z() < 0.0 || anRgb.z() > 1.0)
+          {
+            std::cout << "Error: RGB color values should be within range 0..1!\n";
+            return 1;
+          }
+          aChangeSet->Color.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
+          break;
+        }
+        default:
+        {
+          std::cout << "Error: wrong syntax at " << anArg << "\n";
+          return 1;
+        }
       }
       aChangeSet->ToSetColor = 1;
-      aChangeSet->Color = ViewerTest::GetColorFromName (theArgVec[anArgIter]);
+      anArgIter += aNbComps;
     }
     else if (anArg == "-unsetcolor")
     {
@@ -1891,15 +1931,6 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
       }
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
   return 0;
 }
 
@@ -1914,6 +1945,7 @@ static int VDonly2 (Draw_Interpretor& ,
                     const char**      theArgVec)
 {
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cerr << "Error: no active view!\n";
@@ -1924,12 +1956,11 @@ static int VDonly2 (Draw_Interpretor& ,
   {
     aCtx->CloseLocalContext();
   }
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
     {
       break;
     }
@@ -1992,16 +2023,6 @@ static int VDonly2 (Draw_Interpretor& ,
       TheNISContext()->Erase (aShape);
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2017,18 +2038,18 @@ int VRemove (Draw_Interpretor& theDI,
              Standard_Integer  theArgNb,
              const char**      theArgVec)
 {
-  if (a3DView().IsNull())
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  if (aCtx.IsNull())
   {
-    std::cout << "Error: wrong syntax!\n";
+    std::cerr << "Error: no active view!\n";
     return 1;
   }
 
-  TheAISContext()->CloseAllContexts (Standard_False);
-
-  ViewerTest_RedrawMode aToUpdate     = ViewerTest_RM_Auto;
-  Standard_Boolean      isContextOnly = Standard_False;
-  Standard_Boolean      toRemoveAll   = Standard_False;
-  Standard_Boolean      toPrintInfo   = Standard_True;
+  Standard_Boolean isContextOnly = Standard_False;
+  Standard_Boolean toRemoveAll   = Standard_False;
+  Standard_Boolean toPrintInfo   = Standard_True;
+  Standard_Boolean toRemoveLocal = Standard_False;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
@@ -2047,7 +2068,15 @@ int VRemove (Draw_Interpretor& theDI,
     {
       toPrintInfo = Standard_False;
     }
-    else if (!parseRedrawMode (anArg, aToUpdate))
+    else if (anArg == "-local")
+    {
+      toRemoveLocal = Standard_True;
+    }
+    else if (anUpdateTool.parseRedrawMode (anArg))
+    {
+      continue;
+    }
+    else
     {
       break;
     }
@@ -2055,10 +2084,20 @@ int VRemove (Draw_Interpretor& theDI,
   if (toRemoveAll
    && anArgIter < theArgNb)
   {
-    std::cout << "Error: wrong syntax!\n";
+    std::cerr << "Error: wrong syntax!\n";
     return 1;
   }
 
+  if (toRemoveLocal && !aCtx->HasOpenedContext())
+  {
+    std::cerr << "Error: local selection context is not open.\n";
+    return 1;
+  }
+  else if (!toRemoveLocal && aCtx->HasOpenedContext())
+  {
+    aCtx->CloseAllContexts (Standard_False);
+  }
+
   NCollection_List<TCollection_AsciiString> anIONameList;
   if (toRemoveAll)
   {
@@ -2084,7 +2123,7 @@ int VRemove (Draw_Interpretor& theDI,
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (aTransientObj);
       if (!anIO.IsNull())
       {
-        if (anIO->GetContext() != TheAISContext())
+        if (anIO->GetContext() != aCtx)
         {
           theDI << aName.ToCString() << " was not displayed in current context.\n";
           theDI << "Please activate view with this object displayed and try again.\n";
@@ -2102,7 +2141,7 @@ int VRemove (Draw_Interpretor& theDI,
       }
     }
   }
-  else if (TheAISContext()->NbCurrents() > 0
+  else if (aCtx->NbCurrents() > 0
         || TheNISContext()->GetSelected().Extent() > 0)
   {
     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
@@ -2111,7 +2150,7 @@ int VRemove (Draw_Interpretor& theDI,
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
       if (!anIO.IsNull())
       {
-        if (!TheAISContext()->IsCurrent (anIO))
+        if (!aCtx->IsCurrent (anIO))
         {
           continue;
         }
@@ -2140,7 +2179,7 @@ int VRemove (Draw_Interpretor& theDI,
     const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value()));
     if (!anIO.IsNull())
     {
-      TheAISContext()->Remove (anIO, Standard_False);
+      aCtx->Remove (anIO, Standard_False);
       if (toPrintInfo)
       {
         theDI << anIter.Value().ToCString() << " was removed\n";
@@ -2164,13 +2203,12 @@ int VRemove (Draw_Interpretor& theDI,
     }
   }
 
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
+  // Close local context if it is empty
+  TColStd_MapOfTransient aLocalIO;
+  if (aCtx->HasOpenedContext()
+   && !aCtx->LocalContext()->DisplayedObjects (aLocalIO))
   {
-    TheAISContext()->UpdateCurrentViewer();
+    aCtx->CloseAllContexts (Standard_False);
   }
 
   return 0;
@@ -2185,37 +2223,59 @@ int VErase (Draw_Interpretor& theDI,
             Standard_Integer  theArgNb,
             const char**      theArgVec)
 {
-  if (a3DView().IsNull())
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  if (aCtx.IsNull())
   {
-    std::cout << "Error: no active view!\n";
+    std::cerr << "Error: no active view!\n";
     return 1;
   }
-  TheAISContext()->CloseAllContexts (Standard_False);
 
-  ViewerTest_RedrawMode  aToUpdate  = ViewerTest_RM_Auto;
   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
 
   Standard_Integer anArgIter = 1;
+  Standard_Boolean toEraseLocal = Standard_False;
+  TColStd_SequenceOfAsciiString aNamesOfEraseIO;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
+    anArgCase.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArgCase))
     {
-      break;
+      continue;
+    }
+    else if (anArgCase == "-local")
+    {
+      toEraseLocal = Standard_True;
+    }
+    else
+    {
+      aNamesOfEraseIO.Append (theArgVec[anArgIter]);
     }
   }
 
-  if (anArgIter < theArgNb)
+  if (!aNamesOfEraseIO.IsEmpty() && toEraseAll)
   {
-    if (toEraseAll)
-    {
-      std::cerr << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.\n";
-      return 1;
-    }
+    std::cerr << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.\n";
+    return 1;
+  }
 
-    // has a list of names
-    for (; anArgIter < theArgNb; ++anArgIter)
+  if (toEraseLocal && !aCtx->HasOpenedContext())
+  {
+    std::cerr << "Error: local selection context is not open.\n";
+    return 1;
+  }
+  else if (!toEraseLocal && aCtx->HasOpenedContext())
+  {
+    aCtx->CloseAllContexts (Standard_False);
+  }
+
+  if (!aNamesOfEraseIO.IsEmpty())
+  {
+    // Erase named objects
+    for (Standard_Integer anIter = 1; anIter <= aNamesOfEraseIO.Length(); ++anIter)
     {
-      TCollection_AsciiString aName = theArgVec[anArgIter];
+      TCollection_AsciiString aName = aNamesOfEraseIO.Value (anIter);
       if (!GetMapOfAIS().IsBound2 (aName))
       {
         continue;
@@ -2226,7 +2286,7 @@ int VErase (Draw_Interpretor& theDI,
       theDI << aName.ToCString() << " ";
       if (!anIO.IsNull())
       {
-        TheAISContext()->Erase (anIO, Standard_False);
+        aCtx->Erase (anIO, Standard_False);
       }
       else
       {
@@ -2238,32 +2298,31 @@ int VErase (Draw_Interpretor& theDI,
       }
     }
   }
-  else if (!toEraseAll
-        && TheAISContext()->NbCurrents() > 0)
+  else if (!toEraseAll && aCtx->NbCurrents() > 0)
   {
-    // remove all currently selected objects
+    // Erase selected objects
     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
          anIter.More(); anIter.Next())
     {
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
       if (!anIO.IsNull()
-       && TheAISContext()->IsCurrent (anIO))
+       && aCtx->IsCurrent (anIO))
       {
         theDI << anIter.Key2().ToCString() << " ";
-        TheAISContext()->Erase (anIO, Standard_False);
+        aCtx->Erase (anIO, Standard_False);
       }
     }
   }
   else
   {
-    // erase entire viewer
+    // Erase all objects
     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
          anIter.More(); anIter.Next())
     {
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
       if (!anIO.IsNull())
       {
-        TheAISContext()->Erase (anIO, Standard_False);
+        aCtx->Erase (anIO, Standard_False);
       }
       else
       {
@@ -2276,15 +2335,6 @@ int VErase (Draw_Interpretor& theDI,
     }
   }
 
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2298,18 +2348,29 @@ static int VDisplayAll (Draw_Interpretor& ,
                         const char**      theArgVec)
 
 {
-  if (a3DView().IsNull())
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  if (aCtx.IsNull())
   {
-    std::cout << "Error: no active view!\n";
+    std::cerr << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-
   Standard_Integer anArgIter = 1;
+  Standard_Boolean toDisplayLocal = Standard_False;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
+    anArgCase.LowerCase();
+    if (anArgCase == "-local")
+    {
+      toDisplayLocal = Standard_True;
+    }
+    else if (anUpdateTool.parseRedrawMode (anArgCase))
+    {
+      continue;
+    }
+    else
     {
       break;
     }
@@ -2320,9 +2381,14 @@ static int VDisplayAll (Draw_Interpretor& ,
     return 1;
   }
 
-  if (TheAISContext()->HasOpenedContext())
+  if (toDisplayLocal && !aCtx->HasOpenedContext())
   {
-    TheAISContext()->CloseLocalContext();
+    std::cerr << "Error: local selection context is not open.\n";
+    return 1;
+  }
+  else if (!toDisplayLocal && aCtx->HasOpenedContext())
+  {
+    aCtx->CloseLocalContext (Standard_False);
   }
 
   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
@@ -2331,7 +2397,7 @@ static int VDisplayAll (Draw_Interpretor& ,
     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
     {
       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
-      TheAISContext()->Erase (aShape, Standard_False);
+      aCtx->Erase (aShape, Standard_False);
     }
     else if (anIter.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject)))
     {
@@ -2346,7 +2412,7 @@ static int VDisplayAll (Draw_Interpretor& ,
     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
     {
       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
-      TheAISContext()->Display (aShape, Standard_False);
+      aCtx->Display (aShape, Standard_False);
     }
     else if (anIter.Key1()->IsKind (STANDARD_TYPE(NIS_InteractiveObject)))
     {
@@ -2354,16 +2420,6 @@ static int VDisplayAll (Draw_Interpretor& ,
       TheNISContext()->Display (aShape);
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2442,15 +2498,15 @@ int VBounding (Draw_Interpretor& theDI,
                const char**      theArgVec)
 {
   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cout << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  ViewerTest_BndAction  anAction  = BndAction_Show;
-  Standard_Integer      aMode     = -1;
+  ViewerTest_BndAction anAction = BndAction_Show;
+  Standard_Integer     aMode    = -1;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
@@ -2478,7 +2534,7 @@ int VBounding (Draw_Interpretor& theDI,
       }
       aMode = Draw::Atoi (theArgVec[anArgIter]);
     }
-    else if (!parseRedrawMode (anArg, aToUpdate))
+    else if (!anUpdateTool.parseRedrawMode (anArg))
     {
       break;
     }
@@ -2506,7 +2562,7 @@ int VBounding (Draw_Interpretor& theDI,
       bndPresentation (theDI, aPrs, aName, anAction);
     }
   }
-  else if (TheAISContext()->NbCurrents() > 0)
+  else if (aCtx->NbCurrents() > 0)
   {
     // remove all currently selected objects
     for (aCtx->InitCurrent(); aCtx->MoreCurrent(); aCtx->NextCurrent())
@@ -2533,16 +2589,6 @@ int VBounding (Draw_Interpretor& theDI,
       }
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2846,39 +2892,67 @@ static int VDisplay2 (Draw_Interpretor& theDI,
 {
   if (theArgNb < 2)
   {
-    std::cout << theArgVec[0] << "Error: wrong syntax!\n";
+    std::cerr << theArgVec[0] << "Error: wrong number of arguments.\n";
     return 1;
   }
-  else if (a3DView().IsNull())
-  {
-    ViewerTest::ViewerInit();
-    std::cout << "Command vinit should be called before!\n";
-    // return 1;
-  }
 
-  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
-  if (aCtx->HasOpenedContext())
+  Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  if (aCtx.IsNull())
   {
-    aCtx->CloseLocalContext();
+    ViewerTest::ViewerInit();
+    aCtx = ViewerTest::GetAISContext();
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  Standard_Integer      isMutable = -1;
+  // Parse input arguments
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  Standard_Integer isMutable = -1;
+  Standard_Boolean toDisplayLocal = Standard_False;
+  TColStd_SequenceOfAsciiString aNamesOfDisplayIO;
   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
     const TCollection_AsciiString aName     = theArgVec[anArgIter];
     TCollection_AsciiString       aNameCase = aName;
     aNameCase.LowerCase();
-    if (parseRedrawMode (aName, aToUpdate))
+    if (anUpdateTool.parseRedrawMode (aName))
     {
       continue;
     }
     else if (aNameCase == "-mutable")
     {
       isMutable = 1;
-      continue;
     }
-    else if (!GetMapOfAIS().IsBound2 (aName))
+    else if (aNameCase == "-local")
+    {
+      toDisplayLocal = Standard_True;
+    }
+    else
+    {
+      aNamesOfDisplayIO.Append (aName);
+    }
+  }
+
+  if (aNamesOfDisplayIO.IsEmpty())
+  {
+    std::cerr << theArgVec[0] << "Error: wrong number of arguments.\n";
+    return 1;
+  }
+
+  // Prepare context for display
+  if (toDisplayLocal && !aCtx->HasOpenedContext())
+  {
+    aCtx->OpenLocalContext (Standard_False);
+  }
+  else if (!toDisplayLocal && aCtx->HasOpenedContext())
+  {
+    aCtx->CloseAllContexts (Standard_False);
+  }
+
+  // Display interactive objects
+  for (Standard_Integer anIter = 1; anIter <= aNamesOfDisplayIO.Length(); ++anIter)
+  {
+    const TCollection_AsciiString& aName = aNamesOfDisplayIO.Value(anIter);
+
+    if (!GetMapOfAIS().IsBound2 (aName))
     {
       // create the AIS_Shape from a name
       const Handle(AIS_InteractiveObject) aShape = GetAISShapeFromName (aName.ToCString());
@@ -2930,14 +3004,6 @@ static int VDisplay2 (Draw_Interpretor& theDI,
     }
   }
 
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    // update the screen and redraw the view
-    aCtx->UpdateCurrentViewer();
-  }
   return 0;
 }
 
@@ -3154,11 +3220,11 @@ static int VAnimation (Draw_Interpretor& di, Standard_Integer argc, const char**
     TheAISContext()->UpdateCurrentViewer();
   }
 
-  TopoDS_Shape myNewCrankArm  =myAisCrankArm ->Shape().Located( myAisCrankArm ->Location() );
-  TopoDS_Shape myNewPropeller =myAisPropeller->Shape().Located( myAisPropeller->Location() );
+  TopoDS_Shape myNewCrankArm  =myAisCrankArm ->Shape().Located( myAisCrankArm ->Transformation() );
+  TopoDS_Shape myNewPropeller =myAisPropeller->Shape().Located( myAisPropeller->Transformation() );
 
-  myAisCrankArm ->ResetLocation();
-  myAisPropeller->ResetLocation();
+  myAisCrankArm ->ResetTransformation();
+  myAisPropeller->ResetTransformation();
 
   myAisCrankArm  -> Set(myNewCrankArm );
   myAisPropeller -> Set(myNewPropeller);
@@ -3566,7 +3632,6 @@ static void localCtxInfo (Draw_Interpretor& theDI)
 //==============================================================================
 //function : VState
 //purpose  :
-//Draw arg : vstate [nameA] ... [nameN]
 //==============================================================================
 static Standard_Integer VState (Draw_Interpretor& theDI,
                                 Standard_Integer  theArgNb,
@@ -3579,6 +3644,55 @@ static Standard_Integer VState (Draw_Interpretor& theDI,
     return 1;
   }
 
+  TCollection_AsciiString anOption (theArgNb >= 2 ? theArgVec[1] : "");
+  anOption.LowerCase();
+  if (anOption == "-detectedEntities"
+   || anOption == "-entities")
+  {
+    theDI << "Detected entities:\n";
+    Handle(StdSelect_ViewerSelector3d) aSelector = aCtx->HasOpenedContext() ? aCtx->LocalSelector() : aCtx->MainSelector();
+    for (aSelector->Init(); aSelector->More(); aSelector->Next())
+    {
+      Handle(SelectBasics_SensitiveEntity) anEntity = aSelector->Primitive (0);
+      Standard_Real aMatchDMin  = 0.0;
+      Standard_Real aMatchDepth = Precision::Infinite();
+      anEntity->Matches (aSelector->LastPickingArguments(), aMatchDMin, aMatchDepth);
+
+      Handle(SelectMgr_EntityOwner) anOwner    = Handle(SelectMgr_EntityOwner)::DownCast (anEntity->OwnerId());
+      Handle(AIS_InteractiveObject) anObj      = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
+
+      const gp_Lin aLine = aSelector->LastPickingArguments().PickLine();
+      const gp_Pnt aPnt  = aLine.Location().Translated (gp_Vec (aLine.Direction()) * aMatchDepth);
+
+      TCollection_AsciiString aName = GetMapOfAIS().Find1 (anObj);
+      aName.LeftJustify (20, ' ');
+      char anInfoStr[512];
+      Sprintf (anInfoStr, " Depth: %+.3f Distance: %+.3f Point: %+.3f %+.3f %+.3f", aMatchDepth, aMatchDMin, aPnt.X(), aPnt.Y(), aPnt.Z());
+      theDI << "  " << aName
+            << anInfoStr
+            << " (" << anEntity->DynamicType()->Name() << ")"
+            << "\n";
+
+      Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast (anOwner);
+      if (!aBRepOwner.IsNull())
+      {
+        theDI << "                       Detected Shape: "
+              << aBRepOwner->Shape().TShape()->DynamicType()->Name()
+              << "\n";
+      }
+
+      Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast (anEntity);
+      if (!aWire.IsNull())
+      {
+        Handle(Select3D_SensitiveEntity) aSen = aWire->GetLastDetected();
+        theDI << "                       Detected Child: "
+              << aSen->DynamicType()->Name()
+              << "\n";
+      }
+    }
+    return 0;
+  }
+
   NCollection_Map<Handle(AIS_InteractiveObject)> aDetected;
   for (aCtx->InitDetected(); aCtx->MoreDetected(); aCtx->NextDetected())
   {
@@ -4240,16 +4354,19 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
 
   // display
   theCommands.Add("visos",
-                  "visos [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]\n"
-                  "\tIf last 3 optional parameters are not set prints numbers of U-, V- isolines and IsoOnPlane.\n",
-                 __FILE__, visos, group);
+      "visos [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]\n"
+      "\tIf last 3 optional parameters are not set prints numbers of U-, V- isolines and IsoOnPlane.\n",
+      __FILE__, visos, group);
 
   theCommands.Add("vdisplay",
-                 "vdisplay [-noupdate|-update] [-mutable] name1 [name2] ... [name n]"
+      "vdisplay [-noupdate|-update] [-local] [-mutable] name1 [name2] ... [name n]"
       "\n\t\t: Displays named objects."
+      "\n\t\t: Option -local enables displaying of objects in local"
+      "\n\t\t: selection context. Local selection context will be opened"
+      "\n\t\t: if there is not any."
       "\n\t\t: Option -noupdate suppresses viewer redraw call."
-      "\n\t\t: Option -mutable enables optimizations for mutable objects."
-                 __FILE__,VDisplay2,group);
+      "\n\t\t: Option -mutable enables optimizations for mutable objects.",
+      __FILE__, VDisplay2, group);
 
   theCommands.Add ("vupdate",
       "vupdate name1 [name2] ... [name n]"
@@ -4257,17 +4374,22 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
       __FILE__, VUpdate, group);
 
   theCommands.Add("verase",
-      "verase [-noupdate|-update] [name1] ...  [name n]"
+      "verase [-noupdate|-update] [-local] [name1] ...  [name n]"
       "\n\t\t: Erases selected or named objects."
-      "\n\t\t: If there are no selected or named objects the whole viewer is erased.",
-                 __FILE__, VErase, group);
+      "\n\t\t: If there are no selected or named objects the whole viewer is erased."
+      "\n\t\t: Option -local enables erasing of selected or named objects without"
+      "\n\t\t: closing local selection context.",
+      __FILE__, VErase, group);
 
   theCommands.Add("vremove",
-    "vremove [-noupdate|-update] [-context] [-all] [-noinfo] [name1] ...  [name n]"
-    "or vremove [-context] -all to remove all objects"
+      "vremove [-noupdate|-update] [-context] [-all] [-noinfo] [name1] ...  [name n]"
+      "or vremove [-context] -all to remove all objects"
       "\n\t\t: Removes selected or named objects."
       "\n\t\t  If -context is in arguments, the objects are not deleted"
       "\n\t\t  from the map of objects and names."
+      "\n\t\t: Option -local enables removing of selected or named objects without"
+      "\n\t\t: closing local selection context. Empty local selection context will be"
+      "\n\t\t: closed."
       "\n\t\t: Option -noupdate suppresses viewer redraw call."
       "\n\t\t: Option -noinfo suppresses displaying the list of removed objects.",
       __FILE__, VRemove, group);
@@ -4278,18 +4400,23 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
                  __FILE__,VDonly2,group);
 
   theCommands.Add("vdisplayall",
-                 "Displays all erased interactive objects (see vdir and vstate)",
-                 __FILE__,VDisplayAll,group);
+      "vidsplayall [-local]"
+      "\n\t\t: Displays all erased interactive objects (see vdir and vstate)."
+      "\n\t\t: Option -local enables displaying of the objects in local"
+      "\n\t\t: selection context.",
+      __FILE__, VDisplayAll, group);
 
   theCommands.Add("veraseall",
-                 "Erases all objects displayed in the viewer",
-                 __FILE__, VErase, group);
+      "veraseall [-local]"
+      "\n\t\t: Erases all objects displayed in the viewer."
+      "\n\t\t: Option -local enables erasing of the objects in local"
+      "\n\t\t: selection context.",
+      __FILE__, VErase, group);
 
   theCommands.Add("verasetype",
-                 "verasetype <Type>"
+      "verasetype <Type>"
       "\n\t\t: Erase all the displayed objects of one given kind (see vtypes)",
-                 __FILE__,VEraseType,group);
-
+      __FILE__, VEraseType, group);
   theCommands.Add("vbounding",
               "vbounding [-noupdate|-update] [-mode] name1 [name2 [...]]"
       "\n\t\t:           [-print] [-hide]"
@@ -4341,7 +4468,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
 
   theCommands.Add("vaspects",
               "vaspects [-noupdate|-update] [name1 [name2 [...]]]"
-      "\n\t\t:          [-setcolor ColorName] [-unsetcolor]"
+      "\n\t\t:          [-setcolor ColorName] [-setcolor R G B] [-unsetcolor]"
       "\n\t\t:          [-setmaterial MatName] [-unsetmaterial]"
       "\n\t\t:          [-settransparency Transp] [-unsettransparency]"
       "\n\t\t:          [-setwidth LineWidth] [-unsetwidth]"
@@ -4489,8 +4616,9 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands)
                  __FILE__,VActivatedMode,group);
 
   theCommands.Add("vstate",
-      "vstate [name1] ... [nameN]"
-      "\n\t\t: Reports show/hidden state for selected or named objects",
+      "vstate [-entities] [name1] ... [nameN]"
+      "\n\t\t: Reports show/hidden state for selected or named objects"
+      "\n\t\t:   -entities - print low-level information about detected entities",
                  __FILE__,VState,group);
 
   theCommands.Add("vpickshapes",