0028895: Visualization, V3d_View::SetComputedMode() - HLR calculation is performed...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
index bd57553..20b1ed0 100644 (file)
 // commercial license or contractual agreement.
 
 #include <OpenGl_GlCore20.hxx>
+
+#include <AIS_Animation.hxx>
+#include <AIS_AnimationCamera.hxx>
+#include <AIS_AnimationObject.hxx>
 #include <AIS_ColorScale.hxx>
 #include <AIS_Manipulator.hxx>
 #include <AIS_RubberBand.hxx>
@@ -159,8 +163,6 @@ Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
 }
 #endif
 
-static Standard_Boolean MyHLRIsOn = Standard_False;
-
 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
@@ -181,12 +183,14 @@ static struct
 //==============================================================================
 
 static int Start_Rot = 0;
+Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
 int X_Motion = 0; // Current cursor position
 int Y_Motion = 0;
 int X_ButtonPress = 0; // Last ButtonPress position
 int Y_ButtonPress = 0;
 Standard_Boolean IsDragged = Standard_False;
 Standard_Boolean DragFirst = Standard_False;
+Standard_Boolean TheIsAnimating = Standard_False;
 
 
 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
@@ -242,15 +246,15 @@ static LRESULT WINAPI AdvViewerWindowProc(
 //purpose  :
 //==============================================================================
 
-const Handle(MMgt_TShared)& ViewerTest::WClass()
+const Handle(Standard_Transient)& ViewerTest::WClass()
 {
-  static Handle(MMgt_TShared) theWClass;
+  static Handle(Standard_Transient) theWClass;
 #if defined(_WIN32)
   if (theWClass.IsNull())
   {
     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
-      CS_VREDRAW | CS_HREDRAW, 0, 0,
-      ::LoadCursor (NULL, IDC_ARROW));
+                                CS_VREDRAW | CS_HREDRAW, 0, 0,
+                                ::LoadCursorW (NULL, IDC_ARROW));
   }
 #endif
   return theWClass;
@@ -346,10 +350,11 @@ public:
           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
       }
       else
+      {
         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
+      }
 
-        myViewName = CreateName <Handle(V3d_View)>
-          (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
+      myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
     }
     else
     {
@@ -446,8 +451,8 @@ void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
                      Standard_CString theTitle)
 {
 #if defined(_WIN32)
-  SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
-    theTitle);
+  const TCollection_ExtendedString theTitleW (theTitle);
+  SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
 #else
@@ -711,7 +716,6 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   // Set parameters for V3d_View and V3d_Viewer
   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
   aV3dView->SetComputedMode(Standard_False);
-  MyHLRIsOn = aV3dView->ComputedMode();
 
   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
   if (toCreateViewer)
@@ -844,76 +848,142 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
   return 0;
 }
 
+//! Parse HLR algo type.
+static Standard_Boolean parseHlrAlgoType (const char* theName,
+                                          Prs3d_TypeOfHLR& theType)
+{
+  TCollection_AsciiString aName (theName);
+  aName.LowerCase();
+  if (aName == "polyalgo")
+  {
+    theType = Prs3d_TOH_PolyAlgo;
+  }
+  else if (aName == "algo")
+  {
+    theType = Prs3d_TOH_Algo;
+  }
+  else
+  {
+    return Standard_False;
+  }
+  return Standard_True;
+}
+
 //==============================================================================
 //function : VHLR
 //purpose  : hidden lines removal algorithm
-//draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
 //==============================================================================
 
 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
 {
-  if (ViewerTest::CurrentView().IsNull())
+  const Handle(V3d_View) aView = ViewerTest::CurrentView();
+  const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  if (aView.IsNull())
   {
-    di << argv[0] << ": Call vinit before this command, please.\n";
+    std::cerr << "Error: No opened viewer!\n";
     return 1;
   }
 
-  if (argc < 2)
+  Standard_Boolean hasHlrOnArg = Standard_False;
+  Standard_Boolean hasShowHiddenArg = Standard_False;
+  Standard_Boolean isHLROn = Standard_False;
+  Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
+  Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
+  ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
   {
-    di << argv[0] << ": Wrong number of command arguments.\n"
-      << "Type help " << argv[0] << " for more information.\n";
-    return 1;
+    TCollection_AsciiString anArg (argv[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
+    {
+      continue;
+    }
+    else if (anArg == "-showhidden"
+          && anArgIter + 1 < argc
+          && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
+    {
+      ++anArgIter;
+      hasShowHiddenArg = Standard_True;
+      continue;
+    }
+    else if ((anArg == "-type"
+           || anArg == "-algo"
+           || anArg == "-algotype")
+          && anArgIter + 1 < argc
+          && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
+    {
+      ++anArgIter;
+      continue;
+    }
+    else if (!hasHlrOnArg
+          && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
+    {
+      hasHlrOnArg = Standard_True;
+      continue;
+    }
+    // old syntax
+    else if (!hasShowHiddenArg
+          && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
+    {
+      hasShowHiddenArg = Standard_True;
+      continue;
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
+      return 1;
+    }
   }
-
-  // Enable or disable HLR mode.
-  Standard_Boolean isHLROn =
-    (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
-
-  if (isHLROn != MyHLRIsOn)
+  if (!hasHlrOnArg)
   {
-    MyHLRIsOn = isHLROn;
-    ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
+    di << "HLR:        " << aView->ComputedMode() << "\n";
+    di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
+    di << "HlrAlgo:    ";
+    switch (aCtx->DefaultDrawer()->TypeOfHLR())
+    {
+      case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
+      case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
+      case Prs3d_TOH_Algo:     di << "Algo\n";     break;
+    }
+    anUpdateTool.Invalidate();
+    return 0;
   }
 
-  // Show or hide hidden lines in HLR mode.
-  Standard_Boolean isCurrentShowHidden
-    = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
-
-  Standard_Boolean isShowHidden =
-    (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
-                : isCurrentShowHidden;
-
-
-  if (isShowHidden != isCurrentShowHidden)
+  Standard_Boolean toRecompute = Standard_False;
+  if (aTypeOfHLR != Prs3d_TOH_NotSet
+   && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
   {
-    if (isShowHidden)
+    toRecompute = Standard_True;
+    aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
+  }
+  if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
+  {
+    toRecompute = Standard_True;
+    if (toShowHidden)
     {
-      ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
+      aCtx->DefaultDrawer()->EnableDrawHiddenLine();
     }
     else
     {
-      ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
+      aCtx->DefaultDrawer()->DisableDrawHiddenLine();
     }
+  }
 
-    // Redisplay shapes.
-    if (MyHLRIsOn)
+  // redisplay shapes
+  if (aView->ComputedMode() && isHLROn && toRecompute)
+  {
+    AIS_ListOfInteractive aListOfShapes;
+    aCtx->DisplayedObjects (aListOfShapes);
+    for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
     {
-      AIS_ListOfInteractive aListOfShapes;
-      ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
-
-      for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
+      if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
       {
-        Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
-        if (aShape.IsNull())
-        {
-          continue;
-        }
-        ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
+        aCtx->Redisplay (aShape, Standard_False);
       }
     }
   }
 
-  ViewerTest::CurrentView()->Update();
+  aView->SetComputedMode (isHLROn);
   return 0;
 }
 
@@ -922,66 +992,95 @@ static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
 //purpose  : change type of using HLR algorithm
 //==============================================================================
 
-static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
 {
-  if (ViewerTest::CurrentView().IsNull())
-  {
-    di << argv[0] << ": Call vinit before this command, please.\n";
-    return 1;
-  }
-
-  if (argc < 2)
+  const Handle(V3d_View) aView = ViewerTest::CurrentView();
+  const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  if (aView.IsNull())
   {
-    di << argv[0] << ": Wrong number of command arguments.\n"
-      << "Type help " << argv[0] << " for more information.\n";
+    std::cerr << "Error: No opened viewer!\n";
     return 1;
   }
 
-  Prs3d_TypeOfHLR aTypeOfHLR =
-    (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
-
-  if (argc == 2)
+  Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
+  ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
+  AIS_ListOfInteractive aListOfShapes;
+  for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
   {
-    AIS_ListOfInteractive aListOfShapes;
-    ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
-    ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
-    for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
-      anIter.More(); anIter.Next())
+    TCollection_AsciiString anArg (argv[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
-      if (aShape.IsNull())
-        continue;
-      if (aShape->TypeOfHLR() != aTypeOfHLR)
-        aShape->SetTypeOfHLR (aTypeOfHLR);
-      if (MyHLRIsOn)
-        ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
+      continue;
     }
-    ViewerTest::CurrentView()->Update();
-    return 0;
-  }
-  else
-  {
-    for (Standard_Integer i = 2; i < argc; ++i)
+    else if ((anArg == "-type"
+           || anArg == "-algo"
+           || anArg == "-algotype")
+          && anArgIter + 1 < argc
+          && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
+    {
+      ++anArgIter;
+      continue;
+    }
+    // old syntax
+    else if (aTypeOfHLR == Prs3d_TOH_NotSet
+          && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
+    {
+      continue;
+    }
+    else
     {
       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
-      TCollection_AsciiString aName (argv[i]);
-
+      TCollection_AsciiString aName (argv[anArgIter]);
       if (!aMap.IsBound2 (aName))
       {
-        di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
-        continue;
+        std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
+        return 1;
       }
-      Handle(AIS_Shape) anAISObject =
-        Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
-      if (anAISObject.IsNull())
-        continue;
-      anAISObject->SetTypeOfHLR (aTypeOfHLR);
-      if (MyHLRIsOn)
-        ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
+
+      Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
+      if (aShape.IsNull())
+      {
+        std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
+        return 1;
+      }
+      aListOfShapes.Append (aShape);
+      continue;
     }
-    ViewerTest::CurrentView()->Update();
   }
+  if (aTypeOfHLR == Prs3d_TOH_NotSet)
+  {
+    std::cout << "Syntax error: wrong number of arguments!\n";
+    return 1;
+  }
+
+  const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
+  if (isGlobal)
+  {
+    aCtx->DisplayedObjects (aListOfShapes);
+    aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
+  }
+
+  for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
+  {
+    Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
+    if (aShape.IsNull())
+    {
+      continue;
+    }
 
+    const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
+                            && aView->ComputedMode();
+    if (!isGlobal
+     || aShape->TypeOfHLR() != aTypeOfHLR)
+    {
+      aShape->SetTypeOfHLR (aTypeOfHLR);
+    }
+    if (toUpdateShape)
+    {
+      aCtx->Redisplay (aShape, Standard_False);
+    }
+  }
   return 0;
 }
 
@@ -1024,13 +1123,10 @@ void ActivateView (const TCollection_AsciiString& theViewName)
       }
 
       ViewerTest::CurrentView (aView);
-      // Update degenerate mode
-      MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
       ViewerTest::SetAISContext (anAISContext);
-      TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
-      aTitle = aTitle + theViewName + "(*)";
+      TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
@@ -1077,14 +1173,16 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
     if (ViewerTest_myViews.Extent() > 1)
     {
       TCollection_AsciiString aNewViewName;
-      for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
-           anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
+      for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
+           anIter.More(); anIter.Next())
+      {
         if (anIter.Key1() != theViewName)
         {
           aNewViewName = anIter.Key1();
           break;
         }
-        ActivateView (aNewViewName);
+      }
+      ActivateView (aNewViewName);
     }
     else
     {
@@ -1112,6 +1210,7 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
 
   // Remove view resources
   ViewerTest_myViews.UnBind1(theViewName);
+  aView->Window()->Unmap();
   aView->Remove();
 
 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
@@ -1300,47 +1399,49 @@ static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const
     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
 
   if (isTreeView)
+  {
     theDi << theArgVec[0] <<":\n";
+  }
 
-    for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
-      aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
-    {
-      if (isTreeView)
-        theDi << aDriverIter.Key1() << ":\n";
+  for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
+       aDriverIter.More(); aDriverIter.Next())
+  {
+    if (isTreeView)
+      theDi << aDriverIter.Key1() << ":\n";
 
-      for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
-        aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
+    for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
+      aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
+    {
+      if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
       {
-        if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
+        if (isTreeView)
         {
-          if (isTreeView)
-          {
-            TCollection_AsciiString aContextName(aContextIter.Key1());
-            theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
-          }
+          TCollection_AsciiString aContextName(aContextIter.Key1());
+          theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
+        }
 
-          for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
-            aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
+        for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
+             aViewIter.More(); aViewIter.Next())
+        {
+          if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
           {
-            if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
+            TCollection_AsciiString aViewName(aViewIter.Key1());
+            if (isTreeView)
             {
-              TCollection_AsciiString aViewName(aViewIter.Key1());
-              if (isTreeView)
-              {
-                if (aViewIter.Value() == ViewerTest::CurrentView())
-                  theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
-                else
-                  theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
-              }
+              if (aViewIter.Value() == ViewerTest::CurrentView())
+                theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
               else
-              {
-                theDi << aViewName << " ";
-              }
+                theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
+            }
+            else
+            {
+              theDi << aViewName << " ";
             }
           }
         }
       }
     }
+  }
   return 0;
 }
 
@@ -1379,9 +1480,9 @@ void VT_ProcessKeyPress (const char* buf_ret)
   else if (!strcasecmp (buf_ret, "H"))
   {
     // HLR
-    cout << "HLR" << endl;
+    std::cout << "HLR" << std::endl;
     aView->SetComputedMode (!aView->ComputedMode());
-    MyHLRIsOn = aView->ComputedMode();
+    aView->Redraw();
   }
   else if (!strcasecmp (buf_ret, "P"))
   {
@@ -1432,7 +1533,7 @@ void VT_ProcessKeyPress (const char* buf_ret)
 
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
     if(Ctx->NbSelected()==0)
-      Ctx->SetDisplayMode(AIS_Shaded);
+      Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
     else{
       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
@@ -1446,7 +1547,7 @@ void VT_ProcessKeyPress (const char* buf_ret)
 
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
     if(Ctx->NbSelected()==0)
-      Ctx->SetDisplayMode(AIS_WireFrame);
+      Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
     else{
       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
@@ -1479,7 +1580,7 @@ void VT_ProcessKeyPress (const char* buf_ret)
     std::cout << "setup WireFrame display mode" << std::endl;
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
     if(Ctx->NbSelected()==0)
-      Ctx->SetDisplayMode(AIS_WireFrame);
+      Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
     else{
       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
@@ -1569,6 +1670,12 @@ Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
                                          Standard_Boolean theToPick,
                                          Standard_Boolean theIsShift)
 {
+  if (TheIsAnimating)
+  {
+    TheIsAnimating = Standard_False;
+    return Standard_False;
+  }
+
   if (theToPick)
   {
     Standard_Real X, Y, Z;
@@ -1621,7 +1728,8 @@ void VT_ProcessButton1Release (Standard_Boolean theIsShift)
 void VT_ProcessButton3Press()
 {
   Start_Rot = 1;
-  if (MyHLRIsOn)
+  HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
+  if (HasHlrOnBeforeRotation)
   {
     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
   }
@@ -1637,9 +1745,11 @@ void VT_ProcessButton3Release()
   if (Start_Rot)
   {
     Start_Rot = 0;
-    if (MyHLRIsOn)
+    if (HasHlrOnBeforeRotation)
     {
+      HasHlrOnBeforeRotation = Standard_False;
       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
+      ViewerTest::CurrentView()->Redraw();
     }
   }
 }
@@ -1888,7 +1998,7 @@ static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
         if (!GetActiveAISManipulator().IsNull())
         {
           GetActiveAISManipulator()->StopTransform();
-          ViewerTest::GetAISContext()->ClearSelected();
+          ViewerTest::GetAISContext()->ClearSelected (Standard_True);
         }
 
         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
@@ -1908,7 +2018,7 @@ static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
         if (!GetActiveAISManipulator().IsNull())
         {
           GetActiveAISManipulator()->StopTransform (Standard_False);
-          ViewerTest::GetAISContext()->ClearSelected();
+          ViewerTest::GetAISContext()->ClearSelected (Standard_True);
         }
         IsDragged = Standard_False;
       }
@@ -1996,7 +2106,7 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
   if (aView.IsNull())
   {
-    return DefWindowProc( hwnd, Msg, wParam, lParam );
+    return DefWindowProcW (hwnd, Msg, wParam, lParam);
   }
 
     PAINTSTRUCT    ps;
@@ -2164,14 +2274,11 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
       break;
 
     default:
-      return( DefWindowProc( hwnd, Msg, wParam, lParam ));
+      return DefWindowProcW (hwnd, Msg, wParam, lParam);
     }
     return 0L;
 }
 
-
-
-
 //==============================================================================
 //function : ViewerMainLoop
 //purpose  : Get a Event on the view and dispatch it
@@ -2192,9 +2299,10 @@ int ViewerMainLoop(Standard_Integer argc, const char** argv)
 
     while ( Ppick == 1 ) {
       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
-      if (GetMessage(&msg, NULL, 0, 0) ) {
-        TranslateMessage(&msg);
-        DispatchMessage(&msg);
+      if (GetMessageW (&msg, NULL, 0, 0))
+      {
+        TranslateMessage (&msg);
+        DispatchMessageW (&msg);
       }
     }
 
@@ -2331,24 +2439,24 @@ int ViewerMainLoop(Standard_Integer argc, const char** argv)
               if( DragFirst )
                 if( ShiftPressed )
                 {
-                  aContext->ShiftSelect();
+                  aContext->ShiftSelect (Standard_True);
                 }
                 else
                 {
-                  aContext->Select();
+                  aContext->Select (Standard_True);
                 }
               else
                 if( ShiftPressed )
                 {
-                  aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
-                    max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
-                    ViewerTest::CurrentView());
+                  aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
+                                        Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
+                                        ViewerTest::CurrentView(), Standard_True);
                 }
                 else
                 {
-                  aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
-                    max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
-                    ViewerTest::CurrentView() );
+                  aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
+                                   Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
+                                   ViewerTest::CurrentView(), Standard_True);
                 }
             else
               VT_ProcessButton3Release();
@@ -2497,33 +2605,42 @@ static void OSWindowSetup()
 
 //==============================================================================
 //function : VFit
-
-//purpose  : Fitall, no DRAW arguments
-//Draw arg : No args
+//purpose  :
 //==============================================================================
 
-static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv)
+static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
 {
-  if (theArgc > 2)
+  const Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl;
+    std::cout << "Error: no active viewer!\n";
+    return 1;
   }
 
-  const Handle(V3d_View) aView = ViewerTest::CurrentView();
-
-  if (theArgc == 2)
+  Standard_Boolean toFit = Standard_True;
+  ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    TCollection_AsciiString anArg (theArgv[1]);
+    TCollection_AsciiString anArg (theArgv[anArgIter]);
     anArg.LowerCase();
-    if (anArg == "-selected")
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      ViewerTest::GetAISContext()->FitSelected (aView);
-      return 0;
+      continue;
+    }
+    else if (anArg == "-selected")
+    {
+      ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
+      toFit = Standard_False;
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << anArg << "'\n";
     }
   }
-  if (aView.IsNull() == Standard_False) {
 
-    aView->FitAll();
+  if (toFit)
+  {
+    aView->FitAll (0.01, Standard_False);
   }
   return 0;
 }
@@ -2629,10 +2746,44 @@ static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const
 //function : VRepaint
 //purpose  :
 //==============================================================================
-static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
+static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
 {
-  Handle(V3d_View) V = ViewerTest::CurrentView();
-  if ( !V.IsNull() ) V->Redraw(); return 0;
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << "Error: no active viewer!\n";
+    return 1;
+  }
+
+  Standard_Boolean isImmediateUpdate = Standard_False;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anArg == "-immediate")
+    {
+      isImmediateUpdate = Standard_True;
+      if (anArgIter + 1 < theArgNb
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
+      {
+        ++anArgIter;
+      }
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << anArg << "'\n";
+    }
+  }
+
+  if (isImmediateUpdate)
+  {
+    aView->RedrawImmediate();
+  }
+  else
+  {
+    aView->Redraw();
+  }
+  return 0;
 }
 
 //==============================================================================
@@ -3391,55 +3542,23 @@ static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** arg
     return 1;
   }
 
+  Standard_DISABLE_DEPRECATION_WARNINGS
   try
   {
-  Standard_DISABLE_DEPRECATION_WARNINGS
     if (!V3dView->Export (argv[1], anExpFormat))
-  Standard_ENABLE_DEPRECATION_WARNINGS
     {
       di << "Error: export of image to " << aFormatStr << " failed!\n";
     }
   }
-  catch (Standard_Failure)
+  catch (Standard_Failure const& anException)
   {
     di << "Error: export of image to " << aFormatStr << " failed";
-    di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
+    di << " (exception: " << anException.GetMessageString() << ")";
   }
+  Standard_ENABLE_DEPRECATION_WARNINGS
   return 0;
 }
 
-//==============================================================================
-//function : VColorScale
-//purpose  : representation color scale
-//==============================================================================
-
-static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
-                                    const TCollection_AsciiString& theGreen,
-                                    const TCollection_AsciiString& theBlue,
-                                                    Standard_Real& theRedValue,
-                                                    Standard_Real& theGreenValue,
-                                                    Standard_Real& theBlueValue)
-{
-  if (!theRed.IsRealValue()
-   || !theGreen.IsRealValue()
-   || !theBlue.IsRealValue())
-  {
-    std::cout << "Error: RGB color values should be real!\n";
-    return Standard_True;
-  }
-  theRedValue = theRed    .RealValue();
-  theGreenValue = theGreen.RealValue();
-  theBlueValue = theBlue  .RealValue();
-  if (theRedValue < 0.0 || theRedValue > 1.0
-   || theGreenValue < 0.0 || theGreenValue > 1.0
-   || theBlueValue < 0.0 || theBlueValue > 1.0)
-  {
-    std::cout << "Error: RGB color values should be within range 0..1!\n";
-    return Standard_True;
-  }
-  return Standard_False;
-}
-
 static int VColorScale (Draw_Interpretor& theDI,
                         Standard_Integer  theArgNb,
                         const char**      theArgVec)
@@ -3457,57 +3576,35 @@ static int VColorScale (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Handle(AIS_ColorScale) aCS;
-  // find object
-  Handle(AIS_InteractiveObject) anIObj;
+  Handle(AIS_ColorScale) aColorScale;
   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
   {
-    aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
-    if (aCS.IsNull())
+    // find existing object
+    aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
+    if (aColorScale.IsNull())
     {
       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
       return 1;
     }
   }
-  else
-  {
-    aCS = new AIS_ColorScale();
-    GetMapOfAIS().Bind (aCS,theArgVec[1]);
-  }
-
-  if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
-  {
-    aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
-  }
-  if (aCS->TransformPersistence().IsNull()
-   || aCS->TransformPersistence()->Mode() != Graphic3d_TMF_2d)
-  {
-    aContext->SetTransformPersistence (aCS, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
-  }
-
-  Standard_Real                   aMinRange    = aCS->GetMin();
-  Standard_Real                   aMaxRange    = aCS->GetMax();
-  Standard_Integer                aBreadth     = aCS->GetBreadth();
-  Standard_Integer                aHeight      = aCS->GetHeight();
-  Standard_Integer                aNbIntervals = aCS->GetNumberOfIntervals();
-  Standard_Integer                aTextHeight  = aCS->GetTextHeight();
-  Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition();
-  Standard_Integer                aPosX = aCS->GetXPosition();
-  Standard_Integer                aPosY = aCS->GetYPosition();
-
-  ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
 
   if (theArgNb <= 2)
   {
+    if (aColorScale.IsNull())
+    {
+      std::cout << "Syntax error: colorscale with a given name does not exist.\n";
+      return 1;
+    }
+
     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
-          << "Min range: " << aMinRange << "\n"
-          << "Max range: " << aMaxRange << "\n"
-          << "Number of intervals: " << aNbIntervals << "\n"
-          << "Text height: " << aTextHeight << "\n"
-          << "Color scale position: " << aPosX <<" "<< aPosY<< "\n"
-          << "Color scale title: " << aCS->GetTitle() << "\n"
+          << "Min range: "            << aColorScale->GetMin() << "\n"
+          << "Max range: "            << aColorScale->GetMax() << "\n"
+          << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
+          << "Text height: "          << aColorScale->GetTextHeight() << "\n"
+          << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
+          << "Color scale title: "    << aColorScale->GetTitle() << "\n"
           << "Label position: ";
-    switch (aLabPosition)
+    switch (aColorScale->GetLabelPosition())
     {
       case Aspect_TOCSP_NONE:
         theDI << "None\n";
@@ -3525,6 +3622,14 @@ static int VColorScale (Draw_Interpretor& theDI,
     return 0;
   }
 
+  if (aColorScale.IsNull())
+  {
+    aColorScale = new AIS_ColorScale();
+    aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
+    aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
+  }
+
+  ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
   {
     Standard_CString        anArg = theArgVec[anArgIter];
@@ -3542,28 +3647,23 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
-      TCollection_AsciiString anArg2 (theArgVec[++anArgIter]);
-      TCollection_AsciiString anArg3 (theArgVec[++anArgIter]);
-      if (!anArg1.IsRealValue())
+      const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
+      const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
+      const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
+      if (!aRangeMin.IsRealValue()
+       || !aRangeMax.IsRealValue())
       {
-        std::cout << "Error: the minRange value should be real!\n";
+        std::cout << "Error: the range values should be real!\n";
         return 1;
       }
-      else if (!anArg2.IsRealValue())
-      {
-        std::cout << "Error: the maxRange value should be real!\n";
-        return 1;
-      }
-      else if (!anArg3.IsIntegerValue())
+      else if (!aNbIntervals.IsIntegerValue())
       {
         std::cout << "Error: the number of intervals should be integer!\n";
         return 1;
       }
 
-      aMinRange    = anArg1.RealValue();
-      aMaxRange    = anArg2.RealValue();
-      aNbIntervals = anArg3.IntegerValue();
+      aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
+      aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
     }
     else if (aFlag == "-font")
     {
@@ -3579,7 +3679,7 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      aTextHeight = aFontArg.IntegerValue();
+      aColorScale->SetTextHeight (aFontArg.IntegerValue());
       anArgIter += 1;
     }
     else if (aFlag == "-textpos")
@@ -3589,8 +3689,10 @@ static int VColorScale (Draw_Interpretor& theDI,
         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
         return 1;
       }
+
       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
       aTextPosArg.LowerCase();
+      Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
       if (aTextPosArg == "none")
       {
         aLabPosition = Aspect_TOCSP_NONE;
@@ -3612,6 +3714,7 @@ static int VColorScale (Draw_Interpretor& theDI,
         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
         return 1;
       }
+      aColorScale->SetLabelPosition (aLabPosition);
     }
     else if (aFlag == "-logarithmic"
           || aFlag == "-log")
@@ -3621,15 +3724,17 @@ static int VColorScale (Draw_Interpretor& theDI,
         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
         return 1;
       }
+
       Standard_Boolean IsLog;
       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
       {
         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
         return 1;
       }
-      aCS->SetLogarithmic (IsLog);
+      aColorScale->SetLogarithmic (IsLog);
     }
-    else if (aFlag == "-xy")
+    else if (aFlag == "-huerange"
+          || aFlag == "-hue")
     {
       if (anArgIter + 2 >= theArgNb)
       {
@@ -3637,35 +3742,90 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString aX (theArgVec[++anArgIter]);
-      TCollection_AsciiString aY (theArgVec[++anArgIter]);
-      if (!aX.IsIntegerValue()
-       || !aY.IsIntegerValue())
+      const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
+      const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
+      aColorScale->SetHueRange (aHueMin, aHueMax);
+    }
+    else if (aFlag == "-colorrange")
+    {
+      Quantity_Color aColorMin, aColorMax;
+      Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
+                                                            theArgVec + (anArgIter + 1),
+                                                            aColorMin);
+      anArgIter += aNbParsed1;
+      Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
+                                                            theArgVec + (anArgIter + 1),
+                                                            aColorMax);
+      anArgIter += aNbParsed2;
+      if (aNbParsed1 == 0
+       || aNbParsed2 == 0)
       {
-        std::cout << "Error: coordinates should be integer values!\n";
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
         return 1;
       }
 
-      aPosX = aX.IntegerValue();
-      aPosY = aY.IntegerValue();
+      aColorScale->SetColorRange (aColorMin, aColorMax);
     }
-    else if (aFlag == "-width"
-          || aFlag == "-w")
+    else if (aFlag == "-reversed"
+          || aFlag == "-inverted"
+          || aFlag == "-topdown"
+          || aFlag == "-bottomup")
     {
-      if (anArgIter + 1 >= theArgNb)
+      Standard_Boolean toEnable = Standard_True;
+      if (anArgIter + 1 < theArgNb
+       && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
       {
-        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        ++anArgIter;
       }
-
-      TCollection_AsciiString aW (theArgVec[++anArgIter]);
-      if (!aW.IsIntegerValue())
+      aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
+    }
+    else if (aFlag == "-smooth"
+          || aFlag == "-smoothtransition")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (anArgIter + 1 < theArgNb
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
       {
-        std::cout << "Error: a width should be an integer value!\n";
-        return 1;
+        ++anArgIter;
       }
-
-      aBreadth = aW.IntegerValue();
+      aColorScale->SetSmoothTransition (toEnable);
+    }
+    else if (aFlag == "-xy")
+    {
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      const TCollection_AsciiString anX (theArgVec[++anArgIter]);
+      const TCollection_AsciiString anY (theArgVec[++anArgIter]);
+      if (!anX.IsIntegerValue()
+       || !anY.IsIntegerValue())
+      {
+        std::cout << "Error: coordinates should be integer values!\n";
+        return 1;
+      }
+
+      aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
+    }
+    else if (aFlag == "-width"
+          || aFlag == "-w"
+          || aFlag == "-breadth")
+    {
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
+      if (!aBreadth.IsIntegerValue())
+      {
+        std::cout << "Error: a width should be an integer value!\n";
+        return 1;
+      }
+      aColorScale->SetBreadth (aBreadth.IntegerValue());
     }
     else if (aFlag == "-height"
           || aFlag == "-h")
@@ -3676,75 +3836,56 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString aH (theArgVec[++anArgIter]);
-      if (!aH.IsIntegerValue())
+      const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
+      if (!aHeight.IsIntegerValue())
       {
         std::cout << "Error: a width should be an integer value!\n";
         return 1;
       }
-
-      aHeight = aH.IntegerValue();
+      aColorScale->SetHeight (aHeight.IntegerValue());
     }
     else if (aFlag == "-color")
     {
-      if (aCS->GetColorType() != Aspect_TOCSD_USER)
+      if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
       {
         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
         return 1;
       }
-
-      Quantity_NameOfColor aColorName;
-      if (anArgIter + 4 >= theArgNb)
+      else if (anArgIter + 2 >= theArgNb)
       {
-        if (anArgIter + 2 >= theArgNb)
-        {
-          std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
-          return 1;
-        }
-        else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
-        {
-          std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n";
-          return 1;
-        }
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
       }
 
-      TCollection_AsciiString anInd (theArgVec[anArgIter + 1]);
+      const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
       if (!anInd.IsIntegerValue())
       {
         std::cout << "Error: Index value should be integer!\n";
         return 1;
       }
-
-      Standard_Integer anIndex = anInd.IntegerValue();
-      if (anIndex <= 0 || anIndex > aNbIntervals)
+      const Standard_Integer anIndex = anInd.IntegerValue();
+      if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
       {
-        std::cout << "Error: Index value should be within range 1.." << aNbIntervals <<"!\n";
+        std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
         return 1;
       }
 
-      if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
-      {
-        aCS->SetIntervalColor (Quantity_Color (aColorName), anIndex);
-        aCS->SetColorType (Aspect_TOCSD_USER);
-        anArgIter += 2;
-        continue;
-      }
-
-      TCollection_AsciiString aRed   (theArgVec[anArgIter + 2]);
-      TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]);
-      TCollection_AsciiString aBlue  (theArgVec[anArgIter + 4]);
-      Standard_Real aRedValue,aGreenValue, aBlueValue;
-      if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
+                                                           theArgVec + (anArgIter + 1),
+                                                           aColor);
+      if (aNbParsed == 0)
       {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
         return 1;
       }
-      aCS->SetIntervalColor (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex);
-      aCS->SetColorType (Aspect_TOCSD_USER);
-      anArgIter += 4;
+      aColorScale->SetIntervalColor (aColor, anIndex);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
+      anArgIter += aNbParsed;
     }
     else if (aFlag == "-label")
     {
-      if (aCS->GetColorType() != Aspect_TOCSD_USER)
+      if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
       {
         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
         return 1;
@@ -3756,90 +3897,115 @@ static int VColorScale (Draw_Interpretor& theDI,
       }
 
       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
-      if (anIndex <= 0 || anIndex > aNbIntervals+1)
+      if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
       {
-        std::cout << "Error: Index value should be within range 1.." << aNbIntervals+1 <<"!\n";
+        std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
         return 1;
       }
 
       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
-      aCS->SetLabel     (aText, anIndex);
-      aCS->SetLabelType (Aspect_TOCSD_USER);
+      aColorScale->SetLabel     (aText, anIndex);
+      aColorScale->SetLabelType (Aspect_TOCSD_USER);
       anArgIter += 2;
     }
-    else if (aFlag == "-colors")
+    else if (aFlag == "-labelat"
+          || aFlag == "-labat"
+          || aFlag == "-labelatborder"
+          || aFlag == "-labatborder"
+          || aFlag == "-labelatcenter"
+          || aFlag == "-labatcenter")
     {
-      Aspect_SequenceOfColor aSeq;
-      if (anArgIter + aNbIntervals + 1 > theArgNb)
-      {
-        std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
-                  << aNbIntervals << " intervals\n";
-        return 1;
-      }
-
-      Standard_Integer aColorIter = anArgIter + 1;
-      while (aColorIter < theArgNb)
+      Standard_Boolean toEnable = Standard_True;
+      if (aFlag == "-labelat"
+       || aFlag == "-labat")
       {
-        if (theArgVec[aColorIter][0] == '-')
-        {
-          break;
-        }
-
-        else if (theArgVec[aColorIter][0] >= 97
-              && theArgVec[aColorIter][0] <= 122)
+        Standard_Integer aLabAtBorder = -1;
+        if (++anArgIter >= theArgNb)
         {
-          Quantity_NameOfColor aColorName;
-          if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName))
+          TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
+          anAtBorder.LowerCase();
+          if (anAtBorder == "border")
           {
-            std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n";
-            return 1;
+            aLabAtBorder = 1;
           }
-          aSeq.Append (Quantity_Color (aColorName));
-          aColorIter++;
-          anArgIter++;
-        }
-        else
-        {
-          TCollection_AsciiString aRed   (theArgVec[aColorIter]);
-          TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]);
-          TCollection_AsciiString aBlue  (theArgVec[aColorIter + 2]);
-          Standard_Real aRedValue,aGreenValue, aBlueValue;
-          if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
+          else if (anAtBorder == "center")
           {
-            return 1;
+            aLabAtBorder = 0;
           }
-          aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB));
-          aColorIter += 3;
-          anArgIter += 3;
         }
+        if (aLabAtBorder == -1)
+        {
+          std::cout << "Syntax error at argument '" << anArg << "'!\n";
+          return 1;
+        }
+        toEnable = (aLabAtBorder == 1);
+      }
+      else if (anArgIter + 1 < theArgNb
+            && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
+      {
+        ++anArgIter;
+      }
+      aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
+                                  || aFlag == "-labatcenter"
+                                   ? !toEnable
+                                   :  toEnable);
+    }
+    else if (aFlag == "-colors")
+    {
+      Aspect_SequenceOfColor aSeq;
+      for (;;)
+      {
+        Quantity_Color aColor;
+        Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
+                                                             theArgVec + (anArgIter + 1),
+                                                             aColor);
+        if (aNbParsed == 0)
+        {
+          break;
+        }
+        anArgIter += aNbParsed;
+        aSeq.Append (aColor);
       }
-      if (aSeq.Length() < aNbIntervals)
+      if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
       {
         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
-                  << aNbIntervals << " intervals\n";
+                  << aColorScale->GetNumberOfIntervals() << " intervals\n";
         return 1;
       }
 
-      aCS->SetColors    (aSeq);
-      aCS->SetColorType (Aspect_TOCSD_USER);
+      aColorScale->SetColors    (aSeq);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
     }
-    else if (aFlag == "-labels")
+    else if (aFlag == "-labels"
+          || aFlag == "-freelabels")
     {
-      if (anArgIter + aNbIntervals + 1 >= theArgNb)
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Syntax error at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
+                                 ? aColorScale->GetNumberOfIntervals() + 1
+                                 : aColorScale->GetNumberOfIntervals();
+      if (aFlag == "-freelabels")
       {
-        std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1)
-                  << " text labels for " << aNbIntervals << " intervals.\n";
+        ++anArgIter;
+        aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
+      }
+      if (anArgIter + aNbLabels >= theArgNb)
+      {
+        std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
         return 1;
       }
 
       TColStd_SequenceOfExtendedString aSeq;
-      for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1)
+      for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
       {
-        aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter]));
+        aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
       }
-      aCS->SetLabels (aSeq);
-      aCS->SetLabelType (Aspect_TOCSD_USER);
-      anArgIter += aSeq.Length();
+      aColorScale->SetLabels (aSeq);
+      aColorScale->SetLabelType (Aspect_TOCSD_USER);
     }
     else if (aFlag == "-title")
     {
@@ -3854,29 +4020,31 @@ static int VColorScale (Draw_Interpretor& theDI,
       {
         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
         aSecondArg.LowerCase();
+      Standard_DISABLE_DEPRECATION_WARNINGS
         if (aSecondArg == "none")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_NONE);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
           isTwoArgs = Standard_True;
         }
         else if (aSecondArg == "left")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_LEFT);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
           isTwoArgs = Standard_True;
         }
         else if (aSecondArg == "right")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_RIGHT);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
           isTwoArgs = Standard_True;
         }
         else if (aSecondArg == "center")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_CENTER);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
           isTwoArgs = Standard_True;
         }
+      Standard_ENABLE_DEPRECATION_WARNINGS
       }
 
-      aCS->SetTitle (theArgVec[anArgIter + 1]);
+      aColorScale->SetTitle (theArgVec[anArgIter + 1]);
       if (isTwoArgs)
       {
         anArgIter += 1;
@@ -3886,17 +4054,15 @@ static int VColorScale (Draw_Interpretor& theDI,
     else if (aFlag == "-demoversion"
           || aFlag == "-demo")
     {
-      aPosX        = 0;
-      aPosY        = 0;
-      aTextHeight  = 16;
-      aMinRange    = 0.0;
-      aMaxRange    = 100;
-      aNbIntervals = 10;
-      aBreadth     = 0;
-      aHeight      = 0;
-      aLabPosition = Aspect_TOCSP_RIGHT;
-      aCS->SetColorType (Aspect_TOCSD_AUTO);
-      aCS->SetLabelType (Aspect_TOCSD_AUTO);
+      aColorScale->SetPosition (0, 0);
+      aColorScale->SetTextHeight (16);
+      aColorScale->SetRange (0.0, 100.0);
+      aColorScale->SetNumberOfIntervals (10);
+      aColorScale->SetBreadth (0);
+      aColorScale->SetHeight  (0);
+      aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
+      aColorScale->SetColorType (Aspect_TOCSD_AUTO);
+      aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
     }
     else if (aFlag == "-findcolor")
     {
@@ -3915,7 +4081,7 @@ static int VColorScale (Draw_Interpretor& theDI,
       }
 
       Quantity_Color aColor;
-      aCS->FindColor (anArg1.RealValue(), aColor);
+      aColorScale->FindColor (anArg1.RealValue(), aColor);
       theDI << Quantity_Color::StringName (aColor.Name());
       return 0;
     }
@@ -3925,29 +4091,19 @@ static int VColorScale (Draw_Interpretor& theDI,
       return 1;
     }
   }
-  if (!aBreadth || !aHeight)
+
+  Standard_Integer aWinWidth = 0, aWinHeight = 0;
+  aView->Window()->Size (aWinWidth, aWinHeight);
+  if (aColorScale->GetBreadth() == 0)
   {
-    Standard_Integer aWinWidth, aWinHeight;
-    aView->Window()->Size (aWinWidth, aWinHeight);
-    if (!aBreadth)
-    {
-      aBreadth = aWinWidth;
-    }
-    if (!aHeight)
-    {
-      aHeight = aWinHeight;
-    }
+    aColorScale->SetBreadth (aWinWidth);
   }
-  aCS->SetSize              (aBreadth, aHeight);
-  aCS->SetPosition          (aPosX, aPosY);
-  aCS->SetTextHeight        (aTextHeight);
-  aCS->SetRange             (aMinRange, aMaxRange);
-  aCS->SetNumberOfIntervals (aNbIntervals);
-  aCS->SetLabelPosition     (aLabPosition);
-//  aCS->SetColor             (aView->BackgroundColor().Invert());
-  aCS->SetToUpdate();
-  aContext->Display (aCS);
-
+  if (aColorScale->GetHeight() == 0)
+  {
+    aColorScale->SetHeight (aWinHeight);
+  }
+  aColorScale->SetToUpdate();
+  ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
   return 0;
 }
 
@@ -4391,216 +4547,383 @@ static int VTile (Draw_Interpretor& theDI,
   return 0;
 }
 
+//! Format ZLayer ID.
+inline const char* formZLayerId (const Standard_Integer theLayerId)
+{
+  switch (theLayerId)
+  {
+    case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
+    case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
+    case Graphic3d_ZLayerId_Top:     return "[TOP]";
+    case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
+    case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
+    case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
+  }
+  return "";
+}
+
+//! Print the ZLayer information.
+inline void printZLayerInfo (Draw_Interpretor& theDI,
+                             const Graphic3d_ZLayerSettings& theLayer)
+{
+  if (!theLayer.Name().IsEmpty())
+  {
+    theDI << "  Name: " << theLayer.Name() << "\n";
+  }
+  if (theLayer.IsImmediate())
+  {
+    theDI << "  Immediate: TRUE\n";
+  }
+  theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
+  theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
+  theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
+  theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
+  if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
+  {
+    theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
+  }
+}
+
 //==============================================================================
 //function : VZLayer
 //purpose  : Test z layer operations for v3d viewer
 //==============================================================================
-static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+static int VZLayer (Draw_Interpretor& theDI,
+                    Standard_Integer  theArgNb,
+                    const char**      theArgVec)
 {
-  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
+  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
   if (aContextAIS.IsNull())
   {
-    di << "Call vinit before!\n";
-    return 1;
-  }
-  else if (argc < 2)
-  {
-    di << di.PrintHelp (argv[0]);
+    std::cout << "No active viewer!\n";
     return 1;
   }
 
   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
-  if (aViewer.IsNull())
+  if (theArgNb < 2)
   {
-    di << "No active viewer!\n";
+    TColStd_SequenceOfInteger aLayers;
+    aViewer->GetAllZLayers (aLayers);
+    for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
+    {
+      theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
+      printZLayerInfo (theDI, aSettings);
+    }
     return 1;
   }
 
-  // perform operation
-  TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
-  if (anOp == "add")
+  Standard_Integer anArgIter = 1;
+  Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
+  ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
+  if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
   {
-    Standard_Integer aNewId;
-    if (!aViewer->AddZLayer (aNewId))
-    {
-      di << "Impossible to add new z layer!\n";
-      return 1;
-    }
+    ++anArgIter;
+  }
 
-    di << "New z layer added with index: " << aNewId << "\n";
+  TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
+  if (aFirstArg.IsIntegerValue())
+  {
+    ++anArgIter;
+    aLayerId = aFirstArg.IntegerValue();
   }
-  else if (anOp == "del")
+  else
   {
-    if (argc < 3)
-    {
-      di << "Please also provide as argument id of z layer to remove\n";
-      return 1;
-    }
-
-    Standard_Integer aDelId = Draw::Atoi (argv[2]);
-    if (!aViewer->RemoveZLayer (aDelId))
+    aFirstArg.LowerCase();
+    if (aFirstArg == "default"
+     || aFirstArg == "def")
     {
-      di << "Impossible to remove the z layer or invalid id!\n";
-      return 1;
+      aLayerId = Graphic3d_ZLayerId_Default;
+      ++anArgIter;
     }
-
-    for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
-         anObjIter.More(); anObjIter.Next())
+    else if (aFirstArg == "top")
     {
-      Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
-      if (aPrs.IsNull()
-       || aPrs->ZLayer() != aDelId)
-      {
-        continue;
-      }
-      aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
+      aLayerId = Graphic3d_ZLayerId_Top;
+      ++anArgIter;
     }
-
-    di << "Z layer " << aDelId << " has been removed\n";
-  }
-  else if (anOp == "get")
-  {
-    TColStd_SequenceOfInteger anIds;
-    aViewer->GetAllZLayers (anIds);
-    for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
+    else if (aFirstArg == "topmost")
     {
-      di << anIds.Value (aSeqIdx) << " ";
+      aLayerId = Graphic3d_ZLayerId_Topmost;
+      ++anArgIter;
     }
-
-    di << "\n";
-  }
-  else if (anOp == "settings")
-  {
-    if (argc < 3)
+    else if (aFirstArg == "overlay"
+          || aFirstArg == "toposd")
     {
-      di << "Please also provide an id\n";
-      return 1;
+      aLayerId = Graphic3d_ZLayerId_TopOSD;
+      ++anArgIter;
     }
-
-    Standard_Integer anId = Draw::Atoi (argv[2]);
-    Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
-
-    di << "Depth test - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthTest) ? "enabled" : "disabled") << "\n";
-    di << "Depth write - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? "enabled" : "disabled") << "\n";
-    di << "Depth buffer clearing - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthClear) ? "enabled" : "disabled") << "\n";
-    di << "Depth offset - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthOffset) ? "enabled" : "disabled") << "\n";
-
-  }
-  else if (anOp == "enable")
-  {
-    if (argc < 3)
+    else if (aFirstArg == "underlay"
+          || aFirstArg == "botosd")
     {
-      di << "Please also provide an option to enable\n";
-      return 1;
+      aLayerId = Graphic3d_ZLayerId_BotOSD;
+      ++anArgIter;
     }
-
-    if (argc < 4)
+    else
     {
-      di << "Please also provide a layer id\n";
-      return 1;
+      TColStd_SequenceOfInteger aLayers;
+      aViewer->GetAllZLayers (aLayers);
+      for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
+      {
+        Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
+        if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
+        {
+          aLayerId = aLayeriter.Value();
+          ++anArgIter;
+          break;
+        }
+      }
     }
+  }
 
-    TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
-    Standard_Integer anId = Draw::Atoi (argv[3]);
-    Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
-
-    if (aSubOp == "depthtest" || aSubOp == "test")
-    {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthTest);
-    }
-    else if (aSubOp == "depthwrite" || aSubOp == "write")
+  for (; anArgIter < theArgNb; ++anArgIter)
+  {
+    // perform operation
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthWrite);
+      //
     }
-    else if (aSubOp == "depthclear" || aSubOp == "clear")
+    else if (anArg == "-add"
+          || anArg == "add")
     {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthClear);
+      aLayerId = Graphic3d_ZLayerId_UNKNOWN;
+      if (!aViewer->AddZLayer (aLayerId))
+      {
+        std::cout << "Error: can not add a new z layer!\n";
+        return 0;
+      }
+
+      theDI << aLayerId;
     }
-    else if (aSubOp == "depthoffset" || aSubOp == "offset")
+    else if (anArg == "-del"
+          || anArg == "-delete"
+          || anArg == "del")
     {
-      if (argc < 6)
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
       {
-        di << "Please also provide a factor and units values for depth offset\n";
-        di << "Format is: vzlayer enable offset [factor] [units] [layerId]\n";
-        return 1;
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of z layer to remove is missing\n";
+          return 1;
+        }
+
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
       }
 
-      Standard_ShortReal aFactor = static_cast<Standard_ShortReal> (Draw::Atof (argv[3]));
-      Standard_ShortReal aUnits  = static_cast<Standard_ShortReal> (Draw::Atof (argv[4]));
-      anId = Draw::Atoi (argv[5]);
-      aSettings = aViewer->ZLayerSettings (anId);
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
+       || aLayerId == Graphic3d_ZLayerId_Default
+       || aLayerId == Graphic3d_ZLayerId_Top
+       || aLayerId == Graphic3d_ZLayerId_Topmost
+       || aLayerId == Graphic3d_ZLayerId_TopOSD
+       || aLayerId == Graphic3d_ZLayerId_BotOSD)
+      {
+        std::cout << "Syntax error: standard Z layer can not be removed\n";
+        return 1;
+      }
 
-      aSettings.DepthOffsetFactor = aFactor;
-      aSettings.DepthOffsetUnits  = aUnits;
+      // move all object displayed in removing layer to default layer
+      for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
+           anObjIter.More(); anObjIter.Next())
+      {
+        Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
+        if (aPrs.IsNull()
+         || aPrs->ZLayer() != aLayerId)
+        {
+          continue;
+        }
+        aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
+      }
 
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthOffset);
-    }
-    else if (aSubOp == "positiveoffset" || aSubOp == "poffset")
-    {
-      aSettings.SetDepthOffsetPositive();
-    }
-    else if (aSubOp == "negativeoffset" || aSubOp == "noffset")
-    {
-      aSettings.SetDepthOffsetNegative();
+      if (!aViewer->RemoveZLayer (aLayerId))
+      {
+        std::cout << "Z layer can not be removed!\n";
+      }
+      else
+      {
+        theDI << aLayerId << " ";
+      }
     }
-    else if (aSubOp == "textureenv")
+    else if (anArg == "-get"
+          || anArg == "get")
     {
-      aSettings.UseEnvironmentTexture = true;
-    }
+      TColStd_SequenceOfInteger aLayers;
+      aViewer->GetAllZLayers (aLayers);
+      for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
+      {
+        theDI << aLayeriter.Value() << " ";
+      }
 
-    aViewer->SetZLayerSettings (anId, aSettings);
-  }
-  else if (anOp == "disable")
-  {
-    if (argc < 3)
-    {
-      di << "Please also provide an option to disable\n";
-      return 1;
+      theDI << "\n";
     }
-
-    if (argc < 4)
+    else if (anArg == "-name")
     {
-      di << "Please also provide a layer id\n";
-      return 1;
-    }
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        std::cout << "Syntax error: id of Z layer is missing\n";
+        return 1;
+      }
 
-    TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
-    Standard_Integer anId = Draw::Atoi (argv[3]);
-    Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error: name is missing\n";
+        return 1;
+      }
 
-    if (aSubOp == "depthtest" || aSubOp == "test")
-    {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthTest);
-    }
-    else if (aSubOp == "depthwrite" || aSubOp == "write")
-    {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthWrite);
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      aSettings.SetName (theArgVec[anArgIter]);
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
     }
-    else if (aSubOp == "depthclear" || aSubOp == "clear")
+    else if (anArg == "-origin")
     {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthClear);
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        std::cout << "Syntax error: id of Z layer is missing\n";
+        return 1;
+      }
+
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Syntax error: origin coordinates are missing\n";
+        return 1;
+      }
+
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      gp_XYZ anOrigin;
+      anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
+      anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
+      anOrigin.SetZ (0.0);
+      if (anArgIter + 3 < theArgNb)
+      {
+        anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
+        anArgIter += 3;
+      }
+      else
+      {
+        anArgIter += 2;
+      }
+      aSettings.SetOrigin (anOrigin);
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
     }
-    else if (aSubOp == "depthoffset" || aSubOp == "offset")
+    else if (anArg == "-settings"
+          || anArg == "settings")
     {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of Z layer is missing\n";
+          return 1;
+        }
+
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
+      }
+
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      printZLayerInfo (theDI, aSettings);
     }
-    else if (aSubOp == "textureenv")
+    else if (anArg == "-enable"
+          || anArg == "enable"
+          || anArg == "-disable"
+          || anArg == "disable")
     {
-      aSettings.UseEnvironmentTexture = false;
-    }
+      const Standard_Boolean toEnable = anArg == "-enable"
+                                     || anArg == "enable";
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error: option name is missing\n";
+        return 1;
+      }
 
-    aViewer->SetZLayerSettings (anId, aSettings);
-  }
-  else
-  {
-    di << "Invalid operation, please use { add / del / get / settings / enable / disable}\n";
-    return 1;
-  }
+      TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
+      aSubOp.LowerCase();
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of Z layer is missing\n";
+          return 1;
+        }
 
-  return 0;
-}
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
+      }
 
-// The interactive presentation of 2d layer item
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      if (aSubOp == "depthtest"
+       || aSubOp == "test")
+      {
+        aSettings.SetEnableDepthTest (toEnable);
+      }
+      else if (aSubOp == "depthwrite"
+            || aSubOp == "write")
+      {
+        aSettings.SetEnableDepthWrite (toEnable);
+      }
+      else if (aSubOp == "depthclear"
+            || aSubOp == "clear")
+      {
+        aSettings.SetClearDepth (toEnable);
+      }
+      else if (aSubOp == "depthoffset"
+            || aSubOp == "offset")
+      {
+        Graphic3d_PolygonOffset aParams;
+        aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
+        if (toEnable)
+        {
+          if (anArgIter + 2 >= theArgNb)
+          {
+            std::cout << "Syntax error: factor and units values for depth offset are missing\n";
+            return 1;
+          }
+
+          aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
+          aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
+        }
+        aSettings.SetPolygonOffset (aParams);
+      }
+      else if (aSubOp == "positiveoffset"
+            || aSubOp == "poffset")
+      {
+        if (toEnable)
+        {
+          aSettings.SetDepthOffsetPositive();
+        }
+        else
+        {
+          aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
+        }
+      }
+      else if (aSubOp == "negativeoffset"
+            || aSubOp == "noffset")
+      {
+        if (toEnable)
+        {
+          aSettings.SetDepthOffsetNegative();
+        }
+        else
+        {
+          aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
+        }
+      }
+      else if (aSubOp == "textureenv")
+      {
+        aSettings.SetEnvironmentTexture (toEnable);
+      }
+
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+// The interactive presentation of 2d layer item
 // for "vlayerline" command it provides a presentation of
 // line with user-defined linewidth, linetype and transparency.
 class V3d_LineItem : public AIS_InteractiveObject
@@ -4699,17 +5022,21 @@ static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char**
   Standard_Real X2 = Draw::Atof(argv[3]);
   Standard_Real Y2 = Draw::Atof(argv[4]);
 
-  Standard_Real    aWidth = 0.5;
-  Standard_Integer aType  = 0;
-  Standard_Real    aTransparency = 1.0;
+  Standard_Real aWidth = 0.5;
+  Standard_Real aTransparency = 1.0;
 
   // has width
   if (argc > 5)
     aWidth = Draw::Atof(argv[5]);
 
-  // has type
-  if (argc > 6)
-     aType = (Standard_Integer) Draw::Atoi(argv[6]);
+  // select appropriate line type
+  Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
+  if (argc > 6
+  && !ViewerTest::ParseLineType (argv[6], aLineType))
+  {
+    std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
+    return 1;
+  }
 
   // has transparency
   if (argc > 7)
@@ -4719,30 +5046,10 @@ static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char**
       aTransparency = 1.0;
   }
 
-  // select appropriate line type
-  Aspect_TypeOfLine aLineType;
-  switch (aType)
-  {
-    case 1:
-      aLineType = Aspect_TOL_DASH;
-    break;
-
-    case 2:
-      aLineType = Aspect_TOL_DOT;
-    break;
-
-    case 3:
-      aLineType = Aspect_TOL_DOTDASH;
-    break;
-
-    default:
-      aLineType = Aspect_TOL_SOLID;
-  }
-
   static Handle (V3d_LineItem) aLine;
   if (!aLine.IsNull())
   {
-    aContext->Erase (aLine);
+    aContext->Erase (aLine, Standard_False);
   }
   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
                             aLineType, aWidth,
@@ -4777,12 +5084,16 @@ static int VGrid (Draw_Interpretor& /*theDI*/,
 
   Aspect_GridType     aType = aViewer->GridType();
   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
-
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
   Standard_Integer anIter = 1;
   for (; anIter < theArgNb; ++anIter)
   {
     const char* aValue = theArgVec[anIter];
-    if (*aValue == 'r')
+    if (anUpdateTool.parseRedrawMode (aValue))
+    {
+      continue;
+    }
+    else if (*aValue == 'r')
     {
       aType = Aspect_GT_Rectangular;
     }
@@ -4822,11 +5133,10 @@ static int VGrid (Draw_Interpretor& /*theDI*/,
     return 1;
   }
 
-  Quantity_Length anOriginX, anOriginY;
-  Quantity_PlaneAngle aRotAngle;
+  Standard_Real anOriginX, anOriginY, aRotAngle;
   if (aType == Aspect_GT_Rectangular)
   {
-    Quantity_Length aRStepX, aRStepY;
+    Standard_Real aRStepX, aRStepY;
     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
 
     anOriginX = Draw::Atof (theArgVec[anIter++]);
@@ -4842,7 +5152,7 @@ static int VGrid (Draw_Interpretor& /*theDI*/,
   }
   else if (aType == Aspect_GT_Circular)
   {
-    Quantity_Length aRadiusStep;
+    Standard_Real aRadiusStep;
     Standard_Integer aDivisionNumber;
     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
 
@@ -5002,8 +5312,8 @@ static int VConvert (Draw_Interpretor& theDI,
   {
     switch (aMode)
     {
-      case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
-      case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
+      case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
+      case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
       default:
         std::cerr << "Error: wrong arguments! See usage:\n";
         theDI.PrintHelp (theArgVec[0]);
@@ -5027,7 +5337,7 @@ static int VConvert (Draw_Interpretor& theDI,
         return 0;
 
       case Window :
-        aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
+        aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
         return 0;
 
@@ -5352,6 +5662,7 @@ static int VCaps (Draw_Interpretor& theDI,
     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
+    theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
     return 0;
   }
 
@@ -5417,6 +5728,20 @@ static int VCaps (Draw_Interpretor& theDI,
       }
       aCaps->contextNoAccel = toEnable;
     }
+    else if (anArgCase == "-winbuffer"
+          || anArgCase == "-windowbuffer"
+          || anArgCase == "-usewinbuffer"
+          || anArgCase == "-usewindowbuffer"
+          || anArgCase == "-usesystembuffer")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->useSystemBuffer = toEnable;
+    }
     else if (anArgCase == "-accel"
           || anArgCase == "-acceleration")
     {
@@ -5549,8 +5874,8 @@ static int VReadPixel (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
-  Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
+  Image_Format         aFormat     = Image_Format_RGBA;
+  Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
 
   Standard_Integer aWidth, aHeight;
   aView->Window()->Size (aWidth, aHeight);
@@ -5566,39 +5891,40 @@ static int VReadPixel (Draw_Interpretor& theDI,
   Standard_Boolean toShowHls  = Standard_False;
   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
   {
-    const char* aParam = theArgVec[anIter];
-    if ( strcasecmp( aParam, "rgb" ) == 0 )
+    TCollection_AsciiString aParam (theArgVec[anIter]);
+    aParam.LowerCase();
+    if (aParam == "rgb")
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
+      aFormat     = Image_Format_RGB;
       aBufferType = Graphic3d_BT_RGB;
     }
-    else if ( strcasecmp( aParam, "hls" ) == 0 )
+    else if (aParam == "hls")
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
+      aFormat     = Image_Format_RGB;
       aBufferType = Graphic3d_BT_RGB;
       toShowHls   = Standard_True;
     }
-    else if ( strcasecmp( aParam, "rgbf" ) == 0 )
+    else if (aParam == "rgbf")
     {
-      aFormat     = Image_PixMap::ImgRGBF;
+      aFormat     = Image_Format_RGBF;
       aBufferType = Graphic3d_BT_RGB;
     }
-    else if ( strcasecmp( aParam, "rgba" ) == 0 )
+    else if (aParam == "rgba")
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+      aFormat     = Image_Format_RGBA;
       aBufferType = Graphic3d_BT_RGBA;
     }
-    else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
+    else if (aParam == "rgbaf")
     {
-      aFormat     = Image_PixMap::ImgRGBAF;
+      aFormat     = Image_Format_RGBAF;
       aBufferType = Graphic3d_BT_RGBA;
     }
-    else if ( strcasecmp( aParam, "depth" ) == 0 )
+    else if (aParam == "depth")
     {
-      aFormat     = Image_PixMap::ImgGrayF;
+      aFormat     = Image_Format_GrayF;
       aBufferType = Graphic3d_BT_Depth;
     }
-    else if ( strcasecmp( aParam, "name" ) == 0 )
+    else if (aParam == "name")
     {
       toShowName = Standard_True;
     }
@@ -5616,17 +5942,16 @@ static int VReadPixel (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Quantity_Parameter anAlpha;
-  Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
+  Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
   if (toShowName)
   {
     if (aBufferType == Graphic3d_BT_RGBA)
     {
-      theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
+      theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
     }
     else
     {
-      theDI << Quantity_Color::StringName (aColor.Name());
+      theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
     }
   }
   else
@@ -5638,22 +5963,22 @@ static int VReadPixel (Draw_Interpretor& theDI,
       {
         if (toShowHls)
         {
-          theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
+          theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
         }
         else
         {
-          theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
+          theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
         }
         break;
       }
       case Graphic3d_BT_RGBA:
       {
-        theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
+        theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
         break;
       }
       case Graphic3d_BT_Depth:
       {
-        theDI << aColor.Red();
+        theDI << aColor.GetRGB().Red();
         break;
       }
     }
@@ -5814,206 +6139,926 @@ static Standard_Integer VMoveTo (Draw_Interpretor& di,
   return 0;
 }
 
+namespace
+{
+  //! Global map storing all animations registered in ViewerTest.
+  static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
+
+  //! The animation calling the Draw Harness command.
+  class ViewerTest_AnimationProc : public AIS_Animation
+  {
+  public:
+
+    //! Main constructor.
+    ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
+                              Draw_Interpretor* theDI,
+                              const TCollection_AsciiString& theCommand)
+    : AIS_Animation (theAnimationName),
+      myDrawInter(theDI),
+      myCommand  (theCommand)
+    {
+      //
+    }
+
+  protected:
+
+    //! Evaluate the command.
+    virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
+    {
+      TCollection_AsciiString aCmd = myCommand;
+      replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
+      replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
+      replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
+      replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
+      replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
+      myDrawInter->Eval (aCmd.ToCString());
+    }
+
+    //! Find the keyword in the command and replace it with value.
+    //! @return the position of the keyword to pass value
+    void replace (TCollection_AsciiString&       theCmd,
+                  const TCollection_AsciiString& theKey,
+                  const TCollection_AsciiString& theVal)
+    {
+      TCollection_AsciiString aCmd (theCmd);
+      aCmd.LowerCase();
+      const Standard_Integer aPos = aCmd.Search (theKey);
+      if (aPos == -1)
+      {
+        return;
+      }
+
+      TCollection_AsciiString aPart1, aPart2;
+      Standard_Integer aPart1To = aPos - 1;
+      if (aPart1To >= 1
+       && aPart1To <= theCmd.Length())
+      {
+        aPart1 = theCmd.SubString (1, aPart1To);
+      }
+
+      Standard_Integer aPart2From = aPos + theKey.Length();
+      if (aPart2From >= 1
+       && aPart2From <= theCmd.Length())
+      {
+        aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
+      }
+
+      theCmd = aPart1 + theVal + aPart2;
+    }
+
+  protected:
+
+    Draw_Interpretor*       myDrawInter;
+    TCollection_AsciiString myCommand;
+
+  };
+
+  //! Replace the animation with the new one.
+  static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
+                                Handle(AIS_Animation)&       theAnimation,
+                                const Handle(AIS_Animation)& theAnimationNew)
+  {
+    theAnimationNew->CopyFrom (theAnimation);
+    if (!theParentAnimation.IsNull())
+    {
+      theParentAnimation->Replace (theAnimation, theAnimationNew);
+    }
+    else
+    {
+      ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
+      ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
+    }
+    theAnimation = theAnimationNew;
+  }
+
+  //! Parse the point.
+  static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
+  {
+    const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
+    if (!anXYZ[0].IsRealValue()
+     || !anXYZ[1].IsRealValue()
+     || !anXYZ[2].IsRealValue())
+    {
+      return Standard_False;
+    }
+
+    thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
+    return Standard_True;
+  }
+
+  //! Parse the quaternion.
+  static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
+  {
+    const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
+    if (!anXYZW[0].IsRealValue()
+     || !anXYZW[1].IsRealValue()
+     || !anXYZW[2].IsRealValue()
+     || !anXYZW[3].IsRealValue())
+    {
+      return Standard_False;
+    }
+
+    theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
+    return Standard_True;
+  }
+
+}
+
 //=================================================================================================
 //function : VViewParams
 //purpose  : Gets or sets AIS View characteristics
 //=================================================================================================
 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
 {
-  Handle(V3d_View) anAISView = ViewerTest::CurrentView();
-  if (anAISView.IsNull())
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
     return 1;
   }
 
+  Standard_Boolean toSetProj     = Standard_False;
+  Standard_Boolean toSetUp       = Standard_False;
+  Standard_Boolean toSetAt       = Standard_False;
+  Standard_Boolean toSetEye      = Standard_False;
+  Standard_Boolean toSetScale    = Standard_False;
+  Standard_Boolean toSetSize     = Standard_False;
+  Standard_Boolean toSetCenter2d = Standard_False;
+  Standard_Real    aViewScale = aView->Scale();
+  Standard_Real    aViewSize  = 1.0;
+  Graphic3d_Vec2i  aCenter2d;
+  gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
+  aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
+  aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
+  aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
+  aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
   if (theArgsNb == 1)
   {
     // print all of the available view parameters
-    Quantity_Factor anAISViewScale = anAISView->Scale();
-
-    Standard_Real anAISViewProjX = 0.0;
-    Standard_Real anAISViewProjY = 0.0;
-    Standard_Real anAISViewProjZ = 0.0;
-    anAISView->Proj (anAISViewProjX, anAISViewProjY, anAISViewProjZ);
-
-    Standard_Real anAISViewUpX = 0.0;
-    Standard_Real anAISViewUpY = 0.0;
-    Standard_Real anAISViewUpZ = 0.0;
-    anAISView->Up (anAISViewUpX, anAISViewUpY, anAISViewUpZ);
-
-    Standard_Real anAISViewAtX = 0.0;
-    Standard_Real anAISViewAtY = 0.0;
-    Standard_Real anAISViewAtZ = 0.0;
-    anAISView->At (anAISViewAtX, anAISViewAtY, anAISViewAtZ);
-
-    Standard_Real anAISViewEyeX = 0.0;
-    Standard_Real anAISViewEyeY = 0.0;
-    Standard_Real anAISViewEyeZ = 0.0;
-    anAISView->Eye (anAISViewEyeX, anAISViewEyeY, anAISViewEyeZ);
-
-    theDi << "Scale of current view: " << anAISViewScale << "\n";
-    theDi << "Proj on X : " << anAISViewProjX << "; on Y: " << anAISViewProjY << "; on Z: " << anAISViewProjZ << "\n";
-    theDi << "Up on X : " << anAISViewUpX << "; on Y: " << anAISViewUpY << "; on Z: " << anAISViewUpZ << "\n";
-    theDi << "At on X : " << anAISViewAtX << "; on Y: " << anAISViewAtY << "; on Z: " << anAISViewAtZ << "\n";
-    theDi << "Eye on X : " << anAISViewEyeX << "; on Y: " << anAISViewEyeY << "; on Z: " << anAISViewEyeZ << "\n";
+    char aText[4096];
+    Sprintf (aText,
+             "Scale: %g\n"
+             "Proj:  %12g %12g %12g\n"
+             "Up:    %12g %12g %12g\n"
+             "At:    %12g %12g %12g\n"
+             "Eye:   %12g %12g %12g\n",
+              aViewScale,
+              aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
+              aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
+              aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
+              aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
+    theDi << aText;
     return 0;
   }
 
-  // -------------------------
-  //  Parse options and values
-  // -------------------------
-
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfKeysByValues;
-  TCollection_AsciiString aParseKey;
-  for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
   {
-    TCollection_AsciiString anArg (theArgVec [anArgIt]);
-
-    if (anArg.Value (1) == '-' && !anArg.IsRealValue())
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      aParseKey = anArg;
-      aParseKey.Remove (1);
-      aParseKey.UpperCase();
-      aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
       continue;
     }
+    else if (anArg == "-cmd"
+          || anArg == "-command"
+          || anArg == "-args")
+    {
+      char aText[4096];
+      Sprintf (aText,
+               "-scale %g "
+               "-proj %g %g %g "
+               "-up %g %g %g "
+               "-at %g %g %g\n",
+                aViewScale,
+                aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
+                aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
+                aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
+      theDi << aText;
+    }
+    else if (anArg == "-scale"
+          || anArg == "-size")
+    {
+      if (anArgIter + 1 < theArgsNb
+       && *theArgVec[anArgIter + 1] != '-')
+      {
+        const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
+        if (aValueArg.IsRealValue())
+        {
+          ++anArgIter;
+          if (anArg == "-scale")
+          {
+            toSetScale = Standard_True;
+            aViewScale = aValueArg.RealValue();
+          }
+          else if (anArg == "-size")
+          {
+            toSetSize = Standard_True;
+            aViewSize = aValueArg.RealValue();
+          }
+          continue;
+        }
+      }
+      if (anArg == "-scale")
+      {
+        theDi << "Scale: " << aView->Scale() << "\n";
+      }
+      else if (anArg == "-size")
+      {
+        Graphic3d_Vec2d aSizeXY;
+        aView->Size (aSizeXY.x(), aSizeXY.y());
+        theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
+      }
+    }
+    else if (anArg == "-eye"
+          || anArg == "-at"
+          || anArg == "-up"
+          || anArg == "-proj")
+    {
+      if (anArgIter + 3 < theArgsNb)
+      {
+        gp_XYZ anXYZ;
+        if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
+        {
+          anArgIter += 3;
+          if (anArg == "-eye")
+          {
+            toSetEye = Standard_True;
+            aViewEye = anXYZ;
+          }
+          else if (anArg == "-at")
+          {
+            toSetAt = Standard_True;
+            aViewAt = anXYZ;
+          }
+          else if (anArg == "-up")
+          {
+            toSetUp = Standard_True;
+            aViewUp = anXYZ;
+          }
+          else if (anArg == "-proj")
+          {
+            toSetProj = Standard_True;
+            aViewProj = anXYZ;
+          }
+          continue;
+        }
+      }
 
-    if (aParseKey.IsEmpty())
+      if (anArg == "-eye")
+      {
+        theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
+      }
+      else if (anArg == "-at")
+      {
+        theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
+      }
+      else if (anArg == "-up")
+      {
+        theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
+      }
+      else if (anArg == "-proj")
+      {
+        theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
+      }
+    }
+    else if (anArg == "-center")
     {
-      std::cout << theArgVec[0] << ": values should be passed with key.\n";
-      std::cout << "Type help for more information.\n";
+      if (anArgIter + 2 < theArgsNb)
+      {
+        const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
+        const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
+        if (anX.IsIntegerValue()
+         && anY.IsIntegerValue())
+        {
+          toSetCenter2d = Standard_True;
+          aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
+        }
+      }
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << anArg << "'\n";
       return 1;
     }
+  }
 
-    aMapOfKeysByValues(aParseKey)->Append (anArg);
+  // change view parameters in proper order
+  if (toSetScale)
+  {
+    aView->SetScale (aViewScale);
+  }
+  if (toSetSize)
+  {
+    aView->SetSize (aViewSize);
+  }
+  if (toSetEye)
+  {
+    aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
+  }
+  if (toSetAt)
+  {
+    aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
+  }
+  if (toSetProj)
+  {
+    aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
+  }
+  if (toSetUp)
+  {
+    aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
+  }
+  if (toSetCenter2d)
+  {
+    aView->SetCenter (aCenter2d.x(), aCenter2d.y());
   }
 
-  // ---------------------------------------------
-  //  Change or print parameters, order plays role
-  // ---------------------------------------------
+  return 0;
+}
 
-  // Check arguments for validity
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfKeysByValues);
-  for (; aMapIt.More(); aMapIt.Next())
+//==============================================================================
+//function : VAnimation
+//purpose  :
+//==============================================================================
+static Standard_Integer VAnimation (Draw_Interpretor& theDI,
+                                    Standard_Integer  theArgNb,
+                                    const char**      theArgVec)
+{
+  Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  if (theArgNb < 2)
   {
-    const TCollection_AsciiString& aKey = aMapIt.Key();
-    const Handle(TColStd_HSequenceOfAsciiString)& aValues = aMapIt.Value();
-
-    if (!(aKey.IsEqual ("SCALE")  && (aValues->Length() == 1 || aValues->IsEmpty()))
-     && !(aKey.IsEqual ("SIZE")   && (aValues->Length() == 1 || aValues->IsEmpty()))
-     && !(aKey.IsEqual ("EYE")    && (aValues->Length() == 3 || aValues->IsEmpty()))
-     && !(aKey.IsEqual ("AT")     && (aValues->Length() == 3 || aValues->IsEmpty()))
-     && !(aKey.IsEqual ("UP")     && (aValues->Length() == 3 || aValues->IsEmpty()))
-     && !(aKey.IsEqual ("PROJ")   && (aValues->Length() == 3 || aValues->IsEmpty()))
-     && !(aKey.IsEqual ("CENTER") &&  aValues->Length() == 2))
-    {
-      TCollection_AsciiString aLowerKey;
-      aLowerKey  = "-";
-      aLowerKey += aKey;
-      aLowerKey.LowerCase();
-      std::cout << theArgVec[0] << ": " << aLowerKey << " is unknown option, or number of arguments is invalid.\n";
-      std::cout << "Type help for more information.\n";
-      return 1;
+    for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
+         anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
+    {
+      theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
     }
+    return 0;
+  }
+  if (aCtx.IsNull())
+  {
+    std::cout << "Error: no active view\n";
+    return 1;
   }
 
-  Handle(TColStd_HSequenceOfAsciiString) aValues;
+  Standard_Integer anArgIter = 1;
+  TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
+  if (aNameArg.IsEmpty())
+  {
+    std::cout << "Syntax error: animation name is not defined.\n";
+    return 1;
+  }
+
+  TCollection_AsciiString aNameArgLower = aNameArg;
+  aNameArgLower.LowerCase();
+  if (aNameArgLower == "-reset"
+   || aNameArgLower == "-clear")
+  {
+    ViewerTest_AnimationTimelineMap.Clear();
+    return 0;
+  }
+  else if (aNameArg.Value (1) == '-')
+  {
+    std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
+    return 1;
+  }
+
+  const char* aNameSplitter = "/";
+  Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
+  if (aSplitPos == -1)
+  {
+    aNameSplitter = ".";
+    aSplitPos = aNameArg.Search (aNameSplitter);
+  }
+
+  // find existing or create a new animation by specified name within syntax "parent.child".
+  Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
+  for (; !aNameArg.IsEmpty();)
+  {
+    TCollection_AsciiString aNameParent;
+    if (aSplitPos != -1)
+    {
+      if (aSplitPos == aNameArg.Length())
+      {
+        std::cout << "Syntax error: animation name is not defined.\n";
+        return 1;
+      }
+
+      aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
+      aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
+
+      aSplitPos = aNameArg.Search (aNameSplitter);
+    }
+    else
+    {
+      aNameParent = aNameArg;
+      aNameArg.Clear();
+    }
+
+    if (anAnimation.IsNull())
+    {
+      if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
+      {
+        anAnimation = new AIS_Animation (aNameParent);
+        ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
+      }
+      aRootAnimation = anAnimation;
+    }
+    else
+    {
+      aParentAnimation = anAnimation;
+      anAnimation = aParentAnimation->Find (aNameParent);
+      if (anAnimation.IsNull())
+      {
+        anAnimation = new AIS_Animation (aNameParent);
+        aParentAnimation->Add (anAnimation);
+      }
+    }
+  }
+
+  if (anArgIter >= theArgNb)
+  {
+    // just print the list of children
+    for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
+    {
+      theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
+    }
+    return 0;
+  }
+
+  // animation parameters
+  Standard_Boolean toPlay = Standard_False;
+  Standard_Real aPlaySpeed     = 1.0;
+  Standard_Real aPlayStartTime = anAnimation->StartPts();
+  Standard_Real aPlayDuration  = anAnimation->Duration();
+  Standard_Integer aFpsNum     = 0;
+  Standard_Integer aFpsDen     = 1;
+  Standard_Boolean isFreeCamera = Standard_False;
+  Standard_Boolean isLockLoop   = Standard_False;
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  for (; anArgIter < theArgNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    // general options
+    if (anArg == "-reset"
+     || anArg == "-clear")
+    {
+      anAnimation->Clear();
+    }
+    else if (anArg == "-remove"
+          || anArg == "-del"
+          || anArg == "-delete")
+    {
+      if (!aParentAnimation.IsNull())
+      {
+        ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
+      }
+      else
+      {
+        aParentAnimation->Remove (anAnimation);
+      }
+    }
+    // playback options
+    else if (anArg == "-play")
+    {
+      toPlay = Standard_True;
+      if (++anArgIter < theArgNb)
+      {
+        if (*theArgVec[anArgIter] == '-')
+        {
+          --anArgIter;
+          continue;
+        }
+        aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
+
+        if (++anArgIter < theArgNb)
+        {
+          if (*theArgVec[anArgIter] == '-')
+          {
+            --anArgIter;
+            continue;
+          }
+          aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
+        }
+      }
+    }
+    else if (anArg == "-resume")
+    {
+      toPlay = Standard_True;
+      aPlayStartTime = anAnimation->ElapsedTime();
+      if (++anArgIter < theArgNb)
+      {
+        if (*theArgVec[anArgIter] == '-')
+        {
+          --anArgIter;
+          continue;
+        }
+
+        aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
+      }
+    }
+    else if (anArg == "-playspeed"
+          || anArg == "-speed")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+      aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
+    }
+    else if (anArg == "-lock"
+          || anArg == "-lockloop"
+          || anArg == "-playlockloop")
+    {
+      isLockLoop = Standard_True;
+    }
+    else if (anArg == "-freecamera"
+          || anArg == "-playfreecamera"
+          || anArg == "-freelook")
+    {
+      isFreeCamera = Standard_True;
+    }
+    else if (anArg == "-fps")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
+      Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
+      if (aSplitIndex == 0)
+      {
+        aFpsNum = aFpsArg.IntegerValue();
+      }
+      else
+      {
+        const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
+        aFpsArg.Split (aFpsArg.Length() - 1);
+        const TCollection_AsciiString aNumStr = aFpsArg;
+        aFpsNum = aNumStr.IntegerValue();
+        aFpsDen = aDenStr.IntegerValue();
+        if (aFpsDen < 1)
+        {
+          std::cout << "Syntax error at " << anArg << ".\n";
+          return 1;
+        }
+      }
+    }
+    // animation definition options
+    else if (anArg == "-start"
+          || anArg == "-starttime"
+          || anArg == "-startpts")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
+      aRootAnimation->UpdateTotalDuration();
+    }
+    else if (anArg == "-end"
+          || anArg == "-endtime"
+          || anArg == "-endpts")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
+      aRootAnimation->UpdateTotalDuration();
+    }
+    else if (anArg == "-dur"
+          || anArg == "-duration")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
+      aRootAnimation->UpdateTotalDuration();
+    }
+    else if (anArg == "-command"
+          || anArg == "-cmd"
+          || anArg == "-invoke"
+          || anArg == "-eval"
+          || anArg == "-proc")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
+      replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
+    }
+    else if (anArg == "-objecttrsf"
+          || anArg == "-objectransformation"
+          || anArg == "-objtransformation"
+          || anArg == "-objtrsf"
+          || anArg == "-object"
+          || anArg == "-obj")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      TCollection_AsciiString anObjName (theArgVec[anArgIter]);
+      const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
+      if (!aMapOfAIS.IsBound2 (anObjName))
+      {
+        std::cout << "Syntax error: wrong object name at " << anArg << "\n";
+        return 1;
+      }
+
+      Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
+      gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
+      gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
+      gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
+      Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
+      Standard_Boolean isTrsfSet = Standard_False;
+      Standard_Integer aTrsfArgIter = anArgIter + 1;
+      for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
+      {
+        TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
+        aTrsfArg.LowerCase();
+        const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
+        if (aTrsfArg.StartsWith ("-rotation")
+         || aTrsfArg.StartsWith ("-rot"))
+        {
+          isTrsfSet = Standard_True;
+          if (aTrsfArgIter + 4 >= theArgNb
+          || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aTrsfArgIter += 4;
+        }
+        else if (aTrsfArg.StartsWith ("-location")
+              || aTrsfArg.StartsWith ("-loc"))
+        {
+          isTrsfSet = Standard_True;
+          if (aTrsfArgIter + 3 >= theArgNb
+          || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aTrsfArgIter += 3;
+        }
+        else if (aTrsfArg.StartsWith ("-scale"))
+        {
+          isTrsfSet = Standard_True;
+          if (++aTrsfArgIter >= theArgNb)
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+
+          const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
+          if (!aScaleStr.IsRealValue())
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aScales[anIndex] = aScaleStr.RealValue();
+        }
+        else
+        {
+          anArgIter = aTrsfArgIter - 1;
+          break;
+        }
+      }
+      if (!isTrsfSet)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+      else if (aTrsfArgIter >= theArgNb)
+      {
+        anArgIter = theArgNb;
+      }
+
+      aTrsfs[0].SetRotation        (aRotQuats[0]);
+      aTrsfs[1].SetRotation        (aRotQuats[1]);
+      aTrsfs[0].SetTranslationPart (aLocPnts[0]);
+      aTrsfs[1].SetTranslationPart (aLocPnts[1]);
+      aTrsfs[0].SetScaleFactor     (aScales[0]);
+      aTrsfs[1].SetScaleFactor     (aScales[1]);
+
+      Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
+      replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
+    }
+    else if (anArg == "-viewtrsf"
+          || anArg == "-view")
+    {
+      Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
+      if (aCamAnimation.IsNull())
+      {
+        aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
+        replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
+      }
+
+      Handle(Graphic3d_Camera) aCams[2] =
+      {
+        new Graphic3d_Camera (aCamAnimation->View()->Camera()),
+        new Graphic3d_Camera (aCamAnimation->View()->Camera())
+      };
+
+      Standard_Boolean isTrsfSet = Standard_False;
+      Standard_Integer aViewArgIter = anArgIter + 1;
+      for (; aViewArgIter < theArgNb; ++aViewArgIter)
+      {
+        TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
+        aViewArg.LowerCase();
+        const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
+        if (aViewArg.StartsWith ("-scale"))
+        {
+          isTrsfSet = Standard_True;
+          if (++aViewArgIter >= theArgNb)
+          {
+            std::cout << "Syntax error at " << anArg << ".\n";
+            return 1;
+          }
+
+          const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
+          if (!aScaleStr.IsRealValue())
+          {
+            std::cout << "Syntax error at " << aViewArg << ".\n";
+            return 1;
+          }
+          Standard_Real aScale = aScaleStr.RealValue();
+          aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
+          aCams[anIndex]->SetScale (aScale);
+        }
+        else if (aViewArg.StartsWith ("-eye")
+              || aViewArg.StartsWith ("-center")
+              || aViewArg.StartsWith ("-at")
+              || aViewArg.StartsWith ("-up"))
+        {
+          isTrsfSet = Standard_True;
+          gp_XYZ anXYZ;
+          if (aViewArgIter + 3 >= theArgNb
+          || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
+          {
+            std::cout << "Syntax error at " << aViewArg << ".\n";
+            return 1;
+          }
+          aViewArgIter += 3;
+
+          if (aViewArg.StartsWith ("-eye"))
+          {
+            aCams[anIndex]->SetEye (anXYZ);
+          }
+          else if (aViewArg.StartsWith ("-center")
+                || aViewArg.StartsWith ("-at"))
+          {
+            aCams[anIndex]->SetCenter (anXYZ);
+          }
+          else if (aViewArg.StartsWith ("-up"))
+          {
+            aCams[anIndex]->SetUp (anXYZ);
+          }
+        }
+        else
+        {
+          anArgIter = aViewArgIter - 1;
+          break;
+        }
+      }
+      if (!isTrsfSet)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+      else if (aViewArgIter >= theArgNb)
+      {
+        anArgIter = theArgNb;
+      }
 
-  // Change view parameters in proper order
-  if (aMapOfKeysByValues.Find ("SCALE", aValues))
-  {
-    if (aValues->IsEmpty())
-    {
-      theDi << "Scale: " << anAISView->Scale() << "\n";
+      aCamAnimation->SetCameraStart(aCams[0]);
+      aCamAnimation->SetCameraEnd  (aCams[1]);
     }
     else
     {
-      anAISView->SetScale (aValues->Value(1).RealValue());
+      std::cout << "Syntax error at " << anArg << ".\n";
+      return 1;
     }
   }
-  if (aMapOfKeysByValues.Find ("SIZE", aValues))
+
+  if (!toPlay)
   {
-    if (aValues->IsEmpty())
-    {
-      Standard_Real aSizeX = 0.0;
-      Standard_Real aSizeY = 0.0;
-      anAISView->Size (aSizeX, aSizeY);
-      theDi << "Size X: " << aSizeX << " Y: " << aSizeY << "\n";
-    }
-    else
-    {
-      anAISView->SetSize (aValues->Value(1).RealValue());
-    }
+    return 0;
   }
-  if (aMapOfKeysByValues.Find ("EYE", aValues))
+
+  // Start animation timeline and process frame updating.
+  TheIsAnimating = Standard_True;
+  const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
+  Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
+  anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
+  if (isFreeCamera)
   {
-    if (aValues->IsEmpty())
-    {
-      Standard_Real anEyeX = 0.0;
-      Standard_Real anEyeY = 0.0;
-      Standard_Real anEyeZ = 0.0;
-      anAISView->Eye (anEyeX, anEyeY, anEyeZ);
-      theDi << "Eye X: " << anEyeX << " Y: " << anEyeY << " Z: " << anEyeZ << "\n";
-    }
-    else
-    {
-      anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
-    }
+    aView->Camera()->Copy (aCameraBack);
   }
-  if (aMapOfKeysByValues.Find ("AT", aValues))
+
+  const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
+  if (aFpsNum <= 0)
   {
-    if (aValues->IsEmpty())
-    {
-      Standard_Real anAtX = 0.0;
-      Standard_Real anAtY = 0.0;
-      Standard_Real anAtZ = 0.0;
-      anAISView->At (anAtX, anAtY, anAtZ);
-      theDi << "At X: " << anAtX << " Y: " << anAtY << " Z: " << anAtZ << "\n";
-    }
-    else
+    while (!anAnimation->IsStopped())
     {
-      anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      aCameraBack->Copy (aView->Camera());
+      const Standard_Real aPts = anAnimation->UpdateTimer();
+      if (isFreeCamera)
+      {
+        aView->Camera()->Copy (aCameraBack);
+      }
+
+      if (aPts >= anUpperPts)
+      {
+        anAnimation->Pause();
+        break;
+      }
+
+      if (aView->IsInvalidated())
+      {
+        aView->Redraw();
+      }
+      else
+      {
+        aView->RedrawImmediate();
+      }
+
+      if (!isLockLoop)
+      {
+        // handle user events
+        theDI.Eval ("after 1 set waiter 1");
+        theDI.Eval ("vwait waiter");
+      }
+      if (!TheIsAnimating)
+      {
+        anAnimation->Pause();
+        theDI << aPts;
+        break;
+      }
     }
-  }
-  if (aMapOfKeysByValues.Find ("PROJ", aValues))
-  {
-    if (aValues->IsEmpty())
+
+    if (aView->IsInvalidated())
     {
-      Standard_Real aProjX = 0.0;
-      Standard_Real aProjY = 0.0;
-      Standard_Real aProjZ = 0.0;
-      anAISView->Proj (aProjX, aProjY, aProjZ);
-      theDi << "Proj X: " << aProjX << " Y: " << aProjY << " Z: " << aProjZ << "\n";
+      aView->Redraw();
     }
     else
     {
-      anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      aView->RedrawImmediate();
     }
   }
-  if (aMapOfKeysByValues.Find ("UP", aValues))
+  else
   {
-    if (aValues->IsEmpty())
-    {
-      Standard_Real anUpX = 0.0;
-      Standard_Real anUpY = 0.0;
-      Standard_Real anUpZ = 0.0;
-      anAISView->Up (anUpX, anUpY, anUpZ);
-      theDi << "Up X: " << anUpX << " Y: " << anUpY << " Z: " << anUpZ << "\n";
-    }
-    else
+    OSD_Timer aPerfTimer;
+    aPerfTimer.Start();
+
+    // Manage frame-rated animation here
+    Standard_Real aPts = aPlayStartTime;
+    int64_t aNbFrames = 0;
+    for (; aPts <= anUpperPts;)
     {
-      anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
+      aPts = aPlayStartTime + aRecPts;
+      ++aNbFrames;
+      if (!anAnimation->Update (aPts))
+      {
+        break;
+      }
+
+      aView->Redraw();
     }
-  }
-  if (aMapOfKeysByValues.Find ("CENTER", aValues))
-  {
-    anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue());
+
+    aPerfTimer.Stop();
+    anAnimation->Stop();
+    const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
+    theDI << "Average FPS: " << aRecFps << "\n"
+          << "Nb. Frames: "  << Standard_Real(aNbFrames);
+
+    aView->Redraw();
   }
 
+  aView->SetImmediateUpdate (wasImmediateUpdate);
+  TheIsAnimating = Standard_False;
   return 0;
 }
 
+
 //=======================================================================
 //function : VChangeSelected
 //purpose  : Adds the shape to selection or remove one from it
@@ -6046,7 +7091,7 @@ static Standard_Integer VChangeSelected (Draw_Interpretor& di,
       return 1;
     }
 
-    aContext->AddOrRemoveSelected(anAISObject);
+    aContext->AddOrRemoveSelected(anAISObject, Standard_True);
   }
   return 0;
 }
@@ -6093,7 +7138,7 @@ static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
     di << "use 'vinit' command before " << argv[0] << "\n";
     return 1;
   }
-  aContext->CloseAllContexts(Standard_False);
+
   di << aContext->PurgeDisplay() << "\n";
   return 0;
 }
@@ -7626,8 +8671,8 @@ static int VLight (Draw_Interpretor& theDi,
     return 1;
   }
 
-  Standard_Real        anXYZ[3];
-  Quantity_Coefficient anAtten[2];
+  Standard_Real anXYZ[3]   = {};
+  Standard_Real anAtten[2] = {};
   if (theArgsNb < 2)
   {
     // print lights info
@@ -8170,16 +9215,28 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
     }
     theDI << "\n";
-    theDI << "msaa:         " <<  aParams.NbMsaaSamples                               << "\n";
-    theDI << "rayDepth:     " <<  aParams.RaytracingDepth                             << "\n";
-    theDI << "fsaa:         " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
-    theDI << "shadows:      " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
-    theDI << "reflections:  " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
-    theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
-    theDI << "GI:           " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
-    theDI << "blocked RNG:  " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
-    theDI << "iss:          " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
-    theDI << "iss debug:    " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
+    theDI << "transparency:  ";
+    switch (aParams.TransparencyMethod)
+    {
+      case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
+      case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
+                                                << TCollection_AsciiString (aParams.OitDepthFactor); break;
+    }
+    theDI << "\n";
+    theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
+    theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
+    theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
+    theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
+    theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
+    theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
+    theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
+    theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
+    theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
+    theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
+    theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
+    theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
+    theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
+    theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
     theDI << "shadingModel: ";
     switch (aView->ShadingModel())
     {
@@ -8275,6 +9332,76 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         aParams.NbMsaaSamples = aNbSamples;
       }
     }
+    else if (aFlag == "-oit")
+    {
+      if (toPrint)
+      {
+        if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
+        {
+          theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
+        }
+        else
+        {
+          theDI << "off" << " ";
+        }
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aParam = theArgVec[anArgIter];
+      aParam.LowerCase();
+      if (aParam.IsRealValue())
+      {
+        const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
+        if (aWeight < 0.f || aWeight > 1.f)
+        {
+          std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
+          return 1;
+        }
+
+        aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
+        aParams.OitDepthFactor     = aWeight;
+      }
+      else if (aParam == "off")
+      {
+        aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
+      }
+      else
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+    }
+    else if (aFlag == "-rendscale"
+          || aFlag == "-renderscale"
+          || aFlag == "-renderresolutionscale")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.RenderResolutionScale << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
+      if (aScale < 0.01)
+      {
+        std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
+        return 1;
+      }
+      else
+      {
+        aParams.RenderResolutionScale = Standard_ShortReal(aScale);
+      }
+    }
     else if (aFlag == "-raydepth"
           || aFlag == "-ray_depth")
     {
@@ -8405,6 +9532,37 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       }
       aParams.CoherentPathTracingMode = toEnable;
     }
+    else if (aFlag == "-maxrad")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.RadianceClampingValue << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
+      if (!aMaxRadStr.IsRealValue())
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
+      if (aMaxRadiance <= 0.0)
+      {
+        std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
+        return 1;
+      }
+      else
+      {
+        aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
+      }
+    }
     else if (aFlag == "-iss")
     {
       if (toPrint)
@@ -8437,6 +9595,32 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       }
       aParams.ShowSamplingTiles = toEnable;
     }
+    else if (aFlag == "-nbtiles")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.NbRayTracingTiles << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
+
+      if (aNbTiles < 64)
+      {
+        std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
+        std::cerr << "Specify value in range [64, 1024].\n";
+        return 1;
+      }
+      else
+      {
+        aParams.NbRayTracingTiles = aNbTiles;
+      }
+    }
     else if (aFlag == "-env")
     {
       if (toPrint)
@@ -8453,6 +9637,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       }
       aParams.UseEnvironmentMapBackground = toEnable;
     }
+    else if (aFlag == "-twoside")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.TwoSidedBsdfModels = toEnable;
+    }
     else if (aFlag == "-shademodel"
           || aFlag == "-shadingmodel"
           || aFlag == "-shading")
@@ -8481,42 +9681,147 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       {
         aView->SetShadingModel (V3d_COLOR);
       }
-      else if (aMode == "flat"
-            || aMode == "facet")
+      else if (aMode == "flat"
+            || aMode == "facet")
+      {
+        aView->SetShadingModel (V3d_FLAT);
+      }
+      else if (aMode == "gouraud"
+            || aMode == "vertex"
+            || aMode == "vert")
+      {
+        aView->SetShadingModel (V3d_GOURAUD);
+      }
+      else if (aMode == "phong"
+            || aMode == "fragment"
+            || aMode == "frag"
+            || aMode == "pixel")
+      {
+        aView->SetShadingModel (V3d_PHONG);
+      }
+      else
+      {
+        std::cout << "Error: unknown shading model '" << aMode << "'\n";
+        return 1;
+      }
+    }
+    else if (aFlag == "-resolution")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aResolution (theArgVec[anArgIter]);
+      if (aResolution.IsIntegerValue())
+      {
+        aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
+      }
+      else
+      {
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
+        return 1;
+      }
+    }
+    else if (aFlag == "-rebuildglsl"
+          || aFlag == "-rebuild")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+          && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.RebuildRayTracingShaders = toEnable;
+    }
+    else if (aFlag == "-focal")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aParam (theArgVec[anArgIter]);
+      if (aParam.IsRealValue())
+      {
+        float aFocalDist = static_cast<float> (aParam.RealValue());
+        if (aFocalDist < 0)
+        {
+          std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
+          return 1;
+        }
+        aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
+      }
+      else
+      {
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
+        return 1;
+      }
+    }
+    else if (aFlag == "-aperture")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aParam(theArgVec[anArgIter]);
+      if (aParam.IsRealValue())
+      {
+        float aApertureSize = static_cast<float> (aParam.RealValue());
+        if (aApertureSize < 0)
+        {
+          std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
+          return 1;
+        }
+        aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
+      }
+      else
       {
-        aView->SetShadingModel (V3d_FLAT);
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
+        return 1;
       }
-      else if (aMode == "gouraud"
-            || aMode == "vertex"
-            || aMode == "vert")
+    }
+    else if (aFlag == "-exposure")
+    {
+      if (++anArgIter >= theArgNb)
       {
-        aView->SetShadingModel (V3d_GOURAUD);
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
       }
-      else if (aMode == "phong"
-            || aMode == "fragment"
-            || aMode == "frag"
-            || aMode == "pixel")
+
+      TCollection_AsciiString anExposure (theArgVec[anArgIter]);
+      if (anExposure.IsRealValue())
       {
-        aView->SetShadingModel (V3d_PHONG);
+        aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
       }
       else
       {
-        std::cout << "Error: unknown shading model '" << aMode << "'\n";
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
         return 1;
       }
     }
-    else if (aFlag == "-resolution")
+    else if (aFlag == "-whitepoint")
     {
       if (++anArgIter >= theArgNb)
       {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
         return 1;
       }
 
-      TCollection_AsciiString aResolution (theArgVec[anArgIter]);
-      if (aResolution.IsIntegerValue())
+      TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
+      if (aWhitePoint.IsRealValue())
       {
-        aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
+        aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
       }
       else
       {
@@ -8524,22 +9829,30 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         return 1;
       }
     }
-    else if (aFlag == "-rebuildglsl"
-          || aFlag == "-rebuild")
+    else if (aFlag == "-tonemapping")
     {
-      if (toPrint)
+      if (++anArgIter >= theArgNb)
       {
-        theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
-        continue;
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
       }
 
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-          && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      TCollection_AsciiString aMode (theArgVec[anArgIter]);
+      aMode.LowerCase();
+
+      if (aMode == "disabled")
       {
-        --anArgIter;
+        aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
+      }
+      else if (aMode == "filmic")
+      {
+        aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
+      }
+      else
+      {
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
+        return 1;
       }
-      aParams.RebuildRayTracingShaders = toEnable;
     }
     else
     {
@@ -8576,7 +9889,7 @@ static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
     Standard_Boolean toExit = Standard_False;
 
     MSG aMsg;
-    while (PeekMessage (&aMsg, NULL, 0, 0, PM_REMOVE))
+    while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
     {
       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
       {
@@ -8584,7 +9897,7 @@ static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
       }
 
       TranslateMessage (&aMsg);
-      DispatchMessage  (&aMsg);
+      DispatchMessageW (&aMsg);
     }
 
     if (toExit)
@@ -8870,7 +10183,7 @@ static int VManipulator (Draw_Interpretor& theDi,
 
     aManipulator->Detach();
     aMapAIS.UnBind2 (aName);
-    ViewerTest::GetAISContext()->Remove (aManipulator);
+    ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
 
     return 0;
   }
@@ -9039,48 +10352,11 @@ static int VManipulator (Draw_Interpretor& theDi,
     aManipulator->Transform (aT);
   }
 
-  ViewerTest::GetAISContext()->Redisplay (aManipulator);
+  ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
 
   return 0;
 }
 
-//===============================================================================================
-//function : parseColor
-//purpose  :
-//===============================================================================================
-static Standard_Boolean parseColor (ViewerTest_CmdParser& theParser,
-                                    const std::string&    theOptionName,
-                                    Quantity_Color&       theColor)
-{
-  std::string aColorArg = theParser.Arg (theOptionName, 0);
-  if (std::isdigit (aColorArg[0]))
-  {
-    Graphic3d_Vec3d aColor = theParser.ArgVec3d (theOptionName);
-    if (aColor.x() < 0.0 || aColor.x() > 1.0
-      || aColor.y() < 0.0 || aColor.y() > 1.0
-      || aColor.z() < 0.0 || aColor.z() > 1.0)
-    {
-      std::cerr << "Error: RGB color values should be within range 0..1!\n";
-      return Standard_False;
-    }
-    theColor.SetValues (aColor.x(), aColor.y(), aColor.z(), Quantity_TOC_RGB);
-  }
-  else
-  {
-    Quantity_NameOfColor aName = Quantity_NOC_BLACK;
-    if (!Quantity_Color::ColorFromName (aColorArg.c_str(), aName))
-    {
-      std::cerr << "Name: " << theParser.Arg (theOptionName, 0)
-                << " does not correspond to any color in Quantity_NameOfColor!"
-                << std::endl;
-      return Standard_False;
-    }
-    theColor.SetValues (aName);
-  }
-
-  return Standard_True;
-}
-
 //===============================================================================================
 //function : VSelectionProperties
 //purpose  :
@@ -9096,78 +10372,399 @@ static int VSelectionProperties (Draw_Interpretor& theDi,
     return 1;
   }
 
-  ViewerTest_CmdParser aCmd;
+  Standard_Boolean toPrint  = theArgsNb == 1;
+  Standard_Boolean toRedraw = Standard_False;
+  Standard_Integer anArgIter = 1;
+  Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
+  if (anArgIter < theArgsNb)
+  {
+    TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
+    anArgFirst.LowerCase();
+    ++anArgIter;
+    if (anArgFirst == "dynhighlight"
+     || anArgFirst == "dynhilight"
+     || anArgFirst == "dynamichighlight"
+     || anArgFirst == "dynamichilight")
+    {
+      aType = Prs3d_TypeOfHighlight_Dynamic;
+    }
+    else if (anArgFirst == "localdynhighlight"
+          || anArgFirst == "localdynhilight"
+          || anArgFirst == "localdynamichighlight"
+          || anArgFirst == "localdynamichilight")
+    {
+      aType = Prs3d_TypeOfHighlight_LocalDynamic;
+    }
+    else if (anArgFirst == "selhighlight"
+          || anArgFirst == "selhilight"
+          || anArgFirst == "selectedhighlight"
+          || anArgFirst == "selectedhilight")
+    {
+      aType = Prs3d_TypeOfHighlight_Selected;
+    }
+    else if (anArgFirst == "localselhighlight"
+          || anArgFirst == "localselhilight"
+          || anArgFirst == "localselectedhighlight"
+          || anArgFirst == "localselectedhilight")
+    {
+      aType = Prs3d_TypeOfHighlight_LocalSelected;
+    }
+    else
+    {
+      --anArgIter;
+    }
+  }
+  for (; anArgIter < theArgsNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anArg == "-help")
+    {
+      theDi.PrintHelp (theArgVec[0]);
+      return 0;
+    }
+    else if (anArg == "-print")
+    {
+      toPrint = Standard_True;
+    }
+    else if (anArg == "-autoactivate")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (anArgIter + 1 < theArgsNb
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
+      {
+        ++anArgIter;
+      }
+      aCtx->SetAutoActivateSelection (toEnable);
+    }
+    else if (anArg == "-pickstrategy"
+          || anArg == "-pickingstrategy")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
+      }
 
-  aCmd.AddOption ("autoActivate");
-  aCmd.AddOption ("pixTol");
+      SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
+      TCollection_AsciiString aVal (theArgVec[anArgIter]);
+      aVal.LowerCase();
+      if (aVal == "first"
+       || aVal == "firstaccepted"
+       || aVal == "firstacceptable")
+      {
+        aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
+      }
+      else if (aVal == "topmost"
+            || aVal == "onlyTopmost")
+      {
+        aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
+      }
+      else
+      {
+        std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
+        return 1;
+      }
 
-  aCmd.AddOption ("selColor");
-  aCmd.AddOption ("hiColor");
-  aCmd.AddOption ("selTransp");
-  aCmd.AddOption ("hiTransp");
+      aCtx->SetPickingStrategy (aStrategy);
+    }
+    else if (anArg == "-pixtol"
+          && anArgIter + 1 < theArgsNb)
+    {
+      aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
+    }
+    else if ((anArg == "-mode"
+           || anArg == "-dispmode")
+          && anArgIter + 1 < theArgsNb)
+    {
+      if (aType == Prs3d_TypeOfHighlight_None)
+      {
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
+      }
 
-  aCmd.AddOption ("print");
+      const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetDisplayMode (aDispMode);
+      toRedraw = Standard_True;
+    }
+    else if (anArg == "-layer"
+          && anArgIter + 1 < theArgsNb)
+    {
+      if (aType == Prs3d_TypeOfHighlight_None)
+      {
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
+      }
 
-  aCmd.Parse (theArgsNb, theArgVec);
+      const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
+      if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
+      {
+        TColStd_SequenceOfInteger aLayers;
+        aCtx->CurrentViewer()->GetAllZLayers (aLayers);
+        if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
+        {
+          std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
+          return 1;
+        }
+      }
 
-  if (aCmd.HasOption ("help"))
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetZLayer (aNewLayer);
+      toRedraw = Standard_True;
+    }
+    else if (anArg == "-hicolor"
+          || anArg == "-selcolor"
+          || anArg == "-color")
+    {
+      if (anArg.StartsWith ("-hi"))
+      {
+        aType = Prs3d_TypeOfHighlight_Dynamic;
+      }
+      else if (anArg.StartsWith ("-sel"))
+      {
+        aType = Prs3d_TypeOfHighlight_Selected;
+      }
+      else if (aType == Prs3d_TypeOfHighlight_None)
+      {
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
+      }
+
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           aColor);
+      if (aNbParsed == 0)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+      anArgIter += aNbParsed;
+
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetColor (aColor);
+      toRedraw = Standard_True;
+    }
+    else if ((anArg == "-transp"
+           || anArg == "-transparency"
+           || anArg == "-hitransp"
+           || anArg == "-seltransp"
+           || anArg == "-hitransplocal"
+           || anArg == "-seltransplocal")
+          && anArgIter + 1 < theArgsNb)
+    {
+      if (anArg.StartsWith ("-hi"))
+      {
+        aType = Prs3d_TypeOfHighlight_Dynamic;
+      }
+      else if (anArg.StartsWith ("-sel"))
+      {
+        aType = Prs3d_TypeOfHighlight_Selected;
+      }
+      else if (aType == Prs3d_TypeOfHighlight_None)
+      {
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
+      }
+
+      const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetTransparency ((Standard_ShortReal )aTransp);
+      toRedraw = Standard_True;
+    }
+    else if ((anArg == "-mat"
+           || anArg == "-material")
+          && anArgIter + 1 < theArgsNb)
+    {
+      if (aType == Prs3d_TypeOfHighlight_None)
+      {
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
+      }
+
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
+      if (aMatName != Graphic3d_NOM_DEFAULT)
+      {
+        ++anArgIter;
+        Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
+        *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
+        Graphic3d_MaterialAspect aMat (aMatName);
+        aMat.SetColor (aStyle->Color());
+        aMat.SetTransparency (aStyle->Transparency());
+        anAspect->SetFrontMaterial (aMat);
+        anAspect->SetInteriorColor (aStyle->Color());
+        aStyle->SetBasicFillAreaAspect (anAspect);
+      }
+      else
+      {
+        aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
+      }
+      toRedraw = Standard_True;
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
+    }
+  }
+
+  if (toPrint)
   {
-    theDi.PrintHelp (theArgVec[0]);
-    return 0;
+    const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
+    const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
+    theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
+    theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
+    theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
+    theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
+    theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
+    theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
+    theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
+    theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
+    theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
+    theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
   }
 
-  if (aCmd.HasOption ("autoActivate", 1, Standard_False))
+  if (aCtx->NbSelected() != 0 && toRedraw)
   {
-    aCtx->SetAutoActivateSelection (aCmd.ArgBool ("autoActivate"));
+    aCtx->HilightSelected (Standard_True);
   }
-  if (aCmd.HasOption ("pixTol", 1, Standard_False))
+
+  return 0;
+}
+
+//===============================================================================================
+//function : VDumpSelectionImage
+//purpose  :
+//===============================================================================================
+static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
+                                Standard_Integer  theArgsNb,
+                                const char**      theArgVec)
+{
+  if (theArgsNb < 2)
   {
-    aCtx->SetPixelTolerance (aCmd.ArgInt ("pixTol"));
+    std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
+    return 1;
   }
 
-  Handle(Graphic3d_HighlightStyle)& aHiStyle = aCtx->ChangeHighlightStyle();
-  Handle(Graphic3d_HighlightStyle)& aSelStyle = aCtx->ChangeSelectionStyle();
-  Standard_Boolean toRedraw = Standard_False;
-  if (aCmd.HasOption ("selColor"))
+  const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
   {
-    Quantity_Color aNewColor;
-    if (!parseColor (aCmd, "selColor", aNewColor))
-      return 1;
-    aSelStyle->SetColor (aNewColor);
-    toRedraw = Standard_True;
+    std::cout << "Error: no active view.\n";
+    return 1;
   }
-  if (aCmd.HasOption ("hiColor"))
+
+  TCollection_AsciiString aFile;
+  StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
+  Image_Format anImgFormat = Image_Format_BGR;
+  Standard_Integer aPickedIndex = 1;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
   {
-    Quantity_Color aNewColor;
-    if (!parseColor (aCmd, "hiColor", aNewColor))
+    TCollection_AsciiString aParam (theArgVec[anArgIter]);
+    aParam.LowerCase();
+    if (aParam == "-type")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aValue (theArgVec[anArgIter]);
+      aValue.LowerCase();
+      if (aValue == "depth"
+       || aValue == "normdepth"
+       || aValue == "normalizeddepth")
+      {
+        aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
+        anImgFormat = Image_Format_GrayF;
+      }
+      if (aValue == "depthinverted"
+       || aValue == "normdepthinverted"
+       || aValue == "normalizeddepthinverted"
+       || aValue == "inverted")
+      {
+        aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
+        anImgFormat = Image_Format_GrayF;
+      }
+      else if (aValue == "unnormdepth"
+            || aValue == "unnormalizeddepth")
+      {
+        aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
+        anImgFormat = Image_Format_GrayF;
+      }
+      else if (aValue == "objectcolor"
+            || aValue == "object"
+            || aValue == "color")
+      {
+        aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
+      }
+      else if (aValue == "entitycolor"
+            || aValue == "entity")
+      {
+        aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
+      }
+      else if (aValue == "ownercolor"
+            || aValue == "owner")
+      {
+        aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
+      }
+      else if (aValue == "selectionmodecolor"
+            || aValue == "selectionmode"
+            || aValue == "selmodecolor"
+            || aValue == "selmode")
+      {
+        aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
+      }
+    }
+    else if (aParam == "-picked"
+          || aParam == "-pickeddepth"
+          || aParam == "-pickedindex")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
+        return 1;
+      }
+
+      aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
+    }
+    else if (aFile.IsEmpty())
+    {
+      aFile = theArgVec[anArgIter];
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
       return 1;
-    aHiStyle->SetColor (aNewColor);
+    }
   }
-  if (aCmd.HasOption ("selTransp"))
+  if (aFile.IsEmpty())
   {
-    aSelStyle->SetTransparency (aCmd.ArgFloat ("selTransp"));
-    toRedraw = Standard_True;
+    std::cout << "Syntax error: image file name is missing.\n";
+    return 1;
   }
-  if (aCmd.HasOption ("hiTransp"))
+
+  const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+  Standard_Integer aWidth = 0, aHeight = 0;
+  aView->Window()->Size (aWidth, aHeight);
+
+  Image_AlienPixMap aPixMap;
+  if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
   {
-    aHiStyle->SetTransparency (aCmd.ArgFloat ("hiTransp"));
+    std::cout << "Error: can't allocate image.\n";
+    return 1;
   }
-
-  if (aCmd.HasOption ("print") || theArgsNb == 1)
+  if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
   {
-    theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
-    theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
-    theDi << "Selection color                : " << Quantity_Color::StringName (aCtx->SelectionStyle()->Color().Name()) << "\n";
-    theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aCtx->HighlightStyle()->Color().Name()) << "\n";
-    theDi << "Selection transparency         : " << aCtx->SelectionStyle()->Transparency() << "\n";
-    theDi << "Dynamic highlight transparency : " << aCtx->HighlightStyle()->Transparency() << "\n";
+    std::cout << "Error: can't generate selection image.\n";
+    return 1;
   }
-
-  if (aCtx->NbSelected() != 0 && toRedraw)
+  if (!aPixMap.Save (aFile))
   {
-    aCtx->HilightSelected (Standard_True);
+    std::cout << "Error: can't save selection image.\n";
+    return 0;
   }
-
   return 0;
 }
 
@@ -9244,8 +10841,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add("vpick" ,
     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
     VPick,group);
-  theCommands.Add("vfit"    ,
-    "vfit or <F> [-selected]"
+  theCommands.Add("vfit",
+    "vfit or <F> [-selected] [-noupdate]"
     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
     __FILE__,VFit,group);
   theCommands.Add ("vfitarea",
@@ -9259,7 +10856,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "   \"scale\" - specifies factor to scale computed z range.\n",
     __FILE__, VZFit, group);
   theCommands.Add("vrepaint",
-    "vrepaint        : vrepaint, force redraw",
+            "vrepaint [-immediate]"
+    "\n\t\t: force redraw",
     __FILE__,VRepaint,group);
   theCommands.Add("vclear",
     "vclear          : vclear"
@@ -9315,22 +10913,35 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " : notice that EMF format requires patched gl2ps",
     __FILE__,VExport,group);
   theCommands.Add("vcolorscale",
-    "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
-    "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
-    "-demo/-demoversion draw a demoversion of color scale.\n"
-    "-show/display display color scale.\n"
-    "-hide/erase erase color scale.\n"
-    "Please note that -show/-hide option must be the first argument!\n"
-    "-color Index R G B: set color for indexed interval\n"
-    "-color Index ColorName: set color for indexed interval\n"
-    "-colors R G B R G B ...: set colors for all intervals\n"
-    "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
-    "-colors supports both color names and rgb values in one call\n"
-    "-label Index Text: set label for indexed interval\n"
-    "-labels Text Text Text ...: set labels for all intervals\n"
-    "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
-    "Available text positions: left, right, center, none;\n",
-    __FILE__,VColorScale,group);
+    "vcolorscale name [-noupdate|-update] [-demo]"
+    "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
+    "\n\t\t:       [-font HeightFont=20]"
+    "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
+    "\n\t\t:       [-smoothTransition {on|off}=off]"
+    "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
+    "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
+    "\n\t\t:       [-textpos {left|right|center|none}=right]"
+    "\n\t\t:       [-labelAtBorder {on|off}=on]"
+    "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
+    "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
+    "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
+    "\n\t\t:       [-xy Left=0 Bottom=0]"
+    "\n\t\t:  -demo     - displays a color scale with demonstratio values"
+    "\n\t\t:  -colors   - set colors for all intervals"
+    "\n\t\t:  -color    - set color for specific interval"
+    "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
+    "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
+    "\n\t\t:              at border means the value inbetween neighbor intervals,"
+    "\n\t\t:              at center means the center value within current interval"
+    "\n\t\t:  -labels   - set labels for all intervals"
+    "\n\t\t:  -freeLabels - same as -labels but does not require"
+    "\n\t\t:              matching the number of intervals"
+    "\n\t\t:  -label    - set label for specific interval"
+    "\n\t\t:  -title    - set title"
+    "\n\t\t:  -reversed - setup smooth color transition between intervals"
+    "\n\t\t:  -smoothTransition - swap colorscale direction"
+    "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
+    __FILE__, VColorScale, group);
   theCommands.Add("vgraduatedtrihedron",
     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
     "\t[-namefont Name] [-valuesfont Name]\n"
@@ -9364,22 +10975,17 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n\t\t:  -upperLeft tile offset as upper left corner",
     __FILE__, VTile, group);
   theCommands.Add("vzlayer",
-    "vzlayer add/del/get/settings/enable/disable [id]\n"
-    " add - add new z layer to viewer and print its id\n"
-    " del - del z layer by its id\n"
-    " get - print sequence of z layers in increasing order of their overlay level\n"
-    " settings - print status of z layer settings\n"
-    " enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    enables given setting for the z layer\n"
-    " enable (p[ositive]offset/n[egative]offset) \n    enables given setting for the z layer\n"
-    " enable textureenv \n    enables environment texture mapping\n"
-    " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    disables given setting for the z layer\n"
-    " disable textureenv \n    disables environment texture mapping\n"
-    "\nWhere id is the layer identificator\n"
-    "\nExamples:\n"
-    "   vzlayer add\n"
-    "   vzlayer enable poffset 1\n"
-    "   vzlayer disable depthtest 1\n"
-    "   vzlayer del 1\n",
+              "vzlayer [layerId]"
+      "\n\t\t:         [-add|-delete|-get|-settings]"
+      "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
+      "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
+      "\n\t\t: ZLayer list management:"
+      "\n\t\t:   -add      add new z layer to viewer and print its id"
+      "\n\t\t:   -delete   delete z layer"
+      "\n\t\t:   -get      print sequence of z layers"
+      "\n\t\t:   -settings print status of z layer settings"
+      "\n\t\t:   -disable  disables given setting"
+      "\n\t\t:   -enable   enables  given setting",
     __FILE__,VZLayer,group);
   theCommands.Add("vlayerline",
     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
@@ -9453,7 +11059,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add ("vcaps",
             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
     "\n\t\t:       [-compatibleProfile {0|1}]"
-    "\n\t\t:       [-vsync {0|1}]"
+    "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
     "\n\t\t: Modify particular graphic driver options:"
@@ -9464,6 +11070,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n\t\t:             arrays to GPU memory)"
     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
     "\n\t\t:  vsync    - switch VSync on or off"
+    "\n\t\t:  winBuffer - allow using window buffer for rendering"
     "\n\t\t: Context creation options:"
     "\n\t\t:  softMode          - software OpenGL implementation"
     "\n\t\t:  compatibleProfile - backward-compatible profile"
@@ -9500,22 +11107,73 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "vmoveto x y"
     "- emulates cursor movement to pixel postion (x,y)",
     __FILE__, VMoveTo, group);
-  theCommands.Add ("vviewparams", "vviewparams usage:\n"
-    "- vviewparams\n"
-    "- vviewparams [-scale [s]] [-eye [x y z]] [-at [x y z]] [-up [x y z]]\n"
-    "              [-proj [x y z]] [-center x y] [-size sx]\n"
-    "-   Gets or sets current view parameters.\n"
-    "-   If called without arguments, all view parameters are printed.\n"
-    "-   The options are:\n"
-    "      -scale [s]    : prints or sets viewport relative scale.\n"
-    "      -eye [x y z]  : prints or sets eye location.\n"
-    "      -at [x y z]   : prints or sets center of look.\n"
-    "      -up [x y z]   : prints or sets direction of up vector.\n"
-    "      -proj [x y z] : prints or sets direction of look.\n"
-    "      -center x y   : sets location of center of the screen in pixels.\n"
-    "      -size [sx]    : prints viewport projection width and height sizes\n"
-    "                    : or changes the size of its maximum dimension.\n",
+  theCommands.Add ("vviewparams",
+              "vviewparams [-args] [-scale [s]]"
+      "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
+      "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
+      "\n\t\t: Manage current view parameters or prints all"
+      "\n\t\t: current values when called without argument."
+      "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
+      "\n\t\t:   -eye  [x y z] prints or sets eye location"
+      "\n\t\t:   -at   [x y z] prints or sets center of look"
+      "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
+      "\n\t\t:   -proj [x y z] prints or sets direction of look"
+      "\n\t\t:   -center x y   sets location of center of the screen in pixels"
+      "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
+      "\n\t\t:                 or changes the size of its maximum dimension"
+      "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
     __FILE__, VViewParams, group);
+
+  theCommands.Add("vanimation", "Alias for vanim",
+    __FILE__, VAnimation, group);
+
+  theCommands.Add("vanim",
+            "List existing animations:"
+    "\n\t\t:  vanim"
+    "\n\t\t: Animation playback:"
+    "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
+    "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
+    "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
+    "\n\t\t:   -freeLook skip camera animations"
+    "\n\t\t:   -lockLoop disable any interactions"
+    "\n\t\t:"
+    "\n\t\t: Animation definition:"
+    "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
+    "\n\t\t:        [start TimeSec] [duration TimeSec]"
+    "\n\t\t:"
+    "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
+    "\n\t\t: specifies nested animations."
+    "\n\t\t: There is no syntax to explicitly add new animation,"
+    "\n\t\t: and all non-existing animations within the name will be"
+    "\n\t\t: implicitly created on first use (including parents)."
+    "\n\t\t:"
+    "\n\t\t: Each animation might define the SINGLE action (see below),"
+    "\n\t\t: like camera transition, object transformation or custom callback."
+    "\n\t\t: Child animations can be used for defining concurrent actions."
+    "\n\t\t:"
+    "\n\t\t: Camera animation:"
+    "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
+    "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
+    "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
+    "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
+    "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
+    "\n\t\t:   -atX    camera Center positions pair"
+    "\n\t\t:   -upX    camera Up directions pair"
+    "\n\t\t:   -scaleX camera Scale factors pair"
+    "\n\t\t: Object animation:"
+    "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
+    "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
+    "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
+    "\n\t\t:   -locX   object Location points pair (translation)"
+    "\n\t\t:   -rotX   object Orientations pair (quaternions)"
+    "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
+    "\n\t\t: Custom callback:"
+    "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
+    "\n\t\t:   %Pts        overall animation presentation timestamp"
+    "\n\t\t:   %LocalPts   local animation timestamp"
+    "\n\t\t:   %Normalized local animation normalized value in range 0..1"
+    __FILE__, VAnimation, group);
+
   theCommands.Add("vchangeselected",
     "vchangeselected shape"
     "- adds to shape to selection or remove one from it",
@@ -9587,19 +11245,18 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "                              ts, tt      - translation for s and t texture coordinates\n"
     "                              rot         - texture rotation angle in degrees",
     __FILE__, VTextureEnv, group);
-  theCommands.Add("vhlr" ,
-    "is_enabled={on|off} [show_hidden={1|0}]"
-    " - Hidden line removal algorithm:"
-    " - is_enabled: if is on HLR algorithm is applied\n"
-    " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
+  theCommands.Add("vhlr",
+            "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
+      "\n\t\t: Hidden Line Removal algorithm."
+      "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
+      "\n\t\t:   -algoType   type of HLR algorithm.\n",
     __FILE__,VHLR,group);
-  theCommands.Add("vhlrtype" ,
-    "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
-    " - Changes the type of HLR algorithm using for shapes."
-    " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
-    "   if equals to polyalgo, polygonal HLR algorithm is applied."
-    "If shapes are not given HLR algoithm of given type is applied"
-    " to all shapes in the view\n",
+  theCommands.Add("vhlrtype",
+              "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
+      "\n\t\t: Changes the type of HLR algorithm using for shapes:"
+      "\n\t\t:   'algo' - exact HLR algorithm is applied"
+      "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
+      "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
     __FILE__,VHLRType,group);
   theCommands.Add("vclipplane",
               "vclipplane planeName [{0|1}]"
@@ -9669,23 +11326,33 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     __FILE__, VRenderParams, group);
   theCommands.Add("vrenderparams",
     "\n    Manages rendering parameters: "
-    "\n      '-raster'               Disables GPU ray-tracing"
-    "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
-    "\n      '-rayTrace'             Enables  GPU ray-tracing"
-    "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
-    "\n      '-shadows      on|off'  Enables/disables shadows rendering"
-    "\n      '-reflections  on|off'  Enables/disables specular reflections"
-    "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
-    "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
-    "\n      '-gi           on|off'  Enables/disables global illumination effects"
-    "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
-    "\n      '-env          on|off'  Enables/disables environment map background"
-    "\n      '-iss          on|off'  Enables/disables adaptive screen sampling (PT mode)"
-    "\n      '-issd         on|off'  Shows screen sampling distribution in ISS mode"
-    "\n      '-rebuildGlsl  on|off'  Rebuild Ray-Tracing GLSL programs (for debugging)"
-    "\n      '-shadingModel model'   Controls shading model from enumeration"
-    "\n                              color, flat, gouraud, phong"
-    "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
+    "\n      '-raster'                   Disables GPU ray-tracing"
+    "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
+    "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
+    "\n      '-rendScale    value        Rendering resolution scale factor"
+    "\n      '-rayTrace'                 Enables  GPU ray-tracing"
+    "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
+    "\n      '-shadows      on|off'      Enables/disables shadows rendering"
+    "\n      '-reflections  on|off'      Enables/disables specular reflections"
+    "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
+    "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
+    "\n      '-gi           on|off'      Enables/disables global illumination effects"
+    "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
+    "\n      '-env          on|off'      Enables/disables environment map background"
+    "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
+    "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
+    "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
+    "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
+    "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
+    "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
+    "\n      '-shadingModel model'       Controls shading model from enumeration"
+    "\n                                  color, flat, gouraud, phong"
+    "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
+    "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
+    "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
+    "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
+    "\n      '-whitepoint   value'       White point value for filmic tone mapping"
+    "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
     "\n    Unlike vcaps, these parameters dramatically change visual properties."
     "\n    Command is intended to control presentation quality depending on"
     "\n    hardware capabilities and performance.",
@@ -9731,17 +11398,32 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     __FILE__, VManipulator, group);
 
   theCommands.Add("vselprops",
-    "\n    vselprops [options]"
+    "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
+    "\n    -pickStrategy {first|topmost} : defines picking strategy"
+    "\n                            'first'   to pick first acceptable (default)"
+    "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
     "\n    -pixTol    value        : sets up pixel tolerance"
-    "\n    -selColor  {name|r g b} : sets selection color"
-    "\n    -hiColor   {name|r g b} : sets dynamic highlight color"
-    "\n    -selTransp value        : sets transparency coefficient for selection"
-    "\n    -hiTransp  value        : sets transparency coefficient for dynamic highlight"
+    "\n    -dispMode  dispMode     : sets display mode for highlighting"
+    "\n    -layer     ZLayer       : sets ZLayer for highlighting"
+    "\n    -color     {name|r g b} : sets highlight color"
+    "\n    -transp    value        : sets transparency coefficient for highlight"
+    "\n    -material  material     : sets highlight material"
     "\n    -print                  : prints current state of all mentioned parameters",
     __FILE__, VSelectionProperties, group);
 
+  theCommands.Add ("vseldump",
+                   "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
+                   "\n\t\t: Generate an image based on detection results:"
+                   "\n\t\t:   depth       normalized depth values"
+                   "\n\t\t:   unnormDepth unnormalized depth values"
+                   "\n\t\t:   object      color of detected object"
+                   "\n\t\t:   owner       color of detected owner"
+                   "\n\t\t:   selMode     color of selection mode"
+                   "\n\t\t:   entity      color of etected entity",
+                   __FILE__, VDumpSelectionImage, group);
+
 #if defined(_WIN32)
   theCommands.Add("vprogressive",
     "vprogressive",