0028110: Configuration - specify Unicode charset instead of multibyte in project...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
index a2b4ebf..b107406 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>
 #include <AIS_Shape.hxx>
-#include <AIS_Drawer.hxx>
 #include <AIS_InteractiveObject.hxx>
 #include <AIS_ListOfInteractive.hxx>
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <DBRep.hxx>
+#include <Graphic3d_ArrayOfPolylines.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
 #include <Graphic3d_ExportFormat.hxx>
 #include <Graphic3d_NameOfTextureEnv.hxx>
+#include <Graphic3d_GraduatedTrihedron.hxx>
 #include <Graphic3d_TextureEnv.hxx>
 #include <Graphic3d_TextureParams.hxx>
 #include <Graphic3d_TypeOfTextureFilter.hxx>
 #include <ViewerTest_EventManager.hxx>
 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
-#include <Visual3d_View.hxx>
-#include <Visual3d_ViewManager.hxx>
+#include <ViewerTest_CmdParser.hxx>
 #include <V3d_AmbientLight.hxx>
 #include <V3d_DirectionalLight.hxx>
-#include <V3d_LayerMgr.hxx>
-#include <V3d_LayerMgrPointer.hxx>
 #include <V3d_PositionalLight.hxx>
 #include <V3d_SpotLight.hxx>
 #include <NCollection_DoubleMap.hxx>
 #include <NCollection_List.hxx>
 #include <NCollection_Vector.hxx>
-#include <NIS_View.hxx>
-#include <NIS_Triangulated.hxx>
-#include <NIS_InteractiveContext.hxx>
 #include <AIS_InteractiveContext.hxx>
 #include <Draw_Interpretor.hxx>
 #include <Draw.hxx>
 #include <Draw_Appli.hxx>
-#include <Aspect_PrintAlgo.hxx>
 #include <Image_AlienPixMap.hxx>
 #include <OpenGl_GraphicDriver.hxx>
 #include <OSD_Timer.hxx>
@@ -60,7 +61,6 @@
 #include <TColStd_HSequenceOfReal.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
 #include <TColStd_MapOfAsciiString.hxx>
-#include <Visual3d_LayerItem.hxx>
 #include <Aspect_TypeOfLine.hxx>
 #include <Image_Diff.hxx>
 #include <Aspect_DisplayConnection.hxx>
 #include <NCollection_DataMap.hxx>
 #include <Graphic3d_Texture2Dmanual.hxx>
 #include <Prs3d_ShadingAspect.hxx>
+#include <Prs3d_Drawer.hxx>
+#include <Prs3d_LineAspect.hxx>
+#include <Prs3d_Root.hxx>
 
-#ifdef WNT
+#ifdef _WIN32
 #undef DrawText
 #endif
 
-#include <Visual3d_Layer.hxx>
 #include <cstdlib>
 
 #if defined(_WIN32)
   #include <WNT_WClass.hxx>
   #include <WNT_Window.hxx>
-
-  #if defined(_MSC_VER)
-    #define _CRT_SECURE_NO_DEPRECATE
-    #pragma warning (disable:4996)
-  #endif
 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
   #include <Cocoa_Window.hxx>
 #else
   #include <tk.h>
 #endif
 
-inline Standard_Boolean parseOnOff (Standard_CString  theArg,
-                                    Standard_Boolean& theIsOn)
-{
-  TCollection_AsciiString aFlag (theArg);
-  aFlag.LowerCase();
-  if (aFlag == "on"
-   || aFlag == "1")
-  {
-    theIsOn = Standard_True;
-    return Standard_True;
-  }
-  else if (aFlag == "off"
-        || aFlag == "0")
-  {
-    theIsOn = Standard_False;
-    return Standard_True;
-  }
-  return Standard_False;
-}
-
 // Auxiliary definitions
 static const char THE_KEY_DELETE = 127;
 
@@ -128,7 +105,6 @@ Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
 
 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
-extern const Handle(NIS_InteractiveContext)& TheNISContext();
 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
 
 extern int VErase (Draw_Interpretor& theDI,
@@ -194,26 +170,65 @@ static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveCon
 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
 static OpenGl_Caps ViewerTest_myDefaultCaps;
 
-#define ZCLIPWIDTH 1.
-
 static void OSWindowSetup();
 
+static struct
+{
+  Quantity_Color FlatColor;
+  Quantity_Color GradientColor1;
+  Quantity_Color GradientColor2;
+  Aspect_GradientFillMethod FillMethod;
+} ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
+
 //==============================================================================
 //  EVENT GLOBAL VARIABLES
 //==============================================================================
 
 static int Start_Rot = 0;
-static int ZClipIsOn = 0;
 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()
+{
+  static Handle(AIS_RubberBand) aBand;
+  if (aBand.IsNull())
+  {
+    aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
+    aBand->SetDisplayMode (0);
+  }
+  return aBand;
+}
+
+typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
+
+Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
+{
+  static ViewerTest_MapOfAISManipulators aMap;
+  return aMap;
+}
+
+Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
+{
+  ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
+  for (; anIt.More(); anIt.Next())
+  {
+    if (anIt.Value()->HasActiveMode())
+    {
+      return anIt.Value();
+    }
+  }
+  return NULL;
+}
 
 //==============================================================================
 
-#ifdef WNT
+#ifdef _WIN32
 static LRESULT WINAPI ViewerWindowProc(
                                        HWND hwnd,
                                        UINT uMsg,
@@ -232,15 +247,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", AdvViewerWindowProc,
-      CS_VREDRAW | CS_HREDRAW, 0, 0,
-      ::LoadCursor (NULL, IDC_ARROW));
+    theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
+                                CS_VREDRAW | CS_HREDRAW, 0, 0,
+                                ::LoadCursorW (NULL, IDC_ARROW));
   }
 #endif
   return theWClass;
@@ -436,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
@@ -548,8 +563,17 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
     (void)theDisplayName; // avoid warning on unused argument
     SetDisplayConnection (new Aspect_DisplayConnection ());
   #endif
+
+    if (Draw_VirtualWindows)
+    {
+      // don't waste the time waiting for VSync when window is not displayed on the screen
+      ViewerTest_myDefaultCaps.swapInterval = 0;
+      // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
+      //ViewerTest_myDefaultCaps.buffersNoSwap = true;
+    }
     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
+
     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
     toCreateViewer = Standard_True;
   }
@@ -612,10 +636,10 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   // Change name of current active window
   if (!ViewerTest::CurrentView().IsNull())
   {
-    TCollection_AsciiString aTitle("3D View - ");
-    aTitle = aTitle
+    TCollection_AsciiString anActiveWindowTitle("3D View - ");
+    anActiveWindowTitle = anActiveWindowTitle
       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
-    SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
+    SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
   }
 
   // Create viewer
@@ -637,12 +661,11 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   else if (a3DViewer.IsNull())
   {
     toCreateViewer = Standard_True;
-    TCollection_ExtendedString NameOfWindow("Viewer3D");
-    a3DViewer = new V3d_Viewer(aGraphicDriver, NameOfWindow.ToExtString());
-
-    NameOfWindow = TCollection_ExtendedString("Collector");
-
-    a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
+    a3DViewer = new V3d_Viewer(aGraphicDriver);
+    a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
+    a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
+                                           ViewerTest_DefaultBackground.GradientColor2,
+                                           ViewerTest_DefaultBackground.FillMethod);
   }
 
   // AIS context setup
@@ -662,7 +685,7 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
 #if defined(_WIN32)
   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
                                     Handle(WNT_WClass)::DownCast (WClass()),
-                                    Draw_VirtualWindows ? WS_POPUPWINDOW : WS_OVERLAPPEDWINDOW,
+                                    Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
                                     aPxLeft, aPxTop,
                                     aPxWidth, aPxHeight,
                                     Quantity_NOC_BLACK);
@@ -679,12 +702,13 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
 #endif
   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
 
-  // NIS setup
-  Handle(NIS_View) aView = new NIS_View (a3DViewer, VT_GetWindow());
+  // View setup
+  Handle(V3d_View) aView = a3DViewer->CreateView();
+  aView->SetWindow (VT_GetWindow());
+  ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
 
   ViewerTest::CurrentView(aView);
   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
-  TheNISContext()->AttachView (aView);
 
   // Setup for X11 or NT
   OSWindowSetup();
@@ -693,8 +717,6 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
   aV3dView->SetComputedMode(Standard_False);
   MyHLRIsOn = aV3dView->ComputedMode();
-  aV3dView->SetZClippingDepth(0.5);
-  aV3dView->SetZClippingWidth(ZCLIPWIDTH/2.);
 
   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
   if (toCreateViewer)
@@ -891,7 +913,7 @@ static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
         {
           continue;
         }
-        aShape->Redisplay();
+        ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
       }
     }
   }
@@ -937,7 +959,7 @@ static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** a
       if (aShape->TypeOfHLR() != aTypeOfHLR)
         aShape->SetTypeOfHLR (aTypeOfHLR);
       if (MyHLRIsOn)
-        aShape->Redisplay();
+        ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
     }
     ViewerTest::CurrentView()->Update();
     return 0;
@@ -951,7 +973,7 @@ static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** a
 
       if (!aMap.IsBound2 (aName))
       {
-        di << argv[0] << ":" << " Wrong shape name:" << aName.ToCString() << ".\n";
+        di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
         continue;
       }
       Handle(AIS_Shape) anAISObject =
@@ -960,7 +982,7 @@ static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** a
         continue;
       anAISObject->SetTypeOfHLR (aTypeOfHLR);
       if (MyHLRIsOn)
-        anAISObject->Redisplay();
+        ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
     }
     ViewerTest::CurrentView()->Update();
   }
@@ -1094,7 +1116,6 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
 
   // Remove view resources
-  TheNISContext()->DetachView(Handle(NIS_View)::DownCast(aView));
   ViewerTest_myViews.UnBind1(theViewName);
   aView->Remove();
 
@@ -1122,6 +1143,8 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
           break;
         }
       }
+
+      aCurrentContext->RemoveAll (Standard_False);
       if(isRemoveDriver)
       {
         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
@@ -1298,7 +1321,7 @@ static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const
           if (isTreeView)
           {
             TCollection_AsciiString aContextName(aContextIter.Key1());
-            theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":" << "\n";
+            theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
           }
 
           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
@@ -1310,7 +1333,7 @@ static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const
               if (isTreeView)
               {
                 if (aViewIter.Value() == ViewerTest::CurrentView())
-                  theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)" << "\n";
+                  theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
                 else
                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
               }
@@ -1334,7 +1357,6 @@ void VT_ProcessKeyPress (const char* buf_ret)
 {
   //cout << "KeyPress" << endl;
   const Handle(V3d_View) aView = ViewerTest::CurrentView();
-  const Handle(NIS_View) aNisView = Handle(NIS_View)::DownCast (aView);
   // Letter in alphabetic order
 
   if (!strcasecmp (buf_ret, "A"))
@@ -1349,11 +1371,15 @@ void VT_ProcessKeyPress (const char* buf_ret)
   }
   else if (!strcasecmp (buf_ret, "F"))
   {
-    // FitAll
-    if (aNisView.IsNull())
-      aView->FitAll();
+    if (ViewerTest::GetAISContext()->NbSelected() > 0)
+    {
+      ViewerTest::GetAISContext()->FitSelected (aView);
+    }
     else
-      aNisView->FitAll3d();
+    {
+      // FitAll
+      aView->FitAll();
+    }
   }
   else if (!strcasecmp (buf_ret, "H"))
   {
@@ -1370,7 +1396,7 @@ void VT_ProcessKeyPress (const char* buf_ret)
       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
     else
       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
-    if (aContext->NbCurrents()==0 || aContext->NbSelected() == 0)
+    if (aContext->NbSelected()==0)
     {
       AIS_ListOfInteractive aListOfShapes;
       aContext->DisplayedObjects(aListOfShapes);
@@ -1384,21 +1410,21 @@ void VT_ProcessKeyPress (const char* buf_ret)
           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
         else
           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
-        aShape->Redisplay();
+        aContext->Redisplay (aShape, Standard_False);
       }
     }
     else
     {
-      for (aContext->InitCurrent();aContext->MoreCurrent();aContext->NextCurrent())
+      for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
       {
-        Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->Current());
+        Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
         if (aShape.IsNull())
           continue;
         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
         else
           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
-        aShape->Redisplay();
+        aContext->Redisplay (aShape, Standard_False);
       }
     }
 
@@ -1410,18 +1436,11 @@ void VT_ProcessKeyPress (const char* buf_ret)
     std::cout << "setup Shaded display mode" << std::endl;
 
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
-    if(Ctx->NbCurrents()==0 ||
-      Ctx->NbSelected()==0)
+    if(Ctx->NbSelected()==0)
       Ctx->SetDisplayMode(AIS_Shaded);
     else{
-      if(Ctx->HasOpenedContext()){
-        for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
-          Ctx->SetDisplayMode(Ctx->Interactive(),1,Standard_False);
-      }
-      else{
-        for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
-          Ctx->SetDisplayMode(Ctx->Current(),1,Standard_False);
-      }
+      for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
+        Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
       Ctx->UpdateCurrentViewer();
     }
   }
@@ -1431,18 +1450,11 @@ void VT_ProcessKeyPress (const char* buf_ret)
     std::cout << "reset display mode to defaults" << std::endl;
 
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
-    if(Ctx->NbCurrents()==0 ||
-      Ctx->NbSelected()==0)
+    if(Ctx->NbSelected()==0)
       Ctx->SetDisplayMode(AIS_WireFrame);
     else{
-      if(Ctx->HasOpenedContext()){
-        for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
-          Ctx->UnsetDisplayMode(Ctx->Interactive(),Standard_False);
-      }
-      else{
-        for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
-          Ctx->UnsetDisplayMode(Ctx->Current(),Standard_False);
-      }
+      for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
+        Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
       Ctx->UpdateCurrentViewer();
     }
 
@@ -1471,39 +1483,14 @@ void VT_ProcessKeyPress (const char* buf_ret)
   {
     std::cout << "setup WireFrame display mode" << std::endl;
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
-    if(Ctx->NbCurrents()==0 ||
-      Ctx->NbSelected()==0)
+    if(Ctx->NbSelected()==0)
       Ctx->SetDisplayMode(AIS_WireFrame);
     else{
-      if(Ctx->HasOpenedContext()){
-        for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
-          Ctx->SetDisplayMode(Ctx->Interactive(),0,Standard_False);
-      }
-      else{
-        for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
-          Ctx->SetDisplayMode(Ctx->Current(),0,Standard_False);
-      }
+      for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
+        Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
       Ctx->UpdateCurrentViewer();
     }
   }
-  else if (!strcasecmp (buf_ret, "Z"))
-  {
-    // ZCLIP
-    if ( ZClipIsOn ) {
-      cout << "ZClipping OFF" << endl;
-      ZClipIsOn = 0;
-
-      aView->SetZClippingType(V3d_OFF);
-      aView->Redraw();
-    }
-    else {
-      cout << "ZClipping ON" << endl;
-      ZClipIsOn = 1;
-
-      aView->SetZClippingType(V3d_FRONT);
-      aView->Redraw();
-    }
-  }
   else if (!strcasecmp (buf_ret, ","))
   {
     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
@@ -1512,11 +1499,28 @@ void VT_ProcessKeyPress (const char* buf_ret)
   {
     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
   }
+  else if (!strcasecmp (buf_ret, "/"))
+  {
+    Handle(Graphic3d_Camera) aCamera = aView->Camera();
+    if (aCamera->IsStereo())
+    {
+      aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
+      aView->Redraw();
+    }
+  }
+  else if (!strcasecmp (buf_ret, "*"))
+  {
+    Handle(Graphic3d_Camera) aCamera = aView->Camera();
+    if (aCamera->IsStereo())
+    {
+      aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
+      aView->Redraw();
+    }
+  }
   else if (*buf_ret == THE_KEY_DELETE)
   {
     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
     if (!aCtx.IsNull()
-     && aCtx->NbCurrents() > 0
      && aCtx->NbSelected() > 0)
     {
       Draw_Interprete ("verase");
@@ -1570,6 +1574,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;
@@ -1604,13 +1614,13 @@ void VT_ProcessButton1Release (Standard_Boolean theIsShift)
     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
     if (theIsShift)
     {
-      EM->ShiftSelect (Min (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
-                       Max (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion));
+      EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
+                       X_Motion, Y_Motion);
     }
     else
     {
-      EM->Select (Min (X_ButtonPress, X_Motion), Max (Y_ButtonPress, Y_Motion),
-                  Max (X_ButtonPress, X_Motion), Min (Y_ButtonPress, Y_Motion));
+      EM->Select (X_ButtonPress, Y_ButtonPress,
+                  X_Motion, Y_Motion);
     }
   }
 }
@@ -1645,46 +1655,6 @@ void VT_ProcessButton3Release()
   }
 }
 
-//==============================================================================
-//function : ProcessZClipMotion
-//purpose  : Zoom
-//==============================================================================
-
-void ProcessZClipMotion()
-{
-  Handle(V3d_View)  a3DView = ViewerTest::CurrentView();
-  if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
-    static Standard_Real CurZPos = 0.;
-
-    //Quantity_Length VDX, VDY;
-    //a3DView->Size(VDX,VDY);
-    //Standard_Real VDZ = a3DView->ZSize();
-    //printf("View size (%lf,%lf,%lf)\n", VDX, VDY, VDZ);
-
-    Quantity_Length dx = a3DView->Convert(X_Motion - X_ButtonPress);
-
-    // Front = Depth + width/2.
-    Standard_Real D = 0.5;
-    Standard_Real W = 0.1;
-
-    CurZPos += (dx);
-
-    D += CurZPos;
-
-    //printf("dx %lf Depth %lf Width %lf\n", dx, D, W);
-
-    a3DView->SetZClippingType(V3d_OFF);
-    a3DView->SetZClippingDepth(D);
-    a3DView->SetZClippingWidth(W);
-    a3DView->SetZClippingType(V3d_FRONT);
-
-    a3DView->Redraw();
-
-    X_ButtonPress = X_Motion;
-    Y_ButtonPress = Y_Motion;
-  }
-}
-
 //==============================================================================
 //function : ProcessControlButton1Motion
 //purpose  : Zoom
@@ -1756,7 +1726,7 @@ static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
 {
   if ( ViewerTest::CurrentView().IsNull() )
   {
-    di<<"Call vinit before this command, please"<<"\n";
+    di<<"Call vinit before this command, please\n";
     return 1;
   }
 
@@ -1805,7 +1775,7 @@ static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
 
 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
 {
-  return ViewProject(di, V3d_Ypos);
+  return ViewProject(di, V3d_Xneg);
 }
 
 //==============================================================================
@@ -1816,7 +1786,7 @@ static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
 
 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
 {
-  return ViewProject(di, V3d_Yneg);
+  return ViewProject(di, V3d_Xpos);
 }
 
 //==============================================================================
@@ -1827,7 +1797,7 @@ static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
 
 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
 {
-  return ViewProject(di, V3d_Xpos);
+  return ViewProject(di, V3d_Yneg);
 }
 
 //==============================================================================
@@ -1838,7 +1808,7 @@ static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
 
 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
 {
-  return ViewProject(di, V3d_Xneg);
+  return ViewProject(di, V3d_Ypos);
 }
 
 //==============================================================================
@@ -1850,44 +1820,44 @@ static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
 {
 
-  di << "Q : Quit the application" << "\n";
-
-  di << "========================="<<"\n";
-  di << "F : FitAll" << "\n";
-  di << "T : TopView" << "\n";
-  di << "B : BottomView" << "\n";
-  di << "R : RightView" << "\n";
-  di << "L : LeftView" << "\n";
-  di << "A : AxonometricView" << "\n";
-  di << "D : ResetView" << "\n";
-
-  di << "========================="<<"\n";
-  di << "S : Shading" << "\n";
-  di << "W : Wireframe" << "\n";
-  di << "H : HidelLineRemoval" << "\n";
-  di << "U : Unset display mode" << "\n";
-  di << "Delete : Remove selection from viewer" << "\n";
-
-  di << "========================="<<"\n";
-  di << "Selection mode "<<"\n";
-  di << "0 : Shape" <<"\n";
-  di << "1 : Vertex" <<"\n";
-  di << "2 : Edge" <<"\n";
-  di << "3 : Wire" <<"\n";
-  di << "4 : Face" <<"\n";
-  di << "5 : Shell" <<"\n";
-  di << "6 : Solid" <<"\n";
-  di << "7 : Compound" <<"\n";
-
-  di << "========================="<<"\n";
-  di << "Z : Switch Z clipping On/Off" << "\n";
-  di << ", : Hilight next detected" << "\n";
-  di << ". : Hilight previous detected" << "\n";
+  di << "Q : Quit the application\n";
+
+  di << "=========================\n";
+  di << "F : FitAll\n";
+  di << "T : TopView\n";
+  di << "B : BottomView\n";
+  di << "R : RightView\n";
+  di << "L : LeftView\n";
+  di << "A : AxonometricView\n";
+  di << "D : ResetView\n";
+
+  di << "=========================\n";
+  di << "S : Shading\n";
+  di << "W : Wireframe\n";
+  di << "H : HidelLineRemoval\n";
+  di << "U : Unset display mode\n";
+  di << "Delete : Remove selection from viewer\n";
+
+  di << "=========================\n";
+  di << "Selection mode \n";
+  di << "0 : Shape\n";
+  di << "1 : Vertex\n";
+  di << "2 : Edge\n";
+  di << "3 : Wire\n";
+  di << "4 : Face\n";
+  di << "5 : Shell\n";
+  di << "6 : Solid\n";
+  di << "7 : Compound\n";
+
+  di << "=========================\n";
+  di << "Z : Switch Z clipping On/Off\n";
+  di << ", : Hilight next detected\n";
+  di << ". : Hilight previous detected\n";
 
   return 0;
 }
 
-#ifdef WNT
+#ifdef _WIN32
 
 static Standard_Boolean Ppick = 0;
 static Standard_Integer Pargc = 0;
@@ -1922,52 +1892,98 @@ static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
         }
       }
       break;
+
     case WM_LBUTTONUP:
-      if (!DragFirst)
+      if (IsDragged && !DragFirst)
       {
-        HDC hdc = GetDC( hwnd );
-        SelectObject( hdc, GetStockObject( HOLLOW_BRUSH ) );
-        SetROP2( hdc, R2_NOT );
-        Rectangle( hdc, X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion );
-        ReleaseDC( hwnd, hdc );
-        VT_ProcessButton1Release (fwKeys & MK_SHIFT);
+        if (!GetActiveAISManipulator().IsNull())
+        {
+          GetActiveAISManipulator()->StopTransform();
+          ViewerTest::GetAISContext()->ClearSelected();
+        }
+
+        if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
+        {
+          ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
+          ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
+        }
+
+        VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
       }
       IsDragged = Standard_False;
       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
 
+    case WM_RBUTTONUP:
+      if (IsDragged && !DragFirst)
+      {
+        if (!GetActiveAISManipulator().IsNull())
+        {
+          GetActiveAISManipulator()->StopTransform (Standard_False);
+          ViewerTest::GetAISContext()->ClearSelected();
+        }
+        IsDragged = Standard_False;
+      }
+      return ViewerWindowProc (hwnd, Msg, wParam, lParam);
+
     case WM_LBUTTONDOWN:
-      if( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) )
+      if (!GetActiveAISManipulator().IsNull())
+      {
+        IsDragged = ( fwKeys == MK_LBUTTON );
+      }
+      else
+      {
+        IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
+      }
+
+      if (IsDragged)
       {
-        IsDragged = Standard_True;
         DragFirst = Standard_True;
         X_ButtonPress = LOWORD(lParam);
         Y_ButtonPress = HIWORD(lParam);
       }
       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
 
-      break;
-
     case WM_MOUSEMOVE:
-      if( IsDragged )
+      if (IsDragged)
       {
-        HDC hdc = GetDC( hwnd );
-
-        HGDIOBJ anObj = SelectObject( hdc, GetStockObject( WHITE_PEN ) );
-        SelectObject( hdc, GetStockObject( HOLLOW_BRUSH ) );
-        SetROP2( hdc, R2_NOT );
+        X_Motion = LOWORD (lParam);
+        Y_Motion = HIWORD (lParam);
+        if (!GetActiveAISManipulator().IsNull())
+        {
+          if (DragFirst)
+          {
+            GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
+          }
+          else
+          {
+            GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
+            ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
+          }
+        }
+        else
+        {
+          bool toRedraw = false;
+          if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
+          {
+            ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
+            toRedraw = true;
+          }
 
-        if( !DragFirst )
-          Rectangle( hdc, X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion );
+          RECT aRect;
+          if (GetClientRect (hwnd, &aRect))
+          {
+            int aHeight = aRect.bottom - aRect.top;
+            GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
+            ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
+            toRedraw = true;
+          }
+          if (toRedraw)
+          {
+            ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
+          }
+        }
 
         DragFirst = Standard_False;
-        X_Motion = LOWORD(lParam);
-        Y_Motion = HIWORD(lParam);
-
-        Rectangle( hdc, X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion );
-
-        SelectObject( hdc, anObj );
-
-        ReleaseDC( hwnd, hdc );
       }
       else
         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
@@ -1988,8 +2004,12 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
                                        LPARAM lParam )
 {
   static int Up = 1;
+  const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    return DefWindowProcW (hwnd, Msg, wParam, lParam);
+  }
 
-  if ( !ViewerTest::CurrentView().IsNull() ) {
     PAINTSTRUCT    ps;
 
     switch( Msg ) {
@@ -2002,6 +2022,20 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
     case WM_SIZE:
       VT_ProcessConfigure();
       break;
+    case WM_MOVE:
+    case WM_MOVING:
+    case WM_SIZING:
+      switch (aView->RenderingParams().StereoMode)
+      {
+        case Graphic3d_StereoMode_RowInterlaced:
+        case Graphic3d_StereoMode_ColumnInterlaced:
+        case Graphic3d_StereoMode_ChessBoard:
+          VT_ProcessConfigure(); // track window moves to reverse stereo pair
+          break;
+        default:
+          break;
+      }
+      break;
 
     case WM_KEYDOWN:
       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
@@ -2023,6 +2057,15 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
         {
           c[0] = '.';
         }
+        else if (wParam == VK_DIVIDE)
+        {
+          c[0] = '/';
+        }
+        // dot
+        else if (wParam == VK_MULTIPLY)
+        {
+          c[0] = '*';
+        }
         VT_ProcessKeyPress (c);
       }
       break;
@@ -2047,13 +2090,13 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
 
         if (Msg == WM_LBUTTONDOWN)
         {
-          if (fwKeys & MK_CONTROL)
+          if ((fwKeys & MK_CONTROL) != 0)
           {
-            Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT));
+            Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
           }
           else
           {
-            VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT));
+            VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
           }
         }
         else if (Msg == WM_RBUTTONDOWN)
@@ -2064,6 +2107,29 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
       }
       break;
 
+    case WM_MOUSEWHEEL:
+    {
+      int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
+      if (wParam & MK_CONTROL)
+      {
+        if (aView->Camera()->IsStereo())
+        {
+          Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
+          if (aFocus > 0.2
+           && aFocus < 2.0)
+          {
+            aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
+            aView->Redraw();
+          }
+        }
+      }
+      else
+      {
+        aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
+      }
+      break;
+    }
+
     case WM_MOUSEMOVE:
       {
         //cout << "\t WM_MOUSEMOVE" << endl;
@@ -2072,67 +2138,48 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
         Y_Motion = HIWORD(lParam);
 
         if ( Up &&
-          fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON ) ) {
+          (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
+          {
             Up = 0;
             X_ButtonPress = LOWORD(lParam);
             Y_ButtonPress = HIWORD(lParam);
 
-            if ( fwKeys & MK_RBUTTON ) {
+            if ((fwKeys & MK_RBUTTON) != 0) {
               // Start rotation
               VT_ProcessButton3Press();
             }
           }
 
-          if ( fwKeys & MK_CONTROL ) {
-            if ( fwKeys & MK_LBUTTON ) {
+          if ((fwKeys & MK_CONTROL) != 0)
+          {
+            if ((fwKeys & MK_LBUTTON) != 0)
+            {
               ProcessControlButton1Motion();
             }
-            else if ( fwKeys & MK_MBUTTON ||
-              ((fwKeys&MK_LBUTTON) &&
-              (fwKeys&MK_RBUTTON) ) ){
-                VT_ProcessControlButton2Motion();
-              }
-            else if ( fwKeys & MK_RBUTTON ) {
+            else if ((fwKeys & MK_MBUTTON) != 0
+                 || ((fwKeys & MK_LBUTTON) != 0
+                  && (fwKeys & MK_RBUTTON) != 0))
+            {
+              VT_ProcessControlButton2Motion();
+            }
+            else if ((fwKeys & MK_RBUTTON) != 0)
+            {
               VT_ProcessControlButton3Motion();
             }
           }
-#ifdef BUG
-          else if ( fwKeys & MK_SHIFT ) {
-            if ( fwKeys & MK_MBUTTON ||
-              ((fwKeys&MK_LBUTTON) &&
-              (fwKeys&MK_RBUTTON) ) ) {
-                cout << "ProcessZClipMotion()" << endl;
-                ProcessZClipMotion();
-              }
-          }
-#endif
           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
           {
-            if ((fwKeys & MK_MBUTTON
-            || ((fwKeys & MK_LBUTTON) && (fwKeys & MK_RBUTTON))))
-            {
-              ProcessZClipMotion();
-            }
-            else
-            {
-              VT_ProcessMotion();
-            }
+            VT_ProcessMotion();
           }
       }
       break;
 
     default:
-      return( DefWindowProc( hwnd, Msg, wParam, lParam ));
+      return DefWindowProcW (hwnd, Msg, wParam, lParam);
     }
     return 0L;
-  }
-
-  return DefWindowProc( hwnd, Msg, wParam, lParam );
 }
 
-
-
-
 //==============================================================================
 //function : ViewerMainLoop
 //purpose  : Get a Event on the view and dispatch it
@@ -2153,9 +2200,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);
       }
     }
 
@@ -2273,9 +2321,11 @@ int ViewerMainLoop(Standard_Integer argc, const char** argv)
           {
             if( !DragFirst )
             {
-              Aspect_Handle aWindow = VT_GetWindow()->XWindow();
-              GC gc = XCreateGC( aDisplay, aWindow, 0, 0 );
-              XDrawRectangle( aDisplay, aWindow, gc, min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ), abs( X_Motion-X_ButtonPress ), abs( Y_Motion-Y_ButtonPress ) );
+              if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
+              {
+                ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
+                ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
+              }
             }
 
             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
@@ -2326,18 +2376,26 @@ int ViewerMainLoop(Standard_Integer argc, const char** argv)
           }
           if( IsDragged )
           {
-            Aspect_Handle aWindow = VT_GetWindow()->XWindow();
-            GC gc = XCreateGC( aDisplay, aWindow, 0, 0 );
-            XSetFunction( aDisplay, gc, GXinvert );
-
             if( !DragFirst )
-              XDrawRectangle(aDisplay, aWindow, gc, min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ), abs( X_Motion-X_ButtonPress ), abs( Y_Motion-Y_ButtonPress ) );
+            {
+              if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
+              {
+                ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
+              }
+            }
 
             X_Motion = aReport.xmotion.x;
             Y_Motion = aReport.xmotion.y;
             DragFirst = Standard_False;
 
-            XDrawRectangle( aDisplay, aWindow, gc, min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ), abs( X_Motion-X_ButtonPress ), abs( Y_Motion-Y_ButtonPress ) );
+            Window aWindow = GetWindowHandle(VT_GetWindow());
+            Window aRoot;
+            int anX, anY;
+            unsigned int aWidth, aHeight, aBorderWidth, aDepth;
+            XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
+            GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
+            ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
+            ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
           }
           else
           {
@@ -2347,30 +2405,6 @@ int ViewerMainLoop(Standard_Integer argc, const char** argv)
             // remove all the ButtonMotionMaskr
             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
 
-            if ( ZClipIsOn && aReport.xmotion.state & ShiftMask ) {
-              if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
-
-                Quantity_Length VDX, VDY;
-
-                ViewerTest::CurrentView()->Size(VDX,VDY);
-                Standard_Real VDZ =0 ;
-                VDZ = ViewerTest::CurrentView()->ZSize();
-
-                printf("%f,%f,%f\n", VDX, VDY, VDZ);
-
-                Quantity_Length dx = 0 ;
-                dx = ViewerTest::CurrentView()->Convert(X_Motion - X_ButtonPress);
-
-                cout << dx << endl;
-
-                dx = dx / VDX * VDZ;
-
-                cout << dx << endl;
-
-                ViewerTest::CurrentView()->Redraw();
-              }
-            }
-
             if ( aReport.xmotion.state & ControlMask ) {
               if ( aReport.xmotion.state & Button1Mask ) {
                 ProcessControlButton1Motion();
@@ -2465,27 +2499,49 @@ static void OSWindowSetup()
   XSynchronize(aDisplay, 0);
 
 #else
-  // WNT
+  // _WIN32
 #endif
 
 }
 
-
 //==============================================================================
 //function : VFit
-
-//purpose  : Fitall, no DRAW arguments
-//Draw arg : No args
+//purpose  :
 //==============================================================================
 
-static int VFit(Draw_Interpretor& , Standard_Integer , const char** )
+static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
 {
   const Handle(V3d_View) aView = ViewerTest::CurrentView();
-  Handle(NIS_View) V = Handle(NIS_View)::DownCast(aView);
-  if (V.IsNull() == Standard_False) {
-    V->FitAll3d();
-  } else if (aView.IsNull() == Standard_False) {
-    aView->FitAll();
+  if (aView.IsNull())
+  {
+    std::cout << "Error: no active viewer!\n";
+    return 1;
+  }
+
+  Standard_Boolean toFit = Standard_True;
+  ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgv[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
+    {
+      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 (toFit)
+  {
+    aView->FitAll (0.01, Standard_False);
   }
   return 0;
 }
@@ -2569,7 +2625,7 @@ static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const
 
   if (theArgsNb == 1)
   {
-    aCurrentView->View()->ZFitAll();
+    aCurrentView->ZFitAll();
     aCurrentView->Redraw();
     return 0;
   }
@@ -2581,7 +2637,7 @@ static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const
     aScale = Draw::Atoi (theArgVec[1]);
   }
 
-  aCurrentView->View()->ZFitAll (aScale);
+  aCurrentView->ZFitAll (aScale);
   aCurrentView->Redraw();
 
   return 0;
@@ -2620,7 +2676,7 @@ static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
 { if (ViewerTest::CurrentView().IsNull() ) return 1;
 
 if ( argc < 4 ) {
-  di << argv[0] << "Invalid number of arguments" << "\n";
+  di << argv[0] << "Invalid number of arguments\n";
   return 1;
 }
 
@@ -2639,8 +2695,8 @@ static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv
 {
   if (argc < 2 || argc > 3)
   {
-    di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background" << "\n";
-    di << "filltype can be one of CENTERED, TILED, STRETCH, NONE" << "\n";
+    di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
+    di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
     return 1;
   }
 
@@ -2662,7 +2718,7 @@ static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv
     else
     {
       di << "Wrong fill type : " << szType << "\n";
-      di << "Must be one of CENTERED, TILED, STRETCH, NONE" << "\n";
+      di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
       return 1;
     }
   }
@@ -2682,8 +2738,8 @@ static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char**
 {
   if (argc != 2)
   {
-    di << "Usage : " << argv[0] << " filltype : Change background image mode" << "\n";
-    di << "filltype must be one of CENTERED, TILED, STRETCH, NONE" << "\n";
+    di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
+    di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
     return 1;
   }
 
@@ -2702,7 +2758,7 @@ static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char**
   else
   {
     di << "Wrong fill type : " << szType << "\n";
-    di << "Must be one of CENTERED, TILED, STRETCH, NONE" << "\n";
+    di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
     return 1;
   }
   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
@@ -2718,10 +2774,10 @@ static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const cha
 {
   if (argc != 8 )
   {
-    di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background" << "\n";
-    di << "R1,G1,B1,R2,G2,B2 = [0..255]" << "\n";
-    di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
-    di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
+    di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
+    di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
+    di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
+    di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
     return 1;
   }
 
@@ -2747,9 +2803,9 @@ static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const cha
     int aType = Draw::Atoi(argv[7]);
     if( aType < 0 || aType > 8 )
     {
-      di << "Wrong fill type " << "\n";
-      di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
-      di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
+      di << "Wrong fill type \n";
+      di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
+      di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
       return 1;
     }
 
@@ -2770,9 +2826,9 @@ static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const
 {
   if (argc != 2 )
   {
-    di << "Usage : " << argv[0] << " Type : Change gradient background fill type" << "\n";
-    di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
-    di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
+    di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
+    di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
+    di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
     return 1;
   }
 
@@ -2787,9 +2843,9 @@ static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const
     int aType = Draw::Atoi(argv[1]);
     if( aType < 0 || aType > 8 )
     {
-      di << "Wrong fill type " << "\n";
-      di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2" << "\n";
-      di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4" << "\n";
+      di << "Wrong fill type \n";
+      di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
+      di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
       return 1;
     }
 
@@ -2810,8 +2866,8 @@ static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char**
 {
   if (argc != 4 )
   {
-    di << "Usage : " << argv[0] << " R G B : Set color background" << "\n";
-    di << "R,G,B = [0..255]" << "\n";
+    di << "Usage : " << argv[0] << " R G B : Set color background\n";
+    di << "R,G,B = [0..255]\n";
     return 1;
   }
 
@@ -2838,110 +2894,296 @@ static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char**
 }
 
 //==============================================================================
-//function : VScale
-//purpose  : View Scaling
+//function : VSetDefaultBg
+//purpose  : Set default viewer background fill color
 //==============================================================================
-
-static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
 {
-  Handle(V3d_View) V3dView = ViewerTest::CurrentView();
-  if ( V3dView.IsNull() ) return 1;
-
-  if ( argc != 4 ) {
-    di << argv[0] << "Invalid number of arguments" << "\n";
+  if (theArgNb != 4
+   && theArgNb != 8)
+  {
+    std::cout << "Error: wrong syntax! See usage:\n";
+    theDI.PrintHelp (theArgVec[0]);
     return 1;
   }
-  V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
-  return 0;
-}
-//==============================================================================
-//function : VTestZBuffTrihedron
-//purpose  : Displays a V3d_ZBUFFER'ed or V3d_WIREFRAME'd trihedron
-//==============================================================================
-
-static int VTestZBuffTrihedron(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
-{
-  Handle(V3d_View) V3dView = ViewerTest::CurrentView();
-  if ( V3dView.IsNull() ) return 1;
 
-  V3dView->ZBufferTriedronSetup();
+  ViewerTest_DefaultBackground.FillMethod =
+    theArgNb == 4 ? Aspect_GFM_NONE
+                  : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
 
-  if ( argc == 1 ) {
-    // Set up default trihedron parameters
-    V3dView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.1, V3d_ZBUFFER );
-  } else
-  if ( argc == 7 )
+  if (theArgNb == 4)
+  {
+    Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
+    Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
+    Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
+    ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
+  }
+  else
   {
-    Aspect_TypeOfTriedronPosition aPosition = Aspect_TOTP_LEFT_LOWER;
-    const char* aPosType = argv[1];
+    Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
+    Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
+    Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
+    ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
 
-    if ( strcmp(aPosType, "center") == 0 )
+    Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
+    Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
+    Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
+    ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
+  }
+
+  for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
+       anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
+  {
+    const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
+    aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
+    aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
+                                         ViewerTest_DefaultBackground.GradientColor2,
+                                         ViewerTest_DefaultBackground.FillMethod);
+  }
+
+  return 0;
+}
+
+//==============================================================================
+//function : VScale
+//purpose  : View Scaling
+//==============================================================================
+
+static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+{
+  Handle(V3d_View) V3dView = ViewerTest::CurrentView();
+  if ( V3dView.IsNull() ) return 1;
+
+  if ( argc != 4 ) {
+    di << argv[0] << "Invalid number of arguments\n";
+    return 1;
+  }
+  V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
+  return 0;
+}
+//==============================================================================
+//function : VZBuffTrihedron
+//purpose  :
+//==============================================================================
+
+static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
+                            Standard_Integer  theArgNb,
+                            const char**      theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << "Error: no active viewer!\n";
+    return 1;
+  }
+
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
+
+  Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
+  V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
+  Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
+  Quantity_Color                anArrowColorX = Quantity_NOC_RED;
+  Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
+  Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
+  Standard_Real                 aScale        = 0.1;
+  Standard_Real                 aSizeRatio    = 0.8;
+  Standard_Real                 anArrowDiam   = 0.05;
+  Standard_Integer              aNbFacets     = 12;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    Standard_CString        anArg = theArgVec[anArgIter];
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (anUpdateTool.parseRedrawMode (aFlag))
     {
-      aPosition = Aspect_TOTP_CENTER;
-    } else
-    if (strcmp(aPosType, "left_lower") == 0)
+      continue;
+    }
+    else if (aFlag == "-on")
     {
-      aPosition = Aspect_TOTP_LEFT_LOWER;
-    } else
-    if (strcmp(aPosType, "left_upper") == 0)
+      continue;
+    }
+    else if (aFlag == "-off")
     {
-      aPosition = Aspect_TOTP_LEFT_UPPER;
-    } else
-    if (strcmp(aPosType, "right_lower") == 0)
+      aView->TriedronErase();
+      return 0;
+    }
+    else if (aFlag == "-pos"
+          || aFlag == "-position"
+          || aFlag == "-corner")
     {
-      aPosition = Aspect_TOTP_RIGHT_LOWER;
-    } else
-    if (strcmp(aPosType, "right_upper") == 0)
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aPosName (theArgVec[anArgIter]);
+      aPosName.LowerCase();
+      if (aPosName == "center")
+      {
+        aPosition = Aspect_TOTP_CENTER;
+      }
+      else if (aPosName == "left_lower"
+            || aPosName == "lower_left"
+            || aPosName == "leftlower"
+            || aPosName == "lowerleft")
+      {
+        aPosition = Aspect_TOTP_LEFT_LOWER;
+      }
+      else if (aPosName == "left_upper"
+            || aPosName == "upper_left"
+            || aPosName == "leftupper"
+            || aPosName == "upperleft")
+      {
+        aPosition = Aspect_TOTP_LEFT_UPPER;
+      }
+      else if (aPosName == "right_lower"
+            || aPosName == "lower_right"
+            || aPosName == "rightlower"
+            || aPosName == "lowerright")
+      {
+        aPosition = Aspect_TOTP_RIGHT_LOWER;
+      }
+      else if (aPosName == "right_upper"
+            || aPosName == "upper_right"
+            || aPosName == "rightupper"
+            || aPosName == "upperright")
+      {
+        aPosition = Aspect_TOTP_RIGHT_UPPER;
+      }
+      else
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
+        return 1;
+      }
+    }
+    else if (aFlag == "-type")
     {
-      aPosition = Aspect_TOTP_RIGHT_UPPER;
-    } else
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
+      aTypeName.LowerCase();
+      if (aTypeName == "wireframe"
+       || aTypeName == "wire")
+      {
+        aVisType = V3d_WIREFRAME;
+      }
+      else if (aTypeName == "zbuffer"
+            || aTypeName == "shaded")
+      {
+        aVisType = V3d_ZBUFFER;
+      }
+      else
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
+      }
+    }
+    else if (aFlag == "-scale")
     {
-      di << argv[1] << " Invalid type of alignment"  << "\n";
-      di << "Must be one of [ center, left_lower,"   << "\n";
-      di << "left_upper, right_lower, right_upper ]" << "\n";
-      return 1;
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      aScale = Draw::Atof (theArgVec[anArgIter]);
     }
+    else if (aFlag == "-size"
+          || aFlag == "-sizeratio")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
 
-    Standard_Real R = Draw::Atof(argv[2])/255.;
-    Standard_Real G = Draw::Atof(argv[3])/255.;
-    Standard_Real B = Draw::Atof(argv[4])/255.;
-    Quantity_Color aColor(R, G, B, Quantity_TOC_RGB);
+      aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
+    }
+    else if (aFlag == "-arrowdiam"
+          || aFlag == "-arrowdiameter")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
 
-    Standard_Real aScale = Draw::Atof(argv[5]);
+      anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
+    }
+    else if (aFlag == "-nbfacets")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
 
-    if( aScale <= 0.0 )
+      aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
+    }
+    else if (aFlag == "-colorlabel"
+          || aFlag == "-colorlabels")
     {
-      di << argv[5] << " Invalid value. Must be > 0" << "\n";
-      return 1;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           aLabelsColor);
+      if (aNbParsed == 0)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+      anArgIter += aNbParsed;
     }
-
-    V3d_TypeOfVisualization aPresentation = V3d_ZBUFFER;
-    const char* aPresType = argv[6];
-
-    if ( strcmp(aPresType, "wireframe") == 0 )
+    else if (aFlag == "-colorarrowx")
+    {
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           anArrowColorX);
+      if (aNbParsed == 0)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+      anArgIter += aNbParsed;
+    }
+    else if (aFlag == "-colorarrowy")
     {
-      aPresentation = V3d_WIREFRAME;
-    } else
-    if (strcmp(aPresType, "zbuffer") == 0)
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           anArrowColorY);
+      if (aNbParsed == 0)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+      anArgIter += aNbParsed;
+    }
+    else if (aFlag == "-colorarrowz")
     {
-      aPresentation = V3d_ZBUFFER;
-    } else
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           anArrowColorZ);
+      if (aNbParsed == 0)
+      {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+      anArgIter += aNbParsed;
+    }
+    else
     {
-      di << argv[6] << " Invalid type of visualization" << "\n";
-      di << "Must be one of [ wireframe, zbuffer ]"     << "\n";
+      std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
       return 1;
     }
-
-    V3dView->TriedronDisplay( aPosition, aColor.Name(), aScale, aPresentation );
-
-  } else
-  {
-    di << argv[0] << " Invalid number of arguments" << "\n";
-    return 1;
   }
 
-  V3dView->View()->ZFitAll();
-
+  aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
+                               aSizeRatio, anArrowDiam, aNbFacets);
+  aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
+  aView->ZFitAll();
   return 0;
 }
 
@@ -2950,22 +3192,84 @@ static int VTestZBuffTrihedron(Draw_Interpretor& di, Standard_Integer argc, cons
 //purpose  : Camera Rotating
 //==============================================================================
 
-static int VRotate( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
-  Handle(V3d_View) V3dView = ViewerTest::CurrentView();
-  if ( V3dView.IsNull() ) {
+static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << "No active view!\n";
     return 1;
   }
 
-  if ( argc == 4 ) {
-    V3dView->Rotate( Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]) );
+  Standard_Boolean hasFlags = Standard_False;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    Standard_CString        anArg (theArgVec[anArgIter]);
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (aFlag == "-mousestart"
+     || aFlag == "-mousefrom")
+    {
+      hasFlags = Standard_True;
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
+      Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
+      aView->StartRotation (anX, anY);
+    }
+    else if (aFlag == "-mousemove")
+    {
+      hasFlags = Standard_True;
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
+
+      Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
+      Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
+      aView->Rotation (anX, anY);
+    }
+    else if (theArgNb != 4
+          && theArgNb != 7)
+    {
+      std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+      return 1;
+    }
+  }
+
+  if (hasFlags)
+  {
     return 0;
-  } else if ( argc == 7 ) {
-    V3dView->Rotate( Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]), Draw::Atof(argv[4]), Draw::Atof(argv[5]), Draw::Atof(argv[6]) );
+  }
+  else if (theArgNb == 4)
+  {
+    Standard_Real anAX = Draw::Atof (theArgVec[1]);
+    Standard_Real anAY = Draw::Atof (theArgVec[2]);
+    Standard_Real anAZ = Draw::Atof (theArgVec[3]);
+    aView->Rotate (anAX, anAY, anAZ);
     return 0;
-  } else {
-    di << argv[0] << " Invalid number of arguments" << "\n";
-    return 1;
   }
+  else if (theArgNb == 7)
+  {
+    Standard_Real anAX = Draw::Atof (theArgVec[1]);
+    Standard_Real anAY = Draw::Atof (theArgVec[2]);
+    Standard_Real anAZ = Draw::Atof (theArgVec[3]);
+
+    Standard_Real anX = Draw::Atof (theArgVec[4]);
+    Standard_Real anY = Draw::Atof (theArgVec[5]);
+    Standard_Real anZ = Draw::Atof (theArgVec[6]);
+
+    aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
+    return 0;
+  }
+
+  std::cout << "Error: Invalid number of arguments\n";
+  return 1;
 }
 
 //==============================================================================
@@ -2982,13 +3286,13 @@ static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv
   if ( argc == 2 ) {
     Standard_Real coef = Draw::Atof(argv[1]);
     if ( coef <= 0.0 ) {
-      di << argv[1] << "Invalid value" << "\n";
+      di << argv[1] << "Invalid value\n";
       return 1;
     }
     V3dView->SetZoom( Draw::Atof(argv[1]) );
     return 0;
   } else {
-    di << argv[0] << " Invalid number of arguments" << "\n";
+    di << argv[0] << " Invalid number of arguments\n";
     return 1;
   }
 }
@@ -3006,7 +3310,7 @@ static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv
     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
     return 0;
   } else {
-    di << argv[0] << " Invalid number of arguments" << "\n";
+    di << argv[0] << " Invalid number of arguments\n";
     return 1;
   }
 }
@@ -3066,11 +3370,11 @@ static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** arg
   {
     if (aFileName.Value (aLen - 2) == '.')
     {
-      aFormatStr = aFileName.SubString (aLen - 1, aLen);
+      aFormatStr = aFileName.ToCString() + aLen - 2;
     }
     else if (aFileName.Value (aLen - 3) == '.')
     {
-      aFormatStr = aFileName.SubString (aLen - 2, aLen);
+      aFormatStr = aFileName.ToCString() + aLen - 3;
     }
     else
     {
@@ -3105,8 +3409,10 @@ static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** arg
     return 1;
   }
 
-  try {
-    if (!V3dView->View()->Export (argv[1], anExpFormat))
+  Standard_DISABLE_DEPRECATION_WARNINGS
+  try
+  {
+    if (!V3dView->Export (argv[1], anExpFormat))
     {
       di << "Error: export of image to " << aFormatStr << " failed!\n";
     }
@@ -3116,4008 +3422,6916 @@ static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** arg
     di << "Error: export of image to " << aFormatStr << " failed";
     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
   }
+  Standard_ENABLE_DEPRECATION_WARNINGS
   return 0;
 }
 
-//==============================================================================
-//function : VColorScale
-//purpose  : representation color scale
-//==============================================================================
-#include <V3d_ColorScale.hxx>
-
-static int VColorScale (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
+static int VColorScale (Draw_Interpretor& theDI,
+                        Standard_Integer  theArgNb,
+                        const char**      theArgVec)
 {
-  if ( argc != 1 && argc != 4 && argc != 5 && argc != 6 && argc != 8 )
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  Handle(V3d_View)               aView    = ViewerTest::CurrentView();
+  if (aContext.IsNull())
   {
-    di << "Usage : " << argv[0] << " [RangeMin = 0 RangeMax = 100 Intervals = 10 HeightFont = 16 Position = Right X = 0 Y = 0]  " << "\n";
+    std::cout << "Error: no active view!\n";
     return 1;
   }
-
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull()) {
-    di << argv[0] << " ERROR : use 'vinit' command before " << "\n";
-    return -1;
-  }
-
-  Standard_Real minRange = 0. , maxRange = 100. ;
-
-  Standard_Integer numIntervals = 10 ;
-  Standard_Integer textHeight = 16;
-  Aspect_TypeOfColorScalePosition position = Aspect_TOCSP_RIGHT;
-  Standard_Real X = 0., Y = 0. ;
-
-  if ( argc < 9 )
-  {
-     if( argc > 3 )
-     {
-       minRange = Draw::Atof( argv[1] );
-       maxRange = Draw::Atof( argv[2] );
-       numIntervals = Draw::Atoi( argv[3] );
-     }
-     if ( argc > 4 )
-       textHeight = Draw::Atoi( argv[4] );
-     if ( argc > 5 )
-       position = (Aspect_TypeOfColorScalePosition)Draw::Atoi( argv[5] );
-     if ( argc > 7 )
-     {
-       X = Draw::Atof( argv[6] );
-       Y = Draw::Atof( argv[7] );
-     }
-  }
-  Handle(V3d_View) curView = ViewerTest::CurrentView( );
-  if ( curView.IsNull( ) )
+  if (theArgNb <= 1)
+  {
+    std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
     return 1;
-  Handle(Aspect_ColorScale) aCSV = curView->ColorScale( );
-  Handle(V3d_ColorScale) aCS = ( Handle( V3d_ColorScale )::DownCast( aCSV ) );
-  if( ! aCS.IsNull( ) )
-  {
-    aCS->SetPosition( X , Y );
-    aCS->SetHeight( 0.95) ;
-    aCS->SetTextHeight( textHeight );
-    aCS->SetRange( minRange , maxRange );
-    aCS->SetNumberOfIntervals( numIntervals );
-    aCS->SetLabelPosition( position );
-    if( !curView->ColorScaleIsDisplayed() )
-      curView->ColorScaleDisplay( );
   }
-  return 0;
-}
-
-//==============================================================================
-//function : VGraduatedTrihedron
-//purpose  : Displays a graduated trihedron
-//==============================================================================
 
-static void AddMultibyteString (TCollection_ExtendedString &name, const char *arg)
-{
-  const char *str = arg;
-  while (*str)
+  Handle(AIS_ColorScale) aColorScale;
+  if (GetMapOfAIS().IsBound2 (theArgVec[1]))
   {
-    unsigned short c1 = *str++;
-    unsigned short c2 = *str++;
-    if (!c1 || !c2) break;
-    name += (Standard_ExtCharacter)((c1 << 8) | c2);
+    // 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;
+    }
   }
-}
 
-static int VGraduatedTrihedron(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
-{
-  // Check arguments
-  if (argc != 2 && argc < 5)
+  if (theArgNb <= 2)
   {
-    di<<"Error: "<<argv[0]<<" - invalid number of arguments\n";
-    di<<"Usage: type help "<<argv[0]<<"\n";
-    return 1; //TCL_ERROR
-  }
-
-  Handle(V3d_View) aV3dView = ViewerTest::CurrentView();
+    if (aColorScale.IsNull())
+    {
+      std::cout << "Syntax error: colorscale with a given name does not exist.\n";
+      return 1;
+    }
 
-  // Create 3D view if it doesn't exist
-  if ( aV3dView.IsNull() )
-  {
-    ViewerTest::ViewerInit();
-    aV3dView = ViewerTest::CurrentView();
-    if( aV3dView.IsNull() )
+    theDI << "Color scale parameters for '"<< theArgVec[1] << "':\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 (aColorScale->GetLabelPosition())
     {
-      di << "Error: Cannot create a 3D view\n";
-      return 1; //TCL_ERROR
+      case Aspect_TOCSP_NONE:
+        theDI << "None\n";
+        break;
+      case Aspect_TOCSP_LEFT:
+        theDI << "Left\n";
+        break;
+      case Aspect_TOCSP_RIGHT:
+        theDI << "Right\n";
+        break;
+      case Aspect_TOCSP_CENTER:
+        theDI << "Center\n";
+        break;
     }
+    return 0;
   }
 
-  // Erase (==0) or display (!=0)
-  const int display = Draw::Atoi(argv[1]);
+  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));
+  }
 
-  if (display)
+  ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
+  for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
   {
-    // Text font
-    TCollection_AsciiString font;
-    if (argc < 6)
-      font.AssignCat("Courier");
-    else
-      font.AssignCat(argv[5]);
+    Standard_CString        anArg = theArgVec[anArgIter];
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (anUpdateTool.parseRedrawMode (aFlag))
+    {
+      continue;
+    }
+    else if (aFlag == "-range")
+    {
+      if (anArgIter + 3 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      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 range values should be real!\n";
+        return 1;
+      }
+      else if (!aNbIntervals.IsIntegerValue())
+      {
+        std::cout << "Error: the number of intervals should be integer!\n";
+        return 1;
+      }
 
-    // Text is multibyte
-    const Standard_Boolean isMultibyte = (argc < 7)? Standard_False : (Draw::Atoi(argv[6]) != 0);
+      aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
+      aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
+    }
+    else if (aFlag == "-font")
+    {
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+      TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
+      if (!aFontArg.IsIntegerValue())
+      {
+        std::cout << "Error: HeightFont value should be integer!\n";
+        return 1;
+      }
 
-    // Set axis names
-    TCollection_ExtendedString xname, yname, zname;
-    if (argc >= 5)
+      aColorScale->SetTextHeight (aFontArg.IntegerValue());
+      anArgIter += 1;
+    }
+    else if (aFlag == "-textpos")
     {
-      if (isMultibyte)
+      if (anArgIter + 1 >= theArgNb)
+      {
+        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;
+      }
+      else if (aTextPosArg == "left")
+      {
+        aLabPosition = Aspect_TOCSP_LEFT;
+      }
+      else if (aTextPosArg == "right")
+      {
+        aLabPosition = Aspect_TOCSP_RIGHT;
+      }
+      else if (aTextPosArg == "center")
       {
-        AddMultibyteString(xname, argv[2]);
-        AddMultibyteString(yname, argv[3]);
-        AddMultibyteString(zname, argv[4]);
+        aLabPosition = Aspect_TOCSP_CENTER;
       }
       else
       {
-        xname += argv[2];
-        yname += argv[3];
-        zname += argv[4];
+        std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
+        return 1;
       }
+      aColorScale->SetLabelPosition (aLabPosition);
     }
-    else
+    else if (aFlag == "-logarithmic"
+          || aFlag == "-log")
     {
-      xname += "X (mm)";
-      yname += "Y (mm)";
-      zname += "Z (mm)";
-    }
-
-    aV3dView->GraduatedTrihedronDisplay(xname, yname, zname,
-                                        Standard_True/*xdrawname*/, Standard_True/*ydrawname*/, Standard_True/*zdrawname*/,
-                                        Standard_True/*xdrawvalues*/, Standard_True/*ydrawvalues*/, Standard_True/*zdrawvalues*/,
-                                        Standard_True/*drawgrid*/,
-                                        Standard_True/*drawaxes*/,
-                                        5/*nbx*/, 5/*nby*/, 5/*nbz*/,
-                                        10/*xoffset*/, 10/*yoffset*/, 10/*zoffset*/,
-                                        30/*xaxisoffset*/, 30/*yaxisoffset*/, 30/*zaxisoffset*/,
-                                        Standard_True/*xdrawtickmarks*/, Standard_True/*ydrawtickmarks*/, Standard_True/*zdrawtickmarks*/,
-                                        10/*xtickmarklength*/, 10/*ytickmarklength*/, 10/*ztickmarklength*/,
-                                        Quantity_NOC_WHITE/*gridcolor*/,
-                                        Quantity_NOC_RED/*xnamecolor*/,Quantity_NOC_GREEN/*ynamecolor*/,Quantity_NOC_BLUE1/*znamecolor*/,
-                                        Quantity_NOC_RED/*xcolor*/,Quantity_NOC_GREEN/*ycolor*/,Quantity_NOC_BLUE1/*zcolor*/,font);
-  }
-  else
-    aV3dView->GraduatedTrihedronErase();
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-  ViewerTest::GetAISContext()->UpdateCurrentViewer();
-  aV3dView->Redraw();
+      Standard_Boolean IsLog;
+      if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+      aColorScale->SetLogarithmic (IsLog);
+    }
+    else if (aFlag == "-huerange"
+          || aFlag == "-hue")
+    {
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-  return 0;
-}
+      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::cerr << "Error: wrong syntax at '" << anArg << "'\n";
+        return 1;
+      }
 
-//==============================================================================
-//function : VPrintView
-//purpose  : Test printing algorithm, print the view to image file with given
-//           width and height. Printing implemented only for WNT.
-//==============================================================================
-static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
-                       const char** argv)
-{
-#ifndef WNT
-  di << "Printing implemented only for wnt!\n";
-  return 0;
-#else
+      aColorScale->SetColorRange (aColorMin, aColorMax);
+    }
+    else if (aFlag == "-reversed"
+          || aFlag == "-inverted"
+          || aFlag == "-topdown"
+          || aFlag == "-bottomup")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (anArgIter + 1 < theArgNb
+       && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
+      {
+        ++anArgIter;
+      }
+      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))
+      {
+        ++anArgIter;
+      }
+      aColorScale->SetSmoothTransition (toEnable);
+    }
+    else if (aFlag == "-xy")
+    {
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-  Handle(AIS_InteractiveContext) aContextAIS = NULL;
-  Handle(V3d_View) aView = NULL;
-  aContextAIS = ViewerTest::GetAISContext();
-  if (!aContextAIS.IsNull())
-  {
-    const Handle(V3d_Viewer)& Vwr = aContextAIS->CurrentViewer();
-    Vwr->InitActiveViews();
-    if(Vwr->MoreActiveViews())
-      aView = Vwr->ActiveView();
-  }
+      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;
+      }
 
-  // check for errors
-  if (aView.IsNull())
-  {
-    di << "Call vinit before!\n";
-    return 1;
-  }
-  else if (argc < 4)
-  {
-    di << "Use: " << argv[0];
-    di << " width height filename [print algo=0] [tile_width tile_height]\n";
-    di << "width, height of the intermediate buffer for operation\n";
-    di << "algo : {0|1}\n";
-    di << "        0 - stretch algorithm\n";
-    di << "        1 - tile algorithm\n";
-    di << "test printing algorithms into an intermediate buffer\n";
-    di << "using specific tile size if provided\n";
-    di << "with saving output to an image file\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;
+      }
 
-  // get the input params
-  Standard_Integer aWidth  = Draw::Atoi (argv[1]);
-  Standard_Integer aHeight = Draw::Atoi (argv[2]);
-  Standard_Integer aMode   = 0;
-  TCollection_AsciiString aFileName = TCollection_AsciiString (argv[3]);
-  if (argc >= 5)
-    aMode = Draw::Atoi (argv[4]);
+      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")
+    {
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-  Standard_Integer aTileWidth  = 0;
-  Standard_Integer aTileHeight = 0;
-  Standard_Boolean isTileSizeProvided = Standard_False;
-  if (argc == 7)
-  {
-    isTileSizeProvided = Standard_True;
-    aTileWidth  = Draw::Atoi (argv[5]);
-    aTileHeight = Draw::Atoi (argv[6]);
-  }
+      const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
+      if (!aHeight.IsIntegerValue())
+      {
+        std::cout << "Error: a width should be an integer value!\n";
+        return 1;
+      }
+      aColorScale->SetHeight (aHeight.IntegerValue());
+    }
+    else if (aFlag == "-color")
+    {
+      if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
+      {
+        std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
+        return 1;
+      }
+      else if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-  // check the input parameters
-  if (aWidth <= 0 || aHeight <= 0)
-  {
-    di << "Width and height must be positive values!\n";
-    return 1;
-  }
-  if (aMode != 0 && aMode != 1)
-    aMode = 0;
-
-  // define compatible bitmap
-  HDC anDC = CreateCompatibleDC(0);
-  BITMAPINFO aBitmapData;
-  memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
-  aBitmapData.bmiHeader.biSize          = sizeof (BITMAPINFOHEADER);
-  aBitmapData.bmiHeader.biWidth         = aWidth ;
-  aBitmapData.bmiHeader.biHeight        = aHeight;
-  aBitmapData.bmiHeader.biPlanes        = 1;
-  aBitmapData.bmiHeader.biBitCount      = 24;
-  aBitmapData.bmiHeader.biXPelsPerMeter = 0;
-  aBitmapData.bmiHeader.biYPelsPerMeter = 0;
-  aBitmapData.bmiHeader.biClrUsed       = 0;
-  aBitmapData.bmiHeader.biClrImportant  = 0;
-  aBitmapData.bmiHeader.biCompression   = BI_RGB;
-  aBitmapData.bmiHeader.biSizeImage     = 0;
-
-  // Create Device Independent Bitmap
-  void* aBitsOut = NULL;
-  HBITMAP aMemoryBitmap = CreateDIBSection (anDC, &aBitmapData, DIB_RGB_COLORS,
-                                            &aBitsOut, NULL, 0);
-  HGDIOBJ anOldBitmap   = SelectObject(anDC, aMemoryBitmap);
-
-  Standard_Boolean isSaved = Standard_False, isPrinted = Standard_False;
-  if (aBitsOut != NULL)
-  {
-    if (aMode == 0)
-      isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_STRETCH);
-    else
+      const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
+      if (!anInd.IsIntegerValue())
+      {
+        std::cout << "Error: Index value should be integer!\n";
+        return 1;
+      }
+      const Standard_Integer anIndex = anInd.IntegerValue();
+      if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
+      {
+        std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
+        return 1;
+      }
+
+      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;
+      }
+      aColorScale->SetIntervalColor (aColor, anIndex);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
+      anArgIter += aNbParsed;
+    }
+    else if (aFlag == "-label")
     {
-      if (isTileSizeProvided)
+      if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
+      {
+        std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
+        return 1;
+      }
+      else if (anArgIter + 2 >= theArgNb)
       {
-        Graphic3d_CView* aCView = static_cast<Graphic3d_CView*> (ViewerTest::CurrentView()->View()->CView());
-        Graphic3d_PtrFrameBuffer anOldBuffer = static_cast<Graphic3d_PtrFrameBuffer> (aCView->ptrFBO);
-        aCView->ptrFBO = aView->View()->FBOCreate (aTileWidth, aTileHeight);
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-        isPrinted = aView->Print (anDC, 1, 1, 0, Aspect_PA_TILE);
+      Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
+      if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
+      {
+        std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
+        return 1;
+      }
 
-        Graphic3d_PtrFrameBuffer aNewBuffer = static_cast<Graphic3d_PtrFrameBuffer> (aCView->ptrFBO);
-        aView->View()->FBORelease (aNewBuffer);
-        aCView->ptrFBO = anOldBuffer;
+      TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
+      aColorScale->SetLabel     (aText, anIndex);
+      aColorScale->SetLabelType (Aspect_TOCSD_USER);
+      anArgIter += 2;
+    }
+    else if (aFlag == "-labelat"
+          || aFlag == "-labat"
+          || aFlag == "-labelatborder"
+          || aFlag == "-labatborder"
+          || aFlag == "-labelatcenter"
+          || aFlag == "-labatcenter")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (aFlag == "-labelat"
+       || aFlag == "-labat")
+      {
+        Standard_Integer aLabAtBorder = -1;
+        if (++anArgIter >= theArgNb)
+        {
+          TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
+          anAtBorder.LowerCase();
+          if (anAtBorder == "border")
+          {
+            aLabAtBorder = 1;
+          }
+          else if (anAtBorder == "center")
+          {
+            aLabAtBorder = 0;
+          }
+        }
+        if (aLabAtBorder == -1)
+        {
+          std::cout << "Syntax error at argument '" << anArg << "'!\n";
+          return 1;
+        }
+        toEnable = (aLabAtBorder == 1);
       }
-      else
+      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() != aColorScale->GetNumberOfIntervals())
+      {
+        std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
+                  << aColorScale->GetNumberOfIntervals() << " intervals\n";
+        return 1;
+      }
+
+      aColorScale->SetColors    (aSeq);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
+    }
+    else if (aFlag == "-labels"
+          || aFlag == "-freelabels")
+    {
+      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")
       {
-        isPrinted = aView->Print (anDC, 1, 1, 0, Aspect_PA_TILE);
+        ++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 (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
+      {
+        aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
+      }
+      aColorScale->SetLabels (aSeq);
+      aColorScale->SetLabelType (Aspect_TOCSD_USER);
     }
+    else if (aFlag == "-title")
+    {
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      Standard_Boolean isTwoArgs = Standard_False;
+      if (anArgIter + 2 < theArgNb)
+      {
+        TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
+        aSecondArg.LowerCase();
+      Standard_DISABLE_DEPRECATION_WARNINGS
+        if (aSecondArg == "none")
+        {
+          aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
+          isTwoArgs = Standard_True;
+        }
+        else if (aSecondArg == "left")
+        {
+          aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
+          isTwoArgs = Standard_True;
+        }
+        else if (aSecondArg == "right")
+        {
+          aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
+          isTwoArgs = Standard_True;
+        }
+        else if (aSecondArg == "center")
+        {
+          aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
+          isTwoArgs = Standard_True;
+        }
+      Standard_ENABLE_DEPRECATION_WARNINGS
+      }
 
-    // succesfully printed into an intermediate buffer
-    if (isPrinted)
+      aColorScale->SetTitle (theArgVec[anArgIter + 1]);
+      if (isTwoArgs)
+      {
+        anArgIter += 1;
+      }
+      anArgIter += 1;
+    }
+    else if (aFlag == "-demoversion"
+          || aFlag == "-demo")
+    {
+      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")
     {
-      Image_PixMap aWrapper;
-      aWrapper.InitWrapper (Image_PixMap::ImgBGR, (Standard_Byte* )aBitsOut, aWidth, aHeight, aWidth * 3 + aWidth % 4);
-      aWrapper.SetTopDown (false);
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
+
+      if (!anArg1.IsRealValue())
+      {
+        std::cout << "Error: the value should be real!\n";
+        return 1;
+      }
 
-      Image_AlienPixMap anImageBitmap;
-      anImageBitmap.InitCopy (aWrapper);
-      isSaved = anImageBitmap.Save (aFileName);
+      Quantity_Color aColor;
+      aColorScale->FindColor (anArg1.RealValue(), aColor);
+      theDI << Quantity_Color::StringName (aColor.Name());
+      return 0;
     }
     else
     {
-      di << "Print operation failed due to printing errors or\n";
-      di << "insufficient memory available\n";
-      di << "Please, try to use smaller dimensions for this test\n";
-      di << "command, as it allocates intermediate buffer for storing\n";
-      di << "the result\n";
+      std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
+      return 1;
     }
   }
-  else
-  {
-    di << "Can't allocate memory for intermediate buffer\n";
-    di << "Please use smaller dimensions\n";
-  }
 
-  if (aMemoryBitmap)
+  Standard_Integer aWinWidth = 0, aWinHeight = 0;
+  aView->Window()->Size (aWinWidth, aWinHeight);
+  if (aColorScale->GetBreadth() == 0)
   {
-    SelectObject (anDC, anOldBitmap);
-    DeleteObject (aMemoryBitmap);
-    DeleteDC(anDC);
+    aColorScale->SetBreadth (aWinWidth);
   }
-
-  if (!isSaved)
+  if (aColorScale->GetHeight() == 0)
   {
-    di << "Save to file operation failed. This operation may fail\n";
-    di << "if you don't have enough available memory, then you can\n";
-    di << "use smaller dimensions for the output file\n";
-    return 1;
+    aColorScale->SetHeight (aWinHeight);
   }
-
+  aColorScale->SetToUpdate();
+  ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
   return 0;
-
-#endif
 }
 
 //==============================================================================
-//function : VZLayer
-//purpose  : Test z layer operations for v3d viewer
+//function : VGraduatedTrihedron
+//purpose  : Displays or hides a graduated trihedron
 //==============================================================================
-static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
+                                  Quantity_Color& theColor)
 {
-  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
-  if (aContextAIS.IsNull())
+  Quantity_NameOfColor aColorName;
+  TCollection_AsciiString aVal = theValue;
+  aVal.UpperCase();
+  if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
   {
-    di << "Call vinit before!\n";
-    return 1;
-  }
-  else if (argc < 2)
-  {
-    di << "Use: vzlayer ";
-    di << " add/del/get/settings/enable/disable [id]\n";
-    di << " add - add new z layer to viewer and print its id\n";
-    di << " del - del z layer by its id\n";
-    di << " get - print sequence of z layers in increasing order of their overlay level\n";
-    di << " settings - print status of z layer settings\n";
-    di << " enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    enables given setting for the z layer\n";
-    di << " enable (p[ositive]offset/n[egative]offset) \n    enables given setting for the z layer\n";
-    di << " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    disables given setting for the z layer\n";
-    di << "\nWhere id is the layer identificator\n";
-    di << "\nExamples:\n";
-    di << "   vzlayer add\n";
-    di << "   vzlayer enable poffset 1\n";
-    di << "   vzlayer disable depthtest 1\n";
-    di << "   vzlayer del 1\n";
-    return 1;
+    return Standard_False;
   }
+  theColor = Quantity_Color (aColorName);
+  return Standard_True;
+}
 
-  const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
-  if (aViewer.IsNull())
+static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
+{
+  if (theArgNum < 2)
   {
-    di << "No active viewer!\n";
-    return 1;
+    std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
+              << theArgs[0] <<"' for more information.\n";
+    return 1;  //TCL_ERROR
   }
 
-  // perform operation
-  TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
-  if (anOp == "add")
+  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
+  TCollection_AsciiString aParseKey;
+  for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
   {
-    Standard_Integer aNewId;
-    if (!aViewer->AddZLayer (aNewId))
-    {
-      di << "Impossible to add new z layer!\n";
-      return 1;
-    }
+    TCollection_AsciiString anArg (theArgs [anArgIt]);
 
-    di << "New z layer added with index: " << aNewId << "\n";
-  }
-  else if (anOp == "del")
-  {
-    if (argc < 3)
+    if (anArg.Value (1) == '-' && !anArg.IsRealValue())
     {
-      di << "Please also provide as argument id of z layer to remove\n";
-      return 1;
+      aParseKey = anArg;
+      aParseKey.Remove (1);
+      aParseKey.LowerCase();
+      aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
+      continue;
     }
 
-    Standard_Integer aDelId = Draw::Atoi (argv[2]);
-    if (!aViewer->RemoveZLayer (aDelId))
+    if (aParseKey.IsEmpty())
     {
-      di << "Impossible to remove the z layer or invalid id!\n";
-      return 1;
+      continue;
     }
 
-    di << "Z layer " << aDelId << " has been removed\n";
+    aMapOfArgs(aParseKey)->Append (anArg);
   }
-  else if (anOp == "get")
-  {
-    TColStd_SequenceOfInteger anIds;
-    aViewer->GetAllZLayers (anIds);
-    for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
-    {
-      di << anIds.Value (aSeqIdx) << " ";
-    }
 
-    di << "\n";
-  }
-  else if (anOp == "settings")
+  // Check parameters
+  for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
+       aMapIt.More(); aMapIt.Next())
   {
-    if (argc < 3)
-    {
-      di << "Please also provide an id\n";
-      return 1;
-    }
-
-    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";
+    const TCollection_AsciiString& aKey = aMapIt.Key();
+    const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
 
-  }
-  else if (anOp == "enable")
-  {
-    if (argc < 3)
+    // Bool key, without arguments
+    if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
+        && anArgs->IsEmpty())
     {
-      di << "Please also provide an option to enable\n";
-      return 1;
+      continue;
     }
 
-    if (argc < 4)
+    // One argument
+    if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
+          && anArgs->Length() == 1)
     {
-      di << "Please also provide a layer id\n";
-      return 1;
+      continue;
     }
 
-    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")
+    // On/off arguments
+    if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
+        || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
+        || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
+        || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
+        && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
     {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthWrite);
-    }
-    else if (aSubOp == "depthclear" || aSubOp == "clear")
-    {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthClear);
+      continue;
     }
-    else if (aSubOp == "depthoffset" || aSubOp == "offset")
-    {
-      if (argc < 6)
-      {
-        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;
-      }
-
-      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);
 
-      aSettings.DepthOffsetFactor = aFactor;
-      aSettings.DepthOffsetUnits  = aUnits;
-
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthOffset);
-    }
-    else if (aSubOp == "positiveoffset" || aSubOp == "poffset")
-    {
-      aSettings.SetDepthOffsetPositive();
-    }
-    else if (aSubOp == "negativeoffset" || aSubOp == "noffset")
+    // One string argument
+    if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
+          || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
+          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
     {
-      aSettings.SetDepthOffsetNegative();
+      continue;
     }
 
-    aViewer->SetZLayerSettings (anId, aSettings);
-  }
-  else if (anOp == "disable")
-  {
-    if (argc < 3)
+    // One integer argument
+    if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
+          || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
+          || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
+          || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
+         && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
     {
-      di << "Please also provide an option to disable\n";
-      return 1;
+      continue;
     }
 
-    if (argc < 4)
+    // One real argument
+    if ( aKey.IsEqual ("arrowlength")
+         && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
     {
-      di << "Please also provide a layer id\n";
-      return 1;
+      continue;
     }
 
-    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")
+    // Two string arguments
+    if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
+         && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
     {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthTest);
-    }
-    else if (aSubOp == "depthwrite" || aSubOp == "write")
-    {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthWrite);
-    }
-    else if (aSubOp == "depthclear" || aSubOp == "clear")
-    {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthClear);
-    }
-    else if (aSubOp == "depthoffset" || aSubOp == "offset")
-    {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
+      continue;
     }
 
-    aViewer->SetZLayerSettings (anId, aSettings);
+    TCollection_AsciiString aLowerKey;
+    aLowerKey  = "-";
+    aLowerKey += aKey;
+    aLowerKey.LowerCase();
+    std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
+    std::cout << "Type help for more information.\n";
+    return 1;
   }
-  else
+
+  Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
+  if (anAISContext.IsNull())
   {
-    di << "Invalid operation, please use { add / del / get / settings / enable / disable}\n";
+    std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
     return 1;
   }
 
-  return 0;
-}
-
-DEFINE_STANDARD_HANDLE(V3d_TextItem, Visual3d_LayerItem)
-
-// this class provides a presentation of text item in v3d view under-/overlayer
-class V3d_TextItem : public Visual3d_LayerItem
-{
-public:
-
-  // CASCADE RTTI
-  DEFINE_STANDARD_RTTI(V3d_TextItem)
-
-  // constructor
-  Standard_EXPORT V3d_TextItem(const TCollection_AsciiString& theText,
-                               const Standard_Real theX1,
-                               const Standard_Real theY1,
-                               const Standard_Real theHeight,
-                               const TCollection_AsciiString& theFontName,
-                               const Quantity_Color& theColor,
-                               const Quantity_Color& theSubtitleColor,
-                               const Aspect_TypeOfDisplayText& theTypeOfDisplay,
-                               const Handle(Visual3d_Layer)& theLayer);
-
-  // redraw method
-  Standard_EXPORT void RedrawLayerPrs();
-
-private:
-
-  Standard_Real            myX1;
-  Standard_Real            myY1;
-  TCollection_AsciiString  myText;
-  Standard_Real            myHeight;
-  Handle(Visual3d_Layer)   myLayer;
-  Quantity_Color           myColor;
-  Quantity_Color           mySubtitleColor;
-  Aspect_TypeOfDisplayText myType;
-  TCollection_AsciiString  myFontName;
-};
-
-IMPLEMENT_STANDARD_HANDLE(V3d_TextItem, Visual3d_LayerItem)
-IMPLEMENT_STANDARD_RTTIEXT(V3d_TextItem, Visual3d_LayerItem)
-
-// create and add to display the text item
-V3d_TextItem::V3d_TextItem (const TCollection_AsciiString& theText,
-                            const Standard_Real theX1,
-                            const Standard_Real theY1,
-                            const Standard_Real theHeight,
-                            const TCollection_AsciiString& theFontName,
-                            const Quantity_Color& theColor,
-                            const Quantity_Color& theSubtitleColor,
-                            const Aspect_TypeOfDisplayText& theTypeOfDisplay,
-                            const Handle(Visual3d_Layer)& theLayer)
- : myX1 (theX1), myY1 (theY1),
-   myText (theText),
-   myHeight (theHeight),
-   myLayer (theLayer),
-   myColor (theColor),
-   mySubtitleColor (theSubtitleColor),
-   myType (theTypeOfDisplay),
-   myFontName (theFontName)
-{
-  if (!myLayer.IsNull ())
-    myLayer->AddLayerItem (this);
-}
-
-// render item
-void V3d_TextItem::RedrawLayerPrs ()
-{
-  if (myLayer.IsNull ())
-    return;
-
-  myLayer->SetColor (myColor);
-  myLayer->SetTextAttributes (myFontName.ToCString (), myType, mySubtitleColor);
-  myLayer->DrawText (myText.ToCString (), myX1, myY1, myHeight);
-}
-
-DEFINE_STANDARD_HANDLE(V3d_LineItem, Visual3d_LayerItem)
-
-// The Visual3d_LayerItem line item for "vlayerline" command
-// it provides a presentation of line with user-defined
-// linewidth, linetype and transparency.
-class V3d_LineItem : public Visual3d_LayerItem
-{
-public:
-  // CASCADE RTTI
-  DEFINE_STANDARD_RTTI(V3d_LineItem)
-
-  // constructor
-  Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
-                               Standard_Real X2, Standard_Real Y2,
-                               V3d_LayerMgrPointer theLayerMgr,
-                               Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
-                               Standard_Real theWidth    = 0.5,
-                               Standard_Real theTransp   = 1.0);
-
-  // redraw method
-  Standard_EXPORT   void RedrawLayerPrs();
-
-private:
-
-  Standard_Real       myX1, myY1, myX2, myY2;
-  V3d_LayerMgrPointer myLayerMgr;
-  Aspect_TypeOfLine   myType;
-  Standard_Real       myWidth;
-  Standard_Real       myTransparency;
-};
-
-IMPLEMENT_STANDARD_HANDLE(V3d_LineItem, Visual3d_LayerItem)
-IMPLEMENT_STANDARD_RTTIEXT(V3d_LineItem, Visual3d_LayerItem)
-
-// default constructor for line item
-V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
-                           Standard_Real X2, Standard_Real Y2,
-                           V3d_LayerMgrPointer theLayerMgr,
-                           Aspect_TypeOfLine theType,
-                           Standard_Real theWidth,
-                           Standard_Real theTransp) :
-  myX1(X1), myY1(Y1), myX2(X2), myY2(Y2), myLayerMgr(theLayerMgr),
-  myType(theType), myWidth(theWidth), myTransparency(theTransp)
-{
-  if (myLayerMgr && !myLayerMgr->Overlay().IsNull())
-    myLayerMgr->Overlay()->AddLayerItem (this);
-}
-
-// render line
-void V3d_LineItem::RedrawLayerPrs ()
-{
-  Handle (Visual3d_Layer) aOverlay;
-
-  if (myLayerMgr)
-    aOverlay = myLayerMgr->Overlay();
-
-  if (!aOverlay.IsNull())
+  Standard_Boolean toDisplay = Standard_True;
+  Quantity_Color aColor;
+  Graphic3d_GraduatedTrihedron aTrihedronData;
+  // Process parameters
+  Handle(TColStd_HSequenceOfAsciiString) aValues;
+  if (aMapOfArgs.Find ("off", aValues))
   {
-    Quantity_Color aColor(1.0, 0, 0, Quantity_TOC_RGB);
-    aOverlay->SetColor(aColor);
-    aOverlay->SetTransparency((Standard_ShortReal)myTransparency);
-    aOverlay->SetLineAttributes((Aspect_TypeOfLine)myType, myWidth);
-    aOverlay->BeginPolyline();
-    aOverlay->AddVertex(myX1, myY1);
-    aOverlay->AddVertex(myX2, myY2);
-    aOverlay->ClosePrimitive();
+    toDisplay = Standard_False;
   }
-}
 
-//=============================================================================
-//function : VLayerLine
-//purpose  : Draws line in the v3d view layer with given attributes: linetype,
-//         : linewidth, transparency coefficient
-//============================================================================
-static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
-{
-  // get the active view
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  // AXES NAMES
+  if (aMapOfArgs.Find ("xname", aValues))
   {
-    di << "Call vinit before!\n";
-    return 1;
+    aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
   }
-  else if (argc < 5)
+  if (aMapOfArgs.Find ("yname", aValues))
   {
-    di << "Use: " << argv[0];
-    di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
-    di << " linetype : { 0 | 1 | 2 | 3 } \n";
-    di << "              0 - solid  \n";
-    di << "              1 - dashed \n";
-    di << "              2 - dot    \n";
-    di << "              3 - dashdot\n";
-    di << " transparency : { 0.0 - 1.0 } \n";
-    di << "                  0.0 - transparent\n";
-    di << "                  1.0 - visible    \n";
-    return 1;
+    aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
   }
-
-  // get the input params
-  Standard_Real X1 = Draw::Atof(argv[1]);
-  Standard_Real Y1 = Draw::Atof(argv[2]);
-  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;
-
-  // has width
-  if (argc > 5)
-    aWidth = Draw::Atof(argv[5]);
-
-  // has type
-  if (argc > 6)
-     aType = (Standard_Integer) Draw::Atoi(argv[6]);
-
-  // has transparency
-  if (argc > 7)
+  if (aMapOfArgs.Find ("zname", aValues))
   {
-    aTransparency = Draw::Atof(argv[7]);
-    if (aTransparency < 0 || aTransparency > 1.0)
-      aTransparency = 1.0;
+    aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
   }
-
-  // select appropriate line type
-  Aspect_TypeOfLine aLineType;
-  switch (aType)
+  if (aMapOfArgs.Find ("xdrawname", aValues))
   {
-    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;
+    aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
   }
-
-  // replace layer manager
-  Handle(V3d_LayerMgr) aMgr = new V3d_LayerMgr(aView);
-  aView->SetLayerMgr(aMgr);
-
-  // add line item
-  Handle (V3d_LineItem) anItem = new V3d_LineItem(X1, Y1, X2, Y2,
-                                                  aMgr.operator->(),
-                                                  aLineType, aWidth,
-                                                  aTransparency);
-
-  // update view
-  aView->MustBeResized();
-  aView->Redraw();
-
-  return 0;
-}
-
-//=======================================================================
-//function : VOverlayText
-//purpose  : Test text displaying in view overlay
-//=======================================================================
-static int VOverlayText (Draw_Interpretor& di, Standard_Integer argc, const char**argv)
-{
-  // get the active view
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  if (aMapOfArgs.Find ("ydrawname", aValues))
   {
-    di << "No active view. Please call vinit.\n";
-    return 1;
+    aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
   }
-  else if (argc < 4 || argc > 13)
+  if (aMapOfArgs.Find ("zdrawname", aValues))
   {
-    di << "Use: " << argv[0];
-    di << " text x y [height] [font_name] [text_color: R G B] [displayType]\n";
-    di << "[background_color: R G B]\n";
-    di << "  height - pixel height of the text (default=10.0)\n";
-    di << "  font_name - name of font (default=courier)\n";
-    di << "  text_color - R G B values of text color (default=255.0 255.0 255.0)\n";
-    di << "  display_type = {normal/subtitle/decal/blend/dimension}, (default=normal)\n";
-    di << "  background_color- R G B values used for subtitle and decal text\n";
-    di << "(default=255.0 255.0 255.0)\n";
-    return 1;
+    aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("xnameoffset", aValues))
+  {
+    aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("ynameoffset", aValues))
+  {
+    aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("znameoffset", aValues))
+  {
+    aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
   }
 
-  TCollection_AsciiString aText (argv[1]);
-  Standard_Real aPosX = Draw::Atof(argv[2]);
-  Standard_Real aPosY = Draw::Atof(argv[3]);
-  Standard_Real aHeight = (argc >= 5) ? Draw::Atof (argv[4]) : 10.0;
-
-  // font name
-  TCollection_AsciiString aFontName = "Courier";
-  if (argc >= 6)
-    aFontName = TCollection_AsciiString (argv[5]);
-
-  // text colors
-  Quantity_Parameter aColorRed   = 1.0;
-  Quantity_Parameter aColorGreen = 1.0;
-  Quantity_Parameter aColorBlue  = 1.0;
-  if (argc >= 9)
+  // COLORS
+  if (aMapOfArgs.Find ("xnamecolor", aValues))
+  {
+    if (!GetColor (aValues->Value(1), aColor))
+    {
+      std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
+      return 1;
+    }
+    aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
+  }
+  if (aMapOfArgs.Find ("ynamecolor", aValues))
+  {
+    if (!GetColor (aValues->Value(1), aColor))
+    {
+      std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
+      return 1;
+    }
+    aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
+  }
+  if (aMapOfArgs.Find ("znamecolor", aValues))
+  {
+    if (!GetColor (aValues->Value(1), aColor))
+    {
+      std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
+      return 1;
+    }
+    aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
+  }
+  if (aMapOfArgs.Find ("xcolor", aValues))
+  {
+    if (!GetColor (aValues->Value(1), aColor))
+    {
+      std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
+      return 1;
+    }
+    aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
+  }
+  if (aMapOfArgs.Find ("ycolor", aValues))
+  {
+    if (!GetColor (aValues->Value(1), aColor))
+    {
+      std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
+      return 1;
+    }
+    aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
+  }
+  if (aMapOfArgs.Find ("zcolor", aValues))
   {
-    aColorRed   = Draw::Atof (argv[6])/255.;
-    aColorGreen = Draw::Atof (argv[7])/255.;
-    aColorBlue  = Draw::Atof (argv[8])/255.;
+    if (!GetColor (aValues->Value(1), aColor))
+    {
+      std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
+      return 1;
+    }
+    aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
   }
 
-  // display type
-  TCollection_AsciiString aDispStr;
-  if (argc >= 10)
-    aDispStr = TCollection_AsciiString (argv[9]);
+  // TICKMARKS
+  if (aMapOfArgs.Find ("xticks", aValues))
+  {
+    aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("yticks", aValues))
+  {
+    aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("zticks", aValues))
+  {
+    aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("xticklength", aValues))
+  {
+    aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("yticklength", aValues))
+  {
+    aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("zticklength", aValues))
+  {
+    aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("xdrawticks", aValues))
+  {
+    aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("ydrawticks", aValues))
+  {
+    aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("zdrawticks", aValues))
+  {
+    aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
+  }
 
-  Aspect_TypeOfDisplayText aTextType = Aspect_TODT_NORMAL;
-  if (aDispStr.IsEqual ("subtitle"))
-    aTextType = Aspect_TODT_SUBTITLE;
-  else if (aDispStr.IsEqual ("decal"))
-    aTextType = Aspect_TODT_DEKALE;
-  else if (aDispStr.IsEqual ("blend"))
-    aTextType = Aspect_TODT_BLEND;
-  else if (aDispStr.IsEqual ("dimension"))
-    aTextType = Aspect_TODT_DIMENSION;
+  // VALUES
+  if (aMapOfArgs.Find ("xdrawvalues", aValues))
+  {
+    aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("ydrawvalues", aValues))
+  {
+    aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("zdrawvalues", aValues))
+  {
+    aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("xvaluesoffset", aValues))
+  {
+    aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("yvaluesoffset", aValues))
+  {
+    aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
+  }
+  if (aMapOfArgs.Find ("zvaluesoffset", aValues))
+  {
+    aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
+  }
 
-  // subtitle color
-  Quantity_Parameter aSubRed   = 1.0;
-  Quantity_Parameter aSubGreen = 1.0;
-  Quantity_Parameter aSubBlue  = 1.0;
-  if (argc == 13)
+  // ARROWS
+  if (aMapOfArgs.Find ("arrowlength", aValues))
   {
-    aSubRed   = Draw::Atof (argv[10])/255.;
-    aSubGreen = Draw::Atof (argv[11])/255.;
-    aSubBlue  = Draw::Atof (argv[12])/255.;
+    aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
   }
 
-  // check fo current overlay
-  Handle(Visual3d_Layer) anOverlay = aView->Viewer()->Viewer()->OverLayer ();
-  if (anOverlay.IsNull ())
+  // FONTS
+  if (aMapOfArgs.Find ("namefont", aValues))
   {
-    Handle(V3d_LayerMgr) aMgr = new V3d_LayerMgr (aView);
-    anOverlay = aMgr->Overlay ();
-    aView->SetLayerMgr (aMgr);
+    aTrihedronData.SetNamesFont (aValues->Value(1));
+  }
+  if (aMapOfArgs.Find ("valuesfont", aValues))
+  {
+    aTrihedronData.SetValuesFont (aValues->Value(1));
   }
 
-  Quantity_Color aTextColor (aColorRed, aColorGreen,
-    aColorBlue, Quantity_TOC_RGB);
-  Quantity_Color aSubtColor (aSubRed, aSubGreen,
-    aSubBlue, Quantity_TOC_RGB);
+  if (aMapOfArgs.Find ("drawgrid", aValues))
+  {
+    aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
+  }
+  if (aMapOfArgs.Find ("drawaxes", aValues))
+  {
+    aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
+  }
 
-  // add text item
-  Handle(V3d_TextItem) anItem = new V3d_TextItem (aText, aPosX, aPosY,
-    aHeight, aFontName, aTextColor, aSubtColor, aTextType, anOverlay);
+  // The final step: display of erase trihedron
+  if (toDisplay)
+  {
+    ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
+  }
+  else
+  {
+    ViewerTest::CurrentView()->GraduatedTrihedronErase();
+  }
 
-  // update view
-  aView->MustBeResized();
-  aView->Redraw();
+  ViewerTest::GetAISContext()->UpdateCurrentViewer();
+  ViewerTest::CurrentView()->Redraw();
 
   return 0;
 }
 
 //==============================================================================
-//function : VGrid
+//function : VTile
 //purpose  :
 //==============================================================================
-
-static int VGrid (Draw_Interpretor& /*theDI*/,
+static int VTile (Draw_Interpretor& theDI,
                   Standard_Integer  theArgNb,
                   const char**      theArgVec)
 {
-  // get the active view
-  Handle(V3d_View)   aView   = ViewerTest::CurrentView();
-  Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
-  if (aView.IsNull() || aViewer.IsNull())
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    std::cerr << "No active view. Please call vinit.\n";
+    std::cerr << "Error: no active viewer.\n";
     return 1;
   }
 
-  Aspect_GridType     aType = aViewer->GridType();
-  Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
+  Graphic3d_CameraTile aTile = aView->Camera()->Tile();
+  if (theArgNb < 2)
+  {
+    theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
+          << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
+          << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
+    return 0;
+  }
 
-  Standard_Integer anIter = 1;
-  for (; anIter < theArgNb; ++anIter)
+  aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    const char* aValue = theArgVec[anIter];
-    if (*aValue == 'r')
-    {
-      aType = Aspect_GT_Rectangular;
-    }
-    else if (*aValue == 'c')
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anArg == "-lowerleft"
+     || anArg == "-upperleft")
     {
-      aType = Aspect_GT_Circular;
+      if (anArgIter + 3 < theArgNb)
+      {
+        std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
+        return 1;
+      }
+      aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
+      aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
+      aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
     }
-    else if (*aValue == 'l')
+    else if (anArg == "-total"
+          || anArg == "-totalsize"
+          || anArg == "-viewsize")
     {
-      aMode = Aspect_GDM_Lines;
+      if (anArgIter + 3 < theArgNb)
+      {
+        std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
+        return 1;
+      }
+      aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
+      aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
+      if (aTile.TotalSize.x() < 1
+       || aTile.TotalSize.y() < 1)
+      {
+        std::cerr << "Error: total size is incorrect.\n";
+        return 1;
+      }
     }
-    else if (*aValue == 'p')
+    else if (anArg == "-tilesize")
     {
-      aMode = Aspect_GDM_Points;
+      if (anArgIter + 3 < theArgNb)
+      {
+        std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
+        return 1;
+      }
+
+      aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
+      aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
+      if (aTile.TileSize.x() < 1
+       || aTile.TileSize.y() < 1)
+      {
+        std::cerr << "Error: tile size is incorrect.\n";
+        return 1;
+      }
     }
-    else if (strcmp (aValue, "off" ) == 0)
+    else if (anArg == "-unset")
     {
-      aViewer->DeactivateGrid();
+      aView->Camera()->SetTile (Graphic3d_CameraTile());
+      aView->Redraw();
       return 0;
     }
-    else
-    {
-      break;
-    }
   }
 
-  Standard_Integer aTail = (theArgNb - anIter);
-  if (aTail == 0)
+  if (aTile.TileSize.x() < 1
+   || aTile.TileSize.y() < 1)
   {
-    aViewer->ActivateGrid (aType, aMode);
-    return 0;
+    std::cerr << "Error: tile size is undefined.\n";
+    return 1;
   }
-  else if (aTail != 2 && aTail != 5)
+  else if (aTile.TotalSize.x() < 1
+        || aTile.TotalSize.y() < 1)
   {
-    std::cerr << "Incorrect arguments number! Usage:\n"
-              << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
+    std::cerr << "Error: total size is undefined.\n";
     return 1;
   }
 
-  Quantity_Length anOriginX, anOriginY;
-  Quantity_PlaneAngle aRotAngle;
-  if (aType == Aspect_GT_Rectangular)
-  {
-    Quantity_Length aRStepX, aRStepY;
-    aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
+  aView->Camera()->SetTile (aTile);
+  aView->Redraw();
+  return 0;
+}
 
-    anOriginX = Draw::Atof (theArgVec[anIter++]);
-    anOriginY = Draw::Atof (theArgVec[anIter++]);
-    if (aTail == 5)
-    {
-      aRStepX   = Draw::Atof (theArgVec[anIter++]);
-      aRStepY   = Draw::Atof (theArgVec[anIter++]);
-      aRotAngle = Draw::Atof (theArgVec[anIter++]);
-    }
-    aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
-    aViewer->ActivateGrid (aType, aMode);
-  }
-  else if (aType == Aspect_GT_Circular)
+//! Format ZLayer ID.
+inline const char* formZLayerId (const Standard_Integer theLayerId)
+{
+  switch (theLayerId)
   {
-    Quantity_Length aRadiusStep;
-    Standard_Integer aDivisionNumber;
-    aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
-
-    anOriginX = Draw::Atof (theArgVec[anIter++]);
-    anOriginY = Draw::Atof (theArgVec[anIter++]);
-    if (aTail == 5)
-    {
-      aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
-      aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
-      aRotAngle       = Draw::Atof (theArgVec[anIter++]);
-    }
-
-    aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
-    aViewer->ActivateGrid (aType, aMode);
+    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 0;
+  return "";
 }
 
-//==============================================================================
-//function : VFps
-//purpose  :
-//==============================================================================
-
-static int VFps (Draw_Interpretor& theDI,
-                 Standard_Integer  theArgNb,
-                 const char**      theArgVec)
+//! Print the ZLayer information.
+inline void printZLayerInfo (Draw_Interpretor& theDI,
+                             const Graphic3d_ZLayerSettings& theLayer)
 {
-  // get the active view
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  if (!theLayer.Name().IsEmpty())
   {
-    std::cerr << "No active view. Please call vinit.\n";
-    return 1;
+    theDI << "  Name: " << theLayer.Name() << "\n";
   }
-
-  Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
-  if (aFramesNb <= 0)
+  if (theLayer.IsImmediate())
   {
-    std::cerr << "Incorrect arguments!\n";
-    return 1;
+    theDI << "  Immediate: TRUE\n";
   }
-
-  // the time is meaningless for first call
-  // due to async OpenGl rendering
-  aView->Redraw();
-
-  // redraw view in loop to estimate average values
-  OSD_Timer aTimer;
-  aTimer.Start();
-  for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
+  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)
   {
-    aView->Redraw();
+    theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
   }
-  aTimer.Stop();
-  Standard_Real aCpu;
-  const Standard_Real aTime = aTimer.ElapsedTime();
-  aTimer.OSD_Chronometer::Show (aCpu);
-
-  const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
-  const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
-
-  // return statistics
-  theDI << "FPS: " << aFpsAver << "\n"
-        << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
-
-  return 0;
 }
 
 //==============================================================================
-//function : VGlDebug
-//purpose  :
+//function : VZLayer
+//purpose  : Test z layer operations for v3d viewer
 //==============================================================================
-
-static int VGlDebug (Draw_Interpretor& theDI,
-                     Standard_Integer  theArgNb,
-                     const char**      theArgVec)
+static int VZLayer (Draw_Interpretor& theDI,
+                    Standard_Integer  theArgNb,
+                    const char**      theArgVec)
 {
-  Handle(OpenGl_GraphicDriver) aDriver;
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (!aView.IsNull())
+  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
+  if (aContextAIS.IsNull())
   {
-    aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
+    std::cout << "No active viewer!\n";
+    return 1;
   }
+
+  const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
   if (theArgNb < 2)
   {
-    if (aDriver.IsNull())
+    TColStd_SequenceOfInteger aLayers;
+    aViewer->GetAllZLayers (aLayers);
+    for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
     {
-      std::cerr << "No active view. Please call vinit.\n";
-      return 0;
+      theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
+      printZLayerInfo (theDI, aSettings);
     }
-
-    Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )glGetString (GL_EXTENSIONS),
-                                                                "GL_ARB_debug_output");
-    std::cout << "Active graphic driver: debug " << (isActive ? "ON" : "OFF") << "\n";
-    theDI << (isActive ? "1" : "0");
-    return 0;
+    return 1;
   }
 
-  const Standard_Boolean toEnableDebug = Draw::Atoi (theArgVec[1]) != 0;
-  ViewerTest_myDefaultCaps.contextDebug = toEnableDebug;
-  ViewerTest_myDefaultCaps.glslWarnings = toEnableDebug;
-  if (aDriver.IsNull())
+  Standard_Integer anArgIter = 1;
+  Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
+  ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
+  if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
   {
-    return 0;
+    ++anArgIter;
   }
 
-  aDriver->ChangeOptions().glslWarnings = toEnableDebug;
-  return 0;
-}
-
-//==============================================================================
-//function : VVbo
-//purpose  :
-//==============================================================================
-
-static int VVbo (Draw_Interpretor& theDI,
-                 Standard_Integer  theArgNb,
-                 const char**      theArgVec)
-{
-  const Standard_Boolean toSet    = (theArgNb > 1);
-  const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
-  if (toSet)
+  TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
+  if (aFirstArg.IsIntegerValue())
   {
-    ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
+    ++anArgIter;
+    aLayerId = aFirstArg.IntegerValue();
   }
-
-  // get the context
-  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
-  if (aContextAIS.IsNull())
+  else
   {
-    if (!toSet)
+    aFirstArg.LowerCase();
+    if (aFirstArg == "default"
+     || aFirstArg == "def")
     {
-      std::cerr << "No active view!\n";
+      aLayerId = Graphic3d_ZLayerId_Default;
+      ++anArgIter;
     }
-    return 1;
-  }
-  Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
-  if (!aDriver.IsNull())
-  {
-    if (!toSet)
+    else if (aFirstArg == "top")
     {
-      theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
+      aLayerId = Graphic3d_ZLayerId_Top;
+      ++anArgIter;
+    }
+    else if (aFirstArg == "topmost")
+    {
+      aLayerId = Graphic3d_ZLayerId_Topmost;
+      ++anArgIter;
+    }
+    else if (aFirstArg == "overlay"
+          || aFirstArg == "toposd")
+    {
+      aLayerId = Graphic3d_ZLayerId_TopOSD;
+      ++anArgIter;
+    }
+    else if (aFirstArg == "underlay"
+          || aFirstArg == "botosd")
+    {
+      aLayerId = Graphic3d_ZLayerId_BotOSD;
+      ++anArgIter;
     }
     else
     {
-      aDriver->ChangeOptions().vboDisable = toUseVbo;
+      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;
+        }
+      }
     }
   }
 
-  return 0;
-}
-
-//==============================================================================
-//function : VCaps
-//purpose  :
-//==============================================================================
-
-static int VCaps (Draw_Interpretor& theDI,
-                  Standard_Integer  theArgNb,
-                  const char**      theArgVec)
-{
-  OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
-  Handle(OpenGl_GraphicDriver)   aDriver;
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if (!aContext.IsNull())
-  {
-    aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
-    aCaps   = &aDriver->ChangeOptions();
-  }
-
-  if (theArgNb < 2)
-  {
-    theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
-    theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
-    theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
-    theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
-    return 0;
-  }
-
-  ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
-  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  for (; anArgIter < theArgNb; ++anArgIter)
   {
-    Standard_CString        anArg     = theArgVec[anArgIter];
-    TCollection_AsciiString anArgCase (anArg);
-    anArgCase.LowerCase();
+    // perform operation
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
     if (anUpdateTool.parseRedrawMode (anArg))
     {
-      continue;
+      //
     }
-    else if (anArgCase == "-ffp")
+    else if (anArg == "-add"
+          || anArg == "add")
     {
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      aLayerId = Graphic3d_ZLayerId_UNKNOWN;
+      if (!aViewer->AddZLayer (aLayerId))
       {
-        --anArgIter;
+        std::cout << "Error: can not add a new z layer!\n";
+        return 0;
       }
-      aCaps->ffpEnable = toEnable;
+
+      theDI << aLayerId;
     }
-    else if (anArgCase == "-vbo")
+    else if (anArg == "-del"
+          || anArg == "-delete"
+          || anArg == "del")
     {
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
       {
-        --anArgIter;
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of z layer to remove is missing\n";
+          return 1;
+        }
+
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
       }
-      aCaps->vboDisable = !toEnable;
-    }
-    else if (anArgCase == "-sprite"
-          || anArgCase == "-sprites")
-    {
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+
+      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)
       {
-        --anArgIter;
+        std::cout << "Syntax error: standard Z layer can not be removed\n";
+        return 1;
+      }
+
+      // 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);
+      }
+
+      if (!aViewer->RemoveZLayer (aLayerId))
+      {
+        std::cout << "Z layer can not be removed!\n";
+      }
+      else
+      {
+        theDI << aLayerId << " ";
       }
-      aCaps->pntSpritesDisable = !toEnable;
     }
-    else if (anArgCase == "-softmode")
+    else if (anArg == "-get"
+          || anArg == "get")
     {
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      TColStd_SequenceOfInteger aLayers;
+      aViewer->GetAllZLayers (aLayers);
+      for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
       {
-        --anArgIter;
+        theDI << aLayeriter.Value() << " ";
       }
-      aCaps->contextNoAccel = toEnable;
+
+      theDI << "\n";
     }
-    else if (anArgCase == "-accel"
-          || anArgCase == "-acceleration")
+    else if (anArg == "-name")
     {
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
       {
-        --anArgIter;
+        std::cout << "Syntax error: id of Z layer is missing\n";
+        return 1;
       }
-      aCaps->contextNoAccel = !toEnable;
+
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error: name is missing\n";
+        return 1;
+      }
+
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      aSettings.SetName (theArgVec[anArgIter]);
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
     }
-    else
+    else if (anArg == "-origin")
     {
-      std::cout << "Error: unknown argument '" << anArg << "'\n";
-      return 1;
-    }
-  }
-  if (aCaps != &ViewerTest_myDefaultCaps)
-  {
-    ViewerTest_myDefaultCaps = *aCaps;
+      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 (anArg == "-settings"
+          || anArg == "settings")
+    {
+      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 (anArg == "-enable"
+          || anArg == "enable"
+          || anArg == "-disable"
+          || anArg == "disable")
+    {
+      const Standard_Boolean toEnable = anArg == "-enable"
+                                     || anArg == "enable";
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error: option name is missing\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;
+        }
+
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
+      }
+
+      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;
 }
 
-//==============================================================================
-//function : VMemGpu
-//purpose  :
-//==============================================================================
+// 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
+{
+public:
+  // CASCADE RTTI
+  DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
 
-static int VMemGpu (Draw_Interpretor& theDI,
-                    Standard_Integer  theArgNb,
-                    const char**      theArgVec)
+  // constructor
+  Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
+                               Standard_Real X2, Standard_Real Y2,
+                               Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
+                               Standard_Real theWidth    = 0.5,
+                               Standard_Real theTransp   = 1.0);
+
+  private:
+
+  void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
+                const Handle(Prs3d_Presentation)& thePresentation,
+                const Standard_Integer theMode) Standard_OVERRIDE;
+
+  void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
+                         const Standard_Integer /*aMode*/) Standard_OVERRIDE
+  {}
+
+private:
+
+  Standard_Real       myX1, myY1, myX2, myY2;
+  Aspect_TypeOfLine   myType;
+  Standard_Real       myWidth;
+};
+
+// default constructor for line item
+V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
+                           Standard_Real X2, Standard_Real Y2,
+                           Aspect_TypeOfLine theType,
+                           Standard_Real theWidth,
+                           Standard_Real theTransp) :
+  myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
+  myType(theType), myWidth(theWidth)
 {
-  // get the context
-  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
-  if (aContextAIS.IsNull())
+  SetTransparency (1-theTransp);
+}
+
+// render line
+void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
+                            const Handle(Prs3d_Presentation)& thePresentation,
+                            const Standard_Integer /*theMode*/)
+{
+  thePresentation->Clear();
+  Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
+  Standard_Integer aWidth, aHeight;
+  ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
+  Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
+  Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
+  aPrim->AddVertex(myX1, aHeight-myY1, 0.);
+  aPrim->AddVertex(myX2, aHeight-myY2, 0.);
+  Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
+  aGroup->SetPrimitivesAspect (anAspect->Aspect());
+  aGroup->AddPrimitiveArray (aPrim);
+}
+
+//=============================================================================
+//function : VLayerLine
+//purpose  : Draws line in the v3d view layer with given attributes: linetype,
+//         : linewidth, transparency coefficient
+//============================================================================
+static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+{
+  // get the active view
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    std::cerr << "No active view. Please call vinit.\n";
+    di << "Call vinit before!\n";
     return 1;
   }
-
-  Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
-  if (aDriver.IsNull())
+  else if (argc < 5)
   {
-    std::cerr << "Graphic driver not available.\n";
+    di << "Use: " << argv[0];
+    di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
+    di << " linetype : { 0 | 1 | 2 | 3 } \n";
+    di << "              0 - solid  \n";
+    di << "              1 - dashed \n";
+    di << "              2 - dot    \n";
+    di << "              3 - dashdot\n";
+    di << " transparency : { 0.0 - 1.0 } \n";
+    di << "                  0.0 - transparent\n";
+    di << "                  1.0 - visible    \n";
     return 1;
   }
 
-  Standard_Size aFreeBytes = 0;
-  TCollection_AsciiString anInfo;
-  if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  // get the input params
+  Standard_Real X1 = Draw::Atof(argv[1]);
+  Standard_Real Y1 = Draw::Atof(argv[2]);
+  Standard_Real X2 = Draw::Atof(argv[3]);
+  Standard_Real Y2 = Draw::Atof(argv[4]);
+
+  Standard_Real aWidth = 0.5;
+  Standard_Real aTransparency = 1.0;
+
+  // has width
+  if (argc > 5)
+    aWidth = Draw::Atof(argv[5]);
+
+  // select appropriate line type
+  Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
+  if (argc > 6
+  && !ViewerTest::ParseLineType (argv[6], aLineType))
   {
-    std::cerr << "Information not available.\n";
+    std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
     return 1;
   }
 
-  if (theArgNb > 1 && *theArgVec[1] == 'f')
+  // has transparency
+  if (argc > 7)
   {
-    theDI << Standard_Real (aFreeBytes);
+    aTransparency = Draw::Atof(argv[7]);
+    if (aTransparency < 0 || aTransparency > 1.0)
+      aTransparency = 1.0;
   }
-  else
+
+  static Handle (V3d_LineItem) aLine;
+  if (!aLine.IsNull())
   {
-    theDI << anInfo;
+    aContext->Erase (aLine);
   }
+  aLine = new V3d_LineItem (X1, Y1, X2, Y2,
+                            aLineType, aWidth,
+                            aTransparency);
+
+  aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
+  aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
+  aLine->SetToUpdate();
+  aContext->Display (aLine, Standard_True);
 
   return 0;
 }
 
-// ==============================================================================
-// function : VReadPixel
-// purpose  :
-// ==============================================================================
-static int VReadPixel (Draw_Interpretor& theDI,
-                       Standard_Integer  theArgNb,
-                       const char**      theArgVec)
+
+//==============================================================================
+//function : VGrid
+//purpose  :
+//==============================================================================
+
+static int VGrid (Draw_Interpretor& /*theDI*/,
+                  Standard_Integer  theArgNb,
+                  const char**      theArgVec)
 {
   // get the active view
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  Handle(V3d_View)   aView   = ViewerTest::CurrentView();
+  Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
+  if (aView.IsNull() || aViewer.IsNull())
   {
     std::cerr << "No active view. Please call vinit.\n";
     return 1;
   }
-  else if (theArgNb < 3)
-  {
-    std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
-    return 1;
-  }
-
-  Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
-  Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
 
-  Standard_Integer aWidth, aHeight;
-  aView->Window()->Size (aWidth, aHeight);
-  const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
-  const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
-  if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
-  {
-    std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
-    return 1;
-  }
+  Aspect_GridType     aType = aViewer->GridType();
+  Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
 
-  Standard_Boolean toShowName = Standard_False;
-  Standard_Boolean toShowHls  = Standard_False;
-  for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
+  Standard_Integer anIter = 1;
+  for (; anIter < theArgNb; ++anIter)
   {
-    const char* aParam = theArgVec[anIter];
-    if ( strcasecmp( aParam, "rgb" ) == 0 )
-    {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
-      aBufferType = Graphic3d_BT_RGB;
-    }
-    else if ( strcasecmp( aParam, "hls" ) == 0 )
+    const char* aValue = theArgVec[anIter];
+    if (*aValue == 'r')
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
-      aBufferType = Graphic3d_BT_RGB;
-      toShowHls   = Standard_True;
+      aType = Aspect_GT_Rectangular;
     }
-    else if ( strcasecmp( aParam, "rgbf" ) == 0 )
+    else if (*aValue == 'c')
     {
-      aFormat     = Image_PixMap::ImgRGBF;
-      aBufferType = Graphic3d_BT_RGB;
+      aType = Aspect_GT_Circular;
     }
-    else if ( strcasecmp( aParam, "rgba" ) == 0 )
+    else if (*aValue == 'l')
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
-      aBufferType = Graphic3d_BT_RGBA;
+      aMode = Aspect_GDM_Lines;
     }
-    else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
+    else if (*aValue == 'p')
     {
-      aFormat     = Image_PixMap::ImgRGBAF;
-      aBufferType = Graphic3d_BT_RGBA;
+      aMode = Aspect_GDM_Points;
     }
-    else if ( strcasecmp( aParam, "depth" ) == 0 )
+    else if (strcmp (aValue, "off" ) == 0)
     {
-      aFormat     = Image_PixMap::ImgGrayF;
-      aBufferType = Graphic3d_BT_Depth;
+      aViewer->DeactivateGrid();
+      return 0;
     }
-    else if ( strcasecmp( aParam, "name" ) == 0 )
+    else
     {
-      toShowName = Standard_True;
+      break;
     }
   }
 
-  Image_PixMap anImage;
-  if (!anImage.InitTrash (aFormat, aWidth, aHeight))
+  Standard_Integer aTail = (theArgNb - anIter);
+  if (aTail == 0)
   {
-    std::cerr << "Image allocation failed\n";
-    return 1;
+    aViewer->ActivateGrid (aType, aMode);
+    return 0;
   }
-  else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
+  else if (aTail != 2 && aTail != 5)
   {
-    std::cerr << "Image dump failed\n";
+    std::cerr << "Incorrect arguments number! Usage:\n"
+              << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
     return 1;
   }
 
-  Quantity_Parameter anAlpha;
-  Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
-  if (toShowName)
+  Quantity_Length anOriginX, anOriginY;
+  Quantity_PlaneAngle aRotAngle;
+  if (aType == Aspect_GT_Rectangular)
   {
-    if (aBufferType == Graphic3d_BT_RGBA)
-    {
-      theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
-    }
-    else
+    Quantity_Length aRStepX, aRStepY;
+    aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
+
+    anOriginX = Draw::Atof (theArgVec[anIter++]);
+    anOriginY = Draw::Atof (theArgVec[anIter++]);
+    if (aTail == 5)
     {
-      theDI << Quantity_Color::StringName (aColor.Name());
+      aRStepX   = Draw::Atof (theArgVec[anIter++]);
+      aRStepY   = Draw::Atof (theArgVec[anIter++]);
+      aRotAngle = Draw::Atof (theArgVec[anIter++]);
     }
+    aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
+    aViewer->ActivateGrid (aType, aMode);
   }
-  else
+  else if (aType == Aspect_GT_Circular)
   {
-    switch (aBufferType)
+    Quantity_Length aRadiusStep;
+    Standard_Integer aDivisionNumber;
+    aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
+
+    anOriginX = Draw::Atof (theArgVec[anIter++]);
+    anOriginY = Draw::Atof (theArgVec[anIter++]);
+    if (aTail == 5)
     {
-      default:
-      case Graphic3d_BT_RGB:
-      {
-        if (toShowHls)
-        {
-          theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
-        }
-        else
-        {
-          theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
-        }
-        break;
-      }
-      case Graphic3d_BT_RGBA:
-      {
-        theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
-        break;
-      }
-      case Graphic3d_BT_Depth:
-      {
-        theDI << aColor.Red();
-        break;
-      }
+      aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
+      aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
+      aRotAngle       = Draw::Atof (theArgVec[anIter++]);
     }
+
+    aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
+    aViewer->ActivateGrid (aType, aMode);
   }
 
   return 0;
 }
 
 //==============================================================================
-//function : VDiffImage
-//purpose  : The draw-command compares two images.
+//function : VPriviledgedPlane
+//purpose  :
 //==============================================================================
 
-static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+static int VPriviledgedPlane (Draw_Interpretor& theDI,
+                              Standard_Integer  theArgNb,
+                              const char**      theArgVec)
 {
-  if (theArgNb < 6)
+  if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
   {
-    theDI << "Not enough arguments.\n";
+    std::cerr << "Error: wrong number of arguments! See usage:\n";
+    theDI.PrintHelp (theArgVec[0]);
     return 1;
   }
 
-  // image file names
-  const char* anImgPathRef = theArgVec[1];
-  const char* anImgPathNew = theArgVec[2];
-
-  // get string tolerance and check its validity
-  Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
-  if (aTolColor < 0.0)
-    aTolColor = 0.0;
-  if (aTolColor > 1.0)
-    aTolColor = 1.0;
-
-  Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
-  Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
-
-  // image file of difference
-  const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
-
-  // compare the images
-  Image_Diff aComparer;
-  if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
+  // get the active viewer
+  Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
+  if (aViewer.IsNull())
   {
+    std::cerr << "Error: no active viewer. Please call vinit.\n";
     return 1;
   }
 
-  aComparer.SetColorTolerance (aTolColor);
-  aComparer.SetBorderFilterOn (isBorderFilterOn);
-  Standard_Integer aDiffColorsNb = aComparer.Compare();
-  theDI << aDiffColorsNb << "\n";
-
-  // save image of difference
-  if (aDiffImagePath != NULL)
+  if (theArgNb == 1)
   {
-    aComparer.SaveDiffImage (aDiffImagePath);
+    gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
+    const gp_Pnt& anOrig = aPriviledgedPlane.Location();
+    const gp_Dir& aNorm = aPriviledgedPlane.Direction();
+    const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
+    theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
+          << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
+          << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
+    return 0;
   }
 
-  return 0;
-}
-
-//=======================================================================
-//function : VSelect
-//purpose  : Emulates different types of selection by mouse:
-//           1) single click selection
-//           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
-//           3) selection with polygon having corners at
-//           pixel positions (x1,y1),...,(xn,yn)
-//           4) any of these selections with shift button pressed
-//=======================================================================
-static Standard_Integer VSelect (Draw_Interpretor& di,
-                                 Standard_Integer argc,
-                                 const char ** argv)
-{
-  if(argc < 3)
-  {
-    di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]" << "\n";
-    return 1;
-  }
+  Standard_Integer anArgIdx = 1;
+  Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
+  Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
+  Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
+  Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
+  Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
+  Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
 
-  Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
-  if(myAIScontext.IsNull())
-  {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
-  }
-  const Standard_Boolean isShiftSelection = (argc>3 && !(argc%2) && (atoi(argv[argc-1])==1));
-  Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
-  aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
-  if(argc <= 4)
-  {
-    if(isShiftSelection)
-      aCurrentEventManager->ShiftSelect();
-    else
-      aCurrentEventManager->Select();
-  }
-  else if(argc <= 6)
+  gp_Ax3 aPriviledgedPlane;
+  gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
+  gp_Dir aNorm (aNormX, aNormY, aNormZ);
+  if (theArgNb > 7)
   {
-    if(isShiftSelection)
-      aCurrentEventManager->ShiftSelect(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]),atoi(argv[4]));
-    else
-      aCurrentEventManager->Select(atoi(argv[1]),atoi(argv[2]),atoi(argv[3]),atoi(argv[4]));
+    Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
+    Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
+    Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
+    gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
+    aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
   }
   else
   {
-    Standard_Integer anUpper = 0;
-
-    if(isShiftSelection)
-      anUpper = (argc-1)/2;
-    else
-      anUpper = argc/2;
-    TColgp_Array1OfPnt2d aPolyline(1,anUpper);
+    aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
+  }
 
-    for(Standard_Integer i=1;i<=anUpper;++i)
-      aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
+  aViewer->SetPrivilegedPlane (aPriviledgedPlane);
 
-    if(isShiftSelection)
-      aCurrentEventManager->ShiftSelect(aPolyline);
-    else
-      aCurrentEventManager->Select(aPolyline);
-  }
   return 0;
 }
 
-//=======================================================================
-//function : VMoveTo
-//purpose  : Emulates cursor movement to defined pixel position
-//=======================================================================
-static Standard_Integer VMoveTo (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+//==============================================================================
+//function : VConvert
+//purpose  :
+//==============================================================================
+
+static int VConvert (Draw_Interpretor& theDI,
+                     Standard_Integer  theArgNb,
+                     const char**      theArgVec)
 {
-  if(argc != 3)
+  // get the active view
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    di << "Usage : " << argv[0] << " x y" << "\n";
+    std::cerr << "Error: no active view. Please call vinit.\n";
     return 1;
   }
 
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
-  {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
-  }
-  ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
-  return 0;
-}
+  enum { Model, Ray, View, Window, Grid } aMode = Model;
 
-//=================================================================================================
-//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())
+  // access coordinate arguments
+  TColStd_SequenceOfReal aCoord;
+  Standard_Integer anArgIdx = 1;
+  for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
   {
-    std::cout << theArgVec[0] << ": please initialize or activate view.\n";
-    return 1;
+    TCollection_AsciiString anArg (theArgVec[anArgIdx]);
+    if (!anArg.IsRealValue())
+    {
+      break;
+    }
+    aCoord.Append (anArg.RealValue());
   }
 
-  if (theArgsNb == 1)
+  // non-numeric argument too early
+  if (aCoord.IsEmpty())
   {
-    // 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";
-    return 0;
+    std::cerr << "Error: wrong number of arguments! See usage:\n";
+    theDI.PrintHelp (theArgVec[0]);
+    return 1;
   }
 
-  // -------------------------
-  //  Parse options and values
-  // -------------------------
-
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfKeysByValues;
-  TCollection_AsciiString aParseKey;
-  for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
+  // collect all other arguments and options
+  for (; anArgIdx < theArgNb; ++anArgIdx)
   {
-    TCollection_AsciiString anArg (theArgVec [anArgIt]);
-
-    if (anArg.Value (1) == '-' && !anArg.IsRealValue())
-    {
-      aParseKey = anArg;
-      aParseKey.Remove (1);
-      aParseKey.UpperCase();
-      aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
-      continue;
-    }
-
-    if (aParseKey.IsEmpty())
+    TCollection_AsciiString anArg (theArgVec[anArgIdx]);
+    anArg.LowerCase();
+    if      (anArg == "window") aMode = Window;
+    else if (anArg == "view")   aMode = View;
+    else if (anArg == "grid")   aMode = Grid;
+    else if (anArg == "ray")    aMode = Ray;
+    else
     {
-      std::cout << theArgVec[0] << ": values should be passed with key.\n";
-      std::cout << "Type help for more information.\n";
+      std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
+      theDI.PrintHelp (theArgVec[0]);
       return 1;
     }
-
-    aMapOfKeysByValues(aParseKey)->Append (anArg);
   }
 
-  // ---------------------------------------------
-  //  Change or print parameters, order plays role
-  // ---------------------------------------------
-
-  // Check arguments for validity
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfKeysByValues);
-  for (; aMapIt.More(); aMapIt.Next())
+  // complete input checks
+  if ((aCoord.Length() == 1 && theArgNb > 3) ||
+      (aCoord.Length() == 2 && theArgNb > 4) ||
+      (aCoord.Length() == 3 && theArgNb > 5))
   {
-    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;
-    }
+    std::cerr << "Error: wrong number of arguments! See usage:\n";
+    theDI.PrintHelp (theArgVec[0]);
+    return 1;
   }
 
-  Handle(TColStd_HSequenceOfAsciiString) aValues;
+  Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+  Standard_Integer aXYp[2] = {0, 0};
 
-  // Change view parameters in proper order
-  if (aMapOfKeysByValues.Find ("SCALE", aValues))
-  {
-    if (aValues->IsEmpty())
-    {
-      theDi << "Scale: " << anAISView->Scale() << "\n";
-    }
-    else
-    {
-      anAISView->SetScale (aValues->Value(1).RealValue());
-    }
-  }
-  if (aMapOfKeysByValues.Find ("SIZE", aValues))
+  // convert one-dimensional coordinate
+  if (aCoord.Length() == 1)
   {
-    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
+    switch (aMode)
     {
-      anAISView->SetSize (aValues->Value(1).RealValue());
+      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;
+      default:
+        std::cerr << "Error: wrong arguments! See usage:\n";
+        theDI.PrintHelp (theArgVec[0]);
+        return 1;
     }
   }
-  if (aMapOfKeysByValues.Find ("EYE", aValues))
+
+  // convert 2D coordinates from projection or view reference space
+  if (aCoord.Length() == 2)
   {
-    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
+    switch (aMode)
     {
-      anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      case Model :
+        aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
+        theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
+        return 0;
+
+      case View :
+        aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
+        theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
+        return 0;
+
+      case Window :
+        aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
+        theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
+        return 0;
+
+      case Grid :
+        aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
+        aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
+        theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
+        return 0;
+
+      case Ray :
+        aView->ConvertWithProj ((Standard_Integer) aCoord (1),
+                                (Standard_Integer) aCoord (2),
+                                aXYZ[0], aXYZ[1], aXYZ[2],
+                                aXYZ[3], aXYZ[4], aXYZ[5]);
+        theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
+        return 0;
+
+      default:
+        std::cerr << "Error: wrong arguments! See usage:\n";
+        theDI.PrintHelp (theArgVec[0]);
+        return 1;
     }
   }
-  if (aMapOfKeysByValues.Find ("AT", aValues))
+
+  // convert 3D coordinates from view reference space
+  else if (aCoord.Length() == 3)
   {
-    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
+    switch (aMode)
     {
-      anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      case Window :
+        aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
+        theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
+        return 0;
+
+      case Grid :
+        aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
+        theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
+        return 0;
+
+      default:
+        std::cerr << "Error: wrong arguments! See usage:\n";
+        theDI.PrintHelp (theArgVec[0]);
+        return 1;
     }
   }
-  if (aMapOfKeysByValues.Find ("PROJ", aValues))
-  {
-    if (aValues->IsEmpty())
-    {
-      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";
-    }
-    else
-    {
-      anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
-    }
-  }
-  if (aMapOfKeysByValues.Find ("UP", aValues))
-  {
-    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
-    {
-      anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
-    }
-  }
-  if (aMapOfKeysByValues.Find ("CENTER", aValues))
-  {
-    anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue());
-  }
 
   return 0;
 }
 
-//=======================================================================
-//function : VChangeSelected
-//purpose  : Adds the shape to selection or remove one from it
-//=======================================================================
-static Standard_Integer VChangeSelected (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+//==============================================================================
+//function : VFps
+//purpose  :
+//==============================================================================
+
+static int VFps (Draw_Interpretor& theDI,
+                 Standard_Integer  theArgNb,
+                 const char**      theArgVec)
 {
-  if(argc != 2)
+  // get the active view
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    di<<"Usage : " << argv[0] << " shape \n";
+    std::cerr << "No active view. Please call vinit.\n";
     return 1;
   }
-  //get AIS_Shape:
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
-  TCollection_AsciiString aName(argv[1]);
-  Handle(AIS_InteractiveObject) anAISObject;
 
-  if(!aMap.IsBound2(aName))
+  Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
+  if (aFramesNb <= 0)
   {
-    di<<"Use 'vdisplay' before";
+    std::cerr << "Incorrect arguments!\n";
     return 1;
   }
-  else
+
+  // the time is meaningless for first call
+  // due to async OpenGl rendering
+  aView->Redraw();
+
+  // redraw view in loop to estimate average values
+  OSD_Timer aTimer;
+  aTimer.Start();
+  for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
   {
-    anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
-    if(anAISObject.IsNull()){
-      di<<"No interactive object \n";
-      return 1;
-    }
+    aView->Redraw();
+  }
+  aTimer.Stop();
+  Standard_Real aCpu;
+  const Standard_Real aTime = aTimer.ElapsedTime();
+  aTimer.OSD_Chronometer::Show (aCpu);
 
-    if(aContext->HasOpenedContext())
-    {
-      aContext->AddOrRemoveSelected(anAISObject);
-    }
-    else
-    {
-      aContext->AddOrRemoveCurrentObject(anAISObject);
-    }
+  const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
+  const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
+
+  // return statistics
+  theDI << "FPS: " << aFpsAver << "\n"
+        << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
+
+  // compute additional statistics in ray-tracing mode
+  Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
+
+  if (aParams.Method == Graphic3d_RM_RAYTRACING)
+  {
+    Standard_Integer aSizeX;
+    Standard_Integer aSizeY;
+
+    aView->Window()->Size (aSizeX, aSizeY);
+
+    // 1 shadow ray and 1 secondary ray pew each bounce
+    const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
+
+    theDI << "MRays/sec (upper bound): " << aMRays << "\n";
   }
+
   return 0;
 }
 
-//=======================================================================
-//function : VZClipping
-//purpose  : Gets or sets ZClipping mode, width and depth
-//=======================================================================
-static Standard_Integer VZClipping (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+//==============================================================================
+//function : VGlDebug
+//purpose  :
+//==============================================================================
+
+static int VGlDebug (Draw_Interpretor& theDI,
+                     Standard_Integer  theArgNb,
+                     const char**      theArgVec)
 {
-  if(argc>4)
-  {
-    di << "Usage : " << argv[0] << " [mode] [depth  width]" << "\n"
-      <<"mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
-    return -1;
-  }
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  Handle(OpenGl_GraphicDriver) aDriver;
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (!aView.IsNull())
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
+    aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
   }
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  V3d_TypeOfZclipping aZClippingMode = V3d_OFF;
-  if(argc==1)
+  OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
+  OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
+
+  if (theArgNb < 2)
   {
-    TCollection_AsciiString aZClippingModeString;
-    Quantity_Length aDepth, aWidth;
-    aZClippingMode = aView->ZClipping(aDepth, aWidth);
-    switch (aZClippingMode)
+    TCollection_AsciiString aDebActive, aSyncActive;
+    if (aCaps == NULL)
     {
-    case V3d_OFF:
-      aZClippingModeString.Copy("OFF");
-      break;
-    case V3d_BACK:
-      aZClippingModeString.Copy("BACK");
-      break;
-    case V3d_FRONT:
-      aZClippingModeString.Copy("FRONT");
-      break;
-    case V3d_SLICE:
-      aZClippingModeString.Copy("SLICE");
-      break;
-    default:
-      aZClippingModeString.Copy(TCollection_AsciiString(aZClippingMode));
-      break;
+      aCaps = aDefCaps;
     }
-    di << "ZClippingMode = " << aZClippingModeString.ToCString() << "\n"
-      << "ZClipping depth = " << aDepth << "\n"
-      << "ZClipping width = " << aWidth << "\n";
+    else
+    {
+      Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
+                                                                  "GL_ARB_debug_output");
+      aDebActive = isActive ? " (active)" : " (inactive)";
+      if (isActive)
+      {
+        // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
+        aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
+      }
+    }
+
+    theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
+          << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
+          << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
+          << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
+    return 0;
   }
-  else
+
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    if(argc !=3)
+    Standard_CString        anArg     = theArgVec[anArgIter];
+    TCollection_AsciiString anArgCase (anArg);
+    anArgCase.LowerCase();
+    Standard_Boolean toEnableDebug = Standard_True;
+    if (anArgCase == "-glsl"
+     || anArgCase == "-glslwarn"
+     || anArgCase == "-glslwarns"
+     || anArgCase == "-glslwarnings")
     {
-      Standard_Integer aStatus = 0;
-      if ( strcmp (argv [1], "OFF") == 0 ) {
-        aStatus = 1;
-        aZClippingMode = V3d_OFF;
-      }
-      if ( strcmp (argv [1], "BACK") == 0 ) {
-        aStatus = 1;
-        aZClippingMode = V3d_BACK;
+      Standard_Boolean toShowWarns = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
+      {
+        --anArgIter;
       }
-      if ( strcmp (argv [1], "FRONT") == 0 ) {
-        aStatus = 1;
-        aZClippingMode = V3d_FRONT;
+      aDefCaps->glslWarnings = toShowWarns;
+      if (aCaps != NULL)
+      {
+        aCaps->glslWarnings = toShowWarns;
       }
-      if ( strcmp (argv [1], "SLICE") == 0 ) {
-        aStatus = 1;
-        aZClippingMode = V3d_SLICE;
+    }
+    else if (anArgCase == "-extra"
+          || anArgCase == "-extramsg"
+          || anArgCase == "-extramessages")
+    {
+      Standard_Boolean toShow = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
+      {
+        --anArgIter;
       }
-      if (aStatus != 1)
+      aDefCaps->suppressExtraMsg = !toShow;
+      if (aCaps != NULL)
       {
-        di << "Bad mode; Usage : " << argv[0] << " [mode] [depth width]" << "\n"
-          << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
-        return 1;
+        aCaps->suppressExtraMsg = !toShow;
       }
-      aView->SetZClippingType(aZClippingMode);
     }
-    if(argc >2)
+    else if (anArgCase == "-noextra"
+          || anArgCase == "-noextramsg"
+          || anArgCase == "-noextramessages")
     {
-      Quantity_Length aDepth = 0., aWidth = 1.;
-      if(argc == 3)
+      Standard_Boolean toSuppress = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
       {
-        aDepth = Draw::Atof (argv[1]);
-        aWidth = Draw::Atof (argv[2]);
+        --anArgIter;
       }
-      else if(argc == 4)
+      aDefCaps->suppressExtraMsg = toSuppress;
+      if (aCaps != NULL)
       {
-        aDepth = Draw::Atof (argv[2]);
-        aWidth = Draw::Atof (argv[3]);
+        aCaps->suppressExtraMsg = toSuppress;
       }
-
-      if(aDepth<0. || aDepth>1.)
+    }
+    else if (anArgCase == "-sync")
+    {
+      Standard_Boolean toSync = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
       {
-        di << "Bad depth; Usage : " << argv[0] << " [mode] [depth width]" << "\n"
-        << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
-        return 1;
+        --anArgIter;
       }
-      if(aWidth<0. || aWidth>1.)
+      aDefCaps->contextSyncDebug = toSync;
+      if (toSync)
       {
-        di << "Bad width; Usage : " << argv[0] << " [mode] [depth width]" << "\n"
-        << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
-        return 1;
+        aDefCaps->contextDebug = Standard_True;
       }
-
-      aView->SetZClippingDepth(aDepth);
-      aView->SetZClippingWidth(aWidth);
     }
-    aView->Redraw();
+    else if (anArgCase == "-debug")
+    {
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
+      {
+        --anArgIter;
+      }
+      aDefCaps->contextDebug = toEnableDebug;
+    }
+    else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
+          && (anArgIter + 1 == theArgNb))
+    {
+      // simple alias to turn on almost everything
+      aDefCaps->contextDebug     = toEnableDebug;
+      aDefCaps->contextSyncDebug = toEnableDebug;
+      aDefCaps->glslWarnings     = toEnableDebug;
+    }
+    else
+    {
+      std::cout << "Error: wrong syntax at '" << anArg << "'\n";
+      return 1;
+    }
   }
+
   return 0;
 }
 
-//=======================================================================
-//function : VNbSelected
-//purpose  : Returns number of selected objects
-//=======================================================================
-static Standard_Integer VNbSelected (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+//==============================================================================
+//function : VVbo
+//purpose  :
+//==============================================================================
+
+static int VVbo (Draw_Interpretor& theDI,
+                 Standard_Integer  theArgNb,
+                 const char**      theArgVec)
 {
-  if(argc != 1)
-  {
-    di << "Usage : " << argv[0] << "\n";
-    return 1;
-  }
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  const Standard_Boolean toSet    = (theArgNb > 1);
+  const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
+  if (toSet)
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
+    ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
   }
-  di << aContext->NbSelected() << "\n";
-  return 0;
-}
 
-//=======================================================================
-//function : VAntialiasing
-//purpose  : Switches altialiasing on or off
-//=======================================================================
-static Standard_Integer VAntialiasing (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
-{
-  if(argc > 2)
+  // get the context
+  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
+  if (aContextAIS.IsNull())
   {
-    di << "Usage : " << argv[0] << " [1|0]" << "\n";
+    if (!toSet)
+    {
+      std::cerr << "No active view!\n";
+    }
     return 1;
   }
-
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
+  if (!aDriver.IsNull())
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
+    if (!toSet)
+    {
+      theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
+    }
+    else
+    {
+      aDriver->ChangeOptions().vboDisable = toUseVbo;
+    }
   }
 
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-
-  if((argc == 2) && (atof(argv[1]) == 0))
-    aView->SetAntialiasingOff();
-  else
-    aView->SetAntialiasingOn();
-  aView->Update();
   return 0;
 }
 
-//=======================================================================
-//function : VPurgeDisplay
-//purpose  : Switches altialiasing on or off
-//=======================================================================
-static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+//==============================================================================
+//function : VCaps
+//purpose  :
+//==============================================================================
+
+static int VCaps (Draw_Interpretor& theDI,
+                  Standard_Integer  theArgNb,
+                  const char**      theArgVec)
 {
-  if (argc > 1)
-  {
-    di << "Usage : " << argv[0] << "\n";
-    return 1;
-  }
+  OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
+  Handle(OpenGl_GraphicDriver)   aDriver;
   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if (aContext.IsNull())
+  if (!aContext.IsNull())
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
+    aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
+    aCaps   = &aDriver->ChangeOptions();
   }
-  aContext->CloseAllContexts(Standard_False);
-  di << aContext->PurgeDisplay() << "\n";
-  return 0;
-}
 
-//=======================================================================
-//function : VSetViewSize
-//purpose  :
-//=======================================================================
-static Standard_Integer VSetViewSize (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
-{
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  if (theArgNb < 2)
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
-    return 1;
+    theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
+    theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
+    theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
+    theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
+    theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
+    theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
+    theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
+    return 0;
   }
-  if(argc != 2)
+
+  ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    di<<"Usage : " << argv[0] << " Size\n";
-    return 1;
+    Standard_CString        anArg     = theArgVec[anArgIter];
+    TCollection_AsciiString anArgCase (anArg);
+    anArgCase.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
+    {
+      continue;
+    }
+    else if (anArgCase == "-vsync"
+          || anArgCase == "-swapinterval")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->swapInterval = toEnable;
+    }
+    else if (anArgCase == "-ffp")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->ffpEnable = toEnable;
+    }
+    else if (anArgCase == "-vbo")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->vboDisable = !toEnable;
+    }
+    else if (anArgCase == "-sprite"
+          || anArgCase == "-sprites")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->pntSpritesDisable = !toEnable;
+    }
+    else if (anArgCase == "-softmode")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->contextNoAccel = toEnable;
+    }
+    else if (anArgCase == "-accel"
+          || anArgCase == "-acceleration")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->contextNoAccel = !toEnable;
+    }
+    else if (anArgCase == "-compat"
+          || anArgCase == "-compatprofile"
+          || anArgCase == "-compatible"
+          || anArgCase == "-compatibleprofile")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->contextCompatible = toEnable;
+      if (!aCaps->contextCompatible)
+      {
+        aCaps->ffpEnable = Standard_False;
+      }
+    }
+    else if (anArgCase == "-core"
+          || anArgCase == "-coreprofile")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->contextCompatible = !toEnable;
+      if (!aCaps->contextCompatible)
+      {
+        aCaps->ffpEnable = Standard_False;
+      }
+    }
+    else if (anArgCase == "-stereo"
+          || anArgCase == "-quadbuffer")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aCaps->contextStereo = toEnable;
+    }
+    else
+    {
+      std::cout << "Error: unknown argument '" << anArg << "'\n";
+      return 1;
+    }
   }
-  Standard_Real aSize = Draw::Atof (argv[1]);
-  if (aSize <= 0.)
+  if (aCaps != &ViewerTest_myDefaultCaps)
   {
-    di<<"Bad Size value  : " << aSize << "\n";
-    return 1;
+    ViewerTest_myDefaultCaps = *aCaps;
   }
-
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  aView->SetSize(aSize);
   return 0;
 }
 
-//=======================================================================
-//function : VMoveView
+//==============================================================================
+//function : VMemGpu
 //purpose  :
-//=======================================================================
-static Standard_Integer VMoveView (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+//==============================================================================
+
+static int VMemGpu (Draw_Interpretor& theDI,
+                    Standard_Integer  theArgNb,
+                    const char**      theArgVec)
 {
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  // get the context
+  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
+  if (aContextAIS.IsNull())
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
+    std::cerr << "No active view. Please call vinit.\n";
     return 1;
   }
-  if(argc < 4 || argc > 5)
+
+  Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
+  if (aDriver.IsNull())
   {
-    di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
+    std::cerr << "Graphic driver not available.\n";
     return 1;
   }
-  Standard_Real Dx = Draw::Atof (argv[1]);
-  Standard_Real Dy = Draw::Atof (argv[2]);
-  Standard_Real Dz = Draw::Atof (argv[3]);
-  Standard_Boolean aStart = Standard_True;
-  if (argc == 5)
-  {
-      aStart = (Draw::Atoi (argv[4]) > 0);
-  }
-
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  aView->Move(Dx,Dy,Dz,aStart);
-  return 0;
-}
 
-//=======================================================================
-//function : VTranslateView
-//purpose  :
-//=======================================================================
-static Standard_Integer VTranslateView (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
-{
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  Standard_Size aFreeBytes = 0;
+  TCollection_AsciiString anInfo;
+  if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
+    std::cerr << "Information not available.\n";
     return 1;
   }
-  if(argc < 4 || argc > 5)
+
+  if (theArgNb > 1 && *theArgVec[1] == 'f')
   {
-    di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
-    return 1;
+    theDI << Standard_Real (aFreeBytes);
   }
-  Standard_Real Dx = Draw::Atof (argv[1]);
-  Standard_Real Dy = Draw::Atof (argv[2]);
-  Standard_Real Dz = Draw::Atof (argv[3]);
-  Standard_Boolean aStart = Standard_True;
-  if (argc == 5)
+  else
   {
-      aStart = (Draw::Atoi (argv[4]) > 0);
+    theDI << anInfo;
   }
 
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  aView->Translate(Dx,Dy,Dz,aStart);
   return 0;
 }
 
-//=======================================================================
-//function : VTurnView
-//purpose  :
-//=======================================================================
-static Standard_Integer VTurnView (Draw_Interpretor& di,
-                                Standard_Integer argc,
-                                const char ** argv)
+// ==============================================================================
+// function : VReadPixel
+// purpose  :
+// ==============================================================================
+static int VReadPixel (Draw_Interpretor& theDI,
+                       Standard_Integer  theArgNb,
+                       const char**      theArgVec)
 {
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull()) {
-    di << "use 'vinit' command before " << argv[0] << "\n";
+  // get the active view
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cerr << "No active view. Please call vinit.\n";
     return 1;
   }
-  if(argc < 4 || argc > 5){
-    di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
+  else if (theArgNb < 3)
+  {
+    std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
     return 1;
   }
-  Standard_Real Ax = Draw::Atof (argv[1]);
-  Standard_Real Ay = Draw::Atof (argv[2]);
-  Standard_Real Az = Draw::Atof (argv[3]);
-  Standard_Boolean aStart = Standard_True;
-  if (argc == 5)
+
+  Image_PixMap::ImgFormat aFormat     = Image_PixMap::ImgRGBA;
+  Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
+
+  Standard_Integer aWidth, aHeight;
+  aView->Window()->Size (aWidth, aHeight);
+  const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
+  const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
+  if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
   {
-      aStart = (Draw::Atoi (argv[4]) > 0);
+    std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
+    return 1;
   }
 
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  aView->Turn(Ax,Ay,Az,aStart);
-  return 0;
-}
-
-//==============================================================================
-//function : VTextureEnv
-//purpose  : ENables or disables environment mapping
-//==============================================================================
-class OCC_TextureEnv : public Graphic3d_TextureEnv
-{
-public:
-  OCC_TextureEnv(const Standard_CString FileName);
-  OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
-  void SetTextureParameters(const Standard_Boolean theRepeatFlag,
-                            const Standard_Boolean theModulateFlag,
-                            const Graphic3d_TypeOfTextureFilter theFilter,
-                            const Standard_ShortReal theXScale,
-                            const Standard_ShortReal theYScale,
-                            const Standard_ShortReal theXShift,
-                            const Standard_ShortReal theYShift,
-                            const Standard_ShortReal theAngle);
-  DEFINE_STANDARD_RTTI(OCC_TextureEnv);
-};
-DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv);
-IMPLEMENT_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv);
-IMPLEMENT_STANDARD_RTTIEXT(OCC_TextureEnv, Graphic3d_TextureEnv);
-
-OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
-  : Graphic3d_TextureEnv(theFileName)
-{
-}
-
-OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
-  : Graphic3d_TextureEnv(theTexId)
-{
-}
-
-void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
-                                          const Standard_Boolean theModulateFlag,
-                                          const Graphic3d_TypeOfTextureFilter theFilter,
-                                          const Standard_ShortReal theXScale,
-                                          const Standard_ShortReal theYScale,
-                                          const Standard_ShortReal theXShift,
-                                          const Standard_ShortReal theYShift,
-                                          const Standard_ShortReal theAngle)
-{
-  myParams->SetRepeat     (theRepeatFlag);
-  myParams->SetModulate   (theModulateFlag);
-  myParams->SetFilter     (theFilter);
-  myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
-  myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
-  myParams->SetRotation   (theAngle);
-}
+  Standard_Boolean toShowName = Standard_False;
+  Standard_Boolean toShowHls  = Standard_False;
+  for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
+  {
+    const char* aParam = theArgVec[anIter];
+    if ( strcasecmp( aParam, "rgb" ) == 0 )
+    {
+      aFormat     = Image_PixMap::ImgRGB;
+      aBufferType = Graphic3d_BT_RGB;
+    }
+    else if ( strcasecmp( aParam, "hls" ) == 0 )
+    {
+      aFormat     = Image_PixMap::ImgRGB;
+      aBufferType = Graphic3d_BT_RGB;
+      toShowHls   = Standard_True;
+    }
+    else if ( strcasecmp( aParam, "rgbf" ) == 0 )
+    {
+      aFormat     = Image_PixMap::ImgRGBF;
+      aBufferType = Graphic3d_BT_RGB;
+    }
+    else if ( strcasecmp( aParam, "rgba" ) == 0 )
+    {
+      aFormat     = Image_PixMap::ImgRGBA;
+      aBufferType = Graphic3d_BT_RGBA;
+    }
+    else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
+    {
+      aFormat     = Image_PixMap::ImgRGBAF;
+      aBufferType = Graphic3d_BT_RGBA;
+    }
+    else if ( strcasecmp( aParam, "depth" ) == 0 )
+    {
+      aFormat     = Image_PixMap::ImgGrayF;
+      aBufferType = Graphic3d_BT_Depth;
+    }
+    else if ( strcasecmp( aParam, "name" ) == 0 )
+    {
+      toShowName = Standard_True;
+    }
+  }
 
-static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
-{
-  // get the active view
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  Image_PixMap anImage;
+  if (!anImage.InitTrash (aFormat, aWidth, aHeight))
   {
-    std::cerr << "No active view. Please call vinit.\n";
+    std::cerr << "Image allocation failed\n";
+    return 1;
+  }
+  else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
+  {
+    std::cerr << "Image dump failed\n";
     return 1;
   }
 
-  // Checking the input arguments
-  Standard_Boolean anEnableFlag = Standard_False;
-  Standard_Boolean isOk         = theArgNb >= 2;
-  if (isOk)
+  Quantity_Parameter anAlpha;
+  Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
+  if (toShowName)
   {
-    TCollection_AsciiString anEnableOpt(theArgVec[1]);
-    anEnableFlag = anEnableOpt.IsEqual("on");
-    isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
+    if (aBufferType == Graphic3d_BT_RGBA)
+    {
+      theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
+    }
+    else
+    {
+      theDI << Quantity_Color::StringName (aColor.Name());
+    }
   }
-  if (anEnableFlag)
+  else
   {
-    isOk = (theArgNb == 3 || theArgNb == 11);
-    if (isOk)
+    switch (aBufferType)
     {
-      TCollection_AsciiString aTextureOpt(theArgVec[2]);
-      isOk = (!aTextureOpt.IsIntegerValue() ||
-             (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
-
-      if (isOk && theArgNb == 11)
+      default:
+      case Graphic3d_BT_RGB:
       {
-        TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
-                                aModulateOpt(theArgVec[4]),
-                                aFilterOpt  (theArgVec[5]),
-                                aSScaleOpt  (theArgVec[6]),
-                                aTScaleOpt  (theArgVec[7]),
-                                aSTransOpt  (theArgVec[8]),
-                                aTTransOpt  (theArgVec[9]),
-                                anAngleOpt  (theArgVec[10]);
-        isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
-                (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
-                (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
-                aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
-                aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
-                anAngleOpt.IsRealValue());
+        if (toShowHls)
+        {
+          theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
+        }
+        else
+        {
+          theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
+        }
+        break;
+      }
+      case Graphic3d_BT_RGBA:
+      {
+        theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
+        break;
+      }
+      case Graphic3d_BT_Depth:
+      {
+        theDI << aColor.Red();
+        break;
       }
     }
   }
 
-  if (!isOk)
+  return 0;
+}
+
+//==============================================================================
+//function : VDiffImage
+//purpose  : The draw-command compares two images.
+//==============================================================================
+
+static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
+{
+  if (theArgNb < 6)
   {
-    std::cerr << "Usage :" << std::endl;
-    std::cerr << theArgVec[0] << " off" << std::endl;
-    std::cerr << theArgVec[0] << " on {index_of_std_texture(0..7)|texture_file_name} [{clamp|repeat} {decal|modulate} {nearest|bilinear|trilinear} scale_s scale_t translation_s translation_t rotation_degrees]" << std::endl;
+    theDI << "Not enough arguments.\n";
     return 1;
   }
 
-  if (anEnableFlag)
-  {
-    TCollection_AsciiString aTextureOpt(theArgVec[2]);
-    Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
-                                     new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
-                                     new OCC_TextureEnv(theArgVec[2]);
+  // image file names
+  const char* anImgPathRef = theArgVec[1];
+  const char* anImgPathNew = theArgVec[2];
 
-    if (theArgNb == 11)
-    {
-      TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
-      aTexEnv->SetTextureParameters(
-        aRepeatOpt.  IsEqual("repeat"),
-        aModulateOpt.IsEqual("modulate"),
-        aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
-                                          aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
-                                                                           Graphic3d_TOTF_TRILINEAR,
-        (Standard_ShortReal)Draw::Atof(theArgVec[6]),
-        (Standard_ShortReal)Draw::Atof(theArgVec[7]),
-        (Standard_ShortReal)Draw::Atof(theArgVec[8]),
-        (Standard_ShortReal)Draw::Atof(theArgVec[9]),
-        (Standard_ShortReal)Draw::Atof(theArgVec[10])
-        );
-    }
-    aView->SetTextureEnv(aTexEnv);
-    aView->SetSurfaceDetail(V3d_TEX_ENVIRONMENT);
+  // get string tolerance and check its validity
+  Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
+  if (aTolColor < 0.0)
+    aTolColor = 0.0;
+  if (aTolColor > 1.0)
+    aTolColor = 1.0;
+
+  Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
+  Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
+
+  // image file of difference
+  const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
+
+  // compare the images
+  Image_Diff aComparer;
+  if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
+  {
+    return 1;
   }
-  else // Disabling environment mapping
+
+  aComparer.SetColorTolerance (aTolColor);
+  aComparer.SetBorderFilterOn (isBorderFilterOn);
+  Standard_Integer aDiffColorsNb = aComparer.Compare();
+  theDI << aDiffColorsNb << "\n";
+
+  // save image of difference
+  if (aDiffColorsNb >0 && aDiffImagePath != NULL)
   {
-    aView->SetSurfaceDetail(V3d_TEX_NONE);
-    Handle(Graphic3d_TextureEnv) aTexture;
-    aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
+    aComparer.SaveDiffImage (aDiffImagePath);
   }
 
-  aView->Redraw();
   return 0;
 }
 
-//===============================================================================================
-//function : VClipPlane
-//purpose  :
-//===============================================================================================
-static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+//=======================================================================
+//function : VSelect
+//purpose  : Emulates different types of selection by mouse:
+//           1) single click selection
+//           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
+//           3) selection with polygon having corners at
+//           pixel positions (x1,y1),...,(xn,yn)
+//           4) any of these selections with shift button pressed
+//=======================================================================
+static Standard_Integer VSelect (Draw_Interpretor& di,
+                                 Standard_Integer argc,
+                                 const char ** argv)
 {
-  // use short-cut for created clip planes map of created (or "registered by name") clip planes
-  typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
-  static MapOfPlanes aRegPlanes;
-
-  if (theArgsNb < 2)
+  if(argc < 3)
   {
-    theDi << theArgVec[0] << ": command argument is required. Type help for more information.\n";
+    di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
     return 1;
   }
 
-  TCollection_AsciiString aCommand (theArgVec[1]);
-
-  // print maximum number of planes for current viewer
-  if (aCommand == "maxplanes")
+  Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
+  if(myAIScontext.IsNull())
   {
-    if (theArgsNb < 3)
-    {
-      theDi << theArgVec[0] << ": view name is required. Type help for more information.\n";
-      return 1;
-    }
-
-    TCollection_AsciiString aViewName (theArgVec[2]);
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
+  }
 
-    if (!ViewerTest_myViews.IsBound1 (aViewName))
+  const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
+  Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
+  TCollection_AsciiString anArg;
+  anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
+  anArg.LowerCase();
+  if (anArg == "-allowoverlap")
+  {
+    Standard_Boolean isValidated = isShiftSelection ? argc == 8
+      : argc == 7;
+    if (!isValidated)
     {
-      theDi << theArgVec[0] << ": view is not found.\n";
+      di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
       return 1;
     }
 
-    const Handle(V3d_View)& aView = ViewerTest_myViews.Find1 (aViewName);
-
-    theDi << theArgVec[0] << ": "
-                          << aView->Viewer()->Driver()->InquirePlaneLimit()
-                          << " plane slots provided by driver."
-                          << " Note that 2 more planes might be used (reserved for z-clipping).\n";
-
-    return 0;
+    Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
+    myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
+    aCoordsNb -= 2;
   }
 
-  // create / delete plane instance
-  if (aCommand == "create" || aCommand == "delete" || aCommand == "clone")
+  Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
+  aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
+  if(aCoordsNb == 2)
   {
-    if (theArgsNb < 3)
+    if(isShiftSelection)
+      aCurrentEventManager->ShiftSelect();
+    else
+      aCurrentEventManager->Select();
+  }
+  else if(aCoordsNb == 4)
+  {
+    if(isShiftSelection)
+      aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
+    else
+      aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
+  }
+  else
+  {
+    TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
+
+    for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
+      aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
+
+    if(isShiftSelection)
+      aCurrentEventManager->ShiftSelect(aPolyline);
+    else
+      aCurrentEventManager->Select(aPolyline);
+  }
+  return 0;
+}
+
+//=======================================================================
+//function : VMoveTo
+//purpose  : Emulates cursor movement to defined pixel position
+//=======================================================================
+static Standard_Integer VMoveTo (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
+{
+  if(argc != 3)
+  {
+    di << "Usage : " << argv[0] << " x y\n";
+    return 1;
+  }
+
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if(aContext.IsNull())
+  {
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
+  }
+  ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
+  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)
     {
-      theDi << theArgVec[0] << ": plane name is required. Type help for more information.\n";
-      return 1;
+      //
     }
 
-    Standard_Boolean toCreate = (aCommand == "create");
-    Standard_Boolean toClone  = (aCommand == "clone");
-    TCollection_AsciiString aPlane (theArgVec[2]);
+  protected:
 
-    if (toCreate)
+    //! Evaluate the command.
+    virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
     {
-      if (aRegPlanes.IsBound (aPlane))
-      {
-        theDi << theArgVec[0] << ": plane name is in use.\n";
-        return 1;
-      }
-
-      aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
+      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());
     }
-    else if (toClone) // toClone
+
+    //! 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)
     {
-      if (!aRegPlanes.IsBound (aPlane))
+      TCollection_AsciiString aCmd (theCmd);
+      aCmd.LowerCase();
+      const Standard_Integer aPos = aCmd.Search (theKey);
+      if (aPos == -1)
       {
-        theDi << theArgVec[0] << ": no such plane.\n";
-        return 1;
+        return;
       }
 
-      if (theArgsNb < 4)
+      TCollection_AsciiString aPart1, aPart2;
+      Standard_Integer aPart1To = aPos - 1;
+      if (aPart1To >= 1
+       && aPart1To <= theCmd.Length())
       {
-        theDi << theArgVec[0] << ": enter name for new plane. Type help for more information.\n";
-        return 1;
+        aPart1 = theCmd.SubString (1, aPart1To);
       }
 
-      TCollection_AsciiString aClone (theArgVec[3]);
-      if (aRegPlanes.IsBound (aClone))
+      Standard_Integer aPart2From = aPos + theKey.Length();
+      if (aPart2From >= 1
+       && aPart2From <= theCmd.Length())
       {
-        theDi << theArgVec[0] << ": plane name is in use.\n";
-        return 1;
+        aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
       }
 
-      const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
-
-      aRegPlanes.Bind (aClone, aClipPlane->Clone());
+      theCmd = aPart1 + theVal + aPart2;
     }
-    else// toDelete
-    {
-      if (!aRegPlanes.IsBound (aPlane))
-      {
-        theDi << theArgVec[0] << ": no such plane.\n";
-        return 1;
-      }
 
-      Handle(Graphic3d_ClipPlane) aClipPlane = aRegPlanes.Find (aPlane);
-      aRegPlanes.UnBind (aPlane);
+  protected:
 
-      ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
-      for (; anIObjIt.More(); anIObjIt.Next())
-      {
-        Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
-        aPrs->RemoveClipPlane(aClipPlane);
-      }
+    Draw_Interpretor*       myDrawInter;
+    TCollection_AsciiString myCommand;
 
-      NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
-      for (; aViewIt.More(); aViewIt.Next())
-      {
-        const Handle(V3d_View)& aView = aViewIt.Key2();
-        aView->RemoveClipPlane(aClipPlane);
-      }
+  };
 
-      ViewerTest::RedrawAllViews();
+  //! 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);
     }
-
-    return 0;
+    else
+    {
+      ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
+      ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
+    }
+    theAnimation = theAnimationNew;
   }
 
-  // set / unset plane command
-  if (aCommand == "set" || aCommand == "unset")
+  //! Parse the point.
+  static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
   {
-    if (theArgsNb < 4)
+    const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
+    if (!anXYZ[0].IsRealValue()
+     || !anXYZ[1].IsRealValue()
+     || !anXYZ[2].IsRealValue())
     {
-      theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-      return 1;
+      return Standard_False;
     }
 
-    Standard_Boolean toSet = (aCommand == "set");
-    TCollection_AsciiString aPlane (theArgVec [2]);
-    if (!aRegPlanes.IsBound (aPlane))
+    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())
     {
-      theDi << theArgVec[0] << ": no such plane.\n";
-      return 1;
+      return Standard_False;
     }
 
-    const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
+    theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
+    return Standard_True;
+  }
 
-    TCollection_AsciiString aTarget (theArgVec [3]);
-    if (aTarget != "object" && aTarget != "view")
-    {
-      theDi << theArgVec[0] << ": invalid target.\n";
-      return 1;
-    }
+}
 
-    if (aTarget == "object" || aTarget == "view")
-    {
-      if (theArgsNb < 5)
-      {
-        theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-        return 1;
-      }
+//=================================================================================================
+//function : VViewParams
+//purpose  : Gets or sets AIS View characteristics
+//=================================================================================================
+static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << theArgVec[0] << ": please initialize or activate view.\n";
+    return 1;
+  }
 
-      Standard_Boolean isObject = (aTarget == "object");
+  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;
+  Quantity_Factor  aViewScale = aView->Scale();
+  Quantity_Length  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
+    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;
+  }
 
-      for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
-      {
-        TCollection_AsciiString anEntityName (theArgVec[anIt]);
-        if (isObject) // to object
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
+    {
+      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())
         {
-          if (!GetMapOfAIS().IsBound2 (anEntityName))
+          ++anArgIter;
+          if (anArg == "-scale")
           {
-            theDi << theArgVec[0] << ": can not find IO with name " << anEntityName << ".\n";
-            continue;
+            toSetScale = Standard_True;
+            aViewScale = aValueArg.RealValue();
           }
-
-          Handle(AIS_InteractiveObject) aIObj =
-            Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
-
-          if (toSet)
-            aIObj->AddClipPlane (aClipPlane);
-          else
-            aIObj->RemoveClipPlane (aClipPlane);
+          else if (anArg == "-size")
+          {
+            toSetSize = Standard_True;
+            aViewSize = aValueArg.RealValue();
+          }
+          continue;
         }
-        else // to view
+      }
+      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))
         {
-          if (!ViewerTest_myViews.IsBound1 (anEntityName))
+          anArgIter += 3;
+          if (anArg == "-eye")
           {
-            theDi << theArgVec[0] << ": can not find View with name " << anEntityName << ".\n";
-            continue;
+            toSetEye = Standard_True;
+            aViewEye = anXYZ;
           }
-
-          Handle(V3d_View) aView = ViewerTest_myViews.Find1(anEntityName);
-          if (toSet)
-            aView->AddClipPlane (aClipPlane);
-          else
-            aView->RemoveClipPlane (aClipPlane);
+          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;
         }
       }
 
-      ViewerTest::RedrawAllViews();
+      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")
+    {
+      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;
     }
+  }
 
-    return 0;
+  // 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 plane command
-  if (aCommand == "change")
+  return 0;
+}
+
+//==============================================================================
+//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)
   {
-    if (theArgsNb < 4)
+    for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
+         anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
     {
-      theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-      return 1;
+      theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
     }
+    return 0;
+  }
+  if (aCtx.IsNull())
+  {
+    std::cout << "Error: no active view\n";
+    return 1;
+  }
+
+  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);
+  }
 
-    TCollection_AsciiString aPlane (theArgVec [2]);
-    if (!aRegPlanes.IsBound (aPlane))
+  // 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)
     {
-      theDi << theArgVec[0] << ": no such plane.\n";
-      return 1;
-    }
+      if (aSplitPos == aNameArg.Length())
+      {
+        std::cout << "Syntax error: animation name is not defined.\n";
+        return 1;
+      }
 
-    const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
+      aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
+      aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
 
-    TCollection_AsciiString aChangeArg (theArgVec [3]);
-    if (aChangeArg != "on" && aChangeArg != "off" && aChangeArg != "capping" && aChangeArg != "equation")
+      aSplitPos = aNameArg.Search (aNameSplitter);
+    }
+    else
     {
-      theDi << theArgVec[0] << ": invalid arguments. Type help for more information.\n";
-      return 1;
+      aNameParent = aNameArg;
+      aNameArg.Clear();
     }
 
-    if (aChangeArg == "on" || aChangeArg == "off") // on / off
+    if (anAnimation.IsNull())
     {
-      aClipPlane->SetOn (aChangeArg == "on");
+      if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
+      {
+        anAnimation = new AIS_Animation (aNameParent);
+        ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
+      }
+      aRootAnimation = anAnimation;
     }
-    else if (aChangeArg == "equation") // change equation
+    else
     {
-      if (theArgsNb < 8)
+      aParentAnimation = anAnimation;
+      anAnimation = aParentAnimation->Find (aNameParent);
+      if (anAnimation.IsNull())
       {
-        theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-        return 1;
+        anAnimation = new AIS_Animation (aNameParent);
+        aParentAnimation->Add (anAnimation);
       }
+    }
+  }
 
-      Standard_Real aCoeffA = Draw::Atof (theArgVec [4]);
-      Standard_Real aCoeffB = Draw::Atof (theArgVec [5]);
-      Standard_Real aCoeffC = Draw::Atof (theArgVec [6]);
-      Standard_Real aCoeffD = Draw::Atof (theArgVec [7]);
-      aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
+  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 (aChangeArg == "capping") // change capping aspects
+    else if (anArg == "-remove"
+          || anArg == "-del"
+          || anArg == "-delete")
     {
-      if (theArgsNb < 5)
+      if (!aParentAnimation.IsNull())
       {
-        theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-        return 1;
+        ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
       }
-
-      TCollection_AsciiString aCappingArg (theArgVec [4]);
-      if (aCappingArg != "on" && aCappingArg != "off" &&
-          aCappingArg != "color" && aCappingArg != "texname" &&
-          aCappingArg != "texscale" && aCappingArg != "texorigin" &&
-          aCappingArg != "texrotate" && aCappingArg != "hatch")
+      else
       {
-        theDi << theArgVec[0] << ": invalid arguments. Type help for more information.\n";
-        return 1;
+        aParentAnimation->Remove (anAnimation);
       }
-
-      if (aCappingArg == "on" || aCappingArg == "off") // on / off capping
-      {
-        aClipPlane->SetCapping (aCappingArg == "on");
-      }
-      else if (aCappingArg == "color") // color aspect for capping
+    }
+    // playback options
+    else if (anArg == "-play")
+    {
+      toPlay = Standard_True;
+      if (++anArgIter < theArgNb)
       {
-        if (theArgsNb < 8)
+        if (*theArgVec[anArgIter] == '-')
         {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
+          --anArgIter;
+          continue;
         }
+        aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
 
-        Standard_Real aRed = Draw::Atof (theArgVec [5]);
-        Standard_Real aGrn = Draw::Atof (theArgVec [6]);
-        Standard_Real aBlu = Draw::Atof (theArgVec [7]);
-
-        Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
-        Quantity_Color aColor (aRed, aGrn, aBlu, Quantity_TOC_RGB);
-        aMat.SetAmbientColor (aColor);
-        aMat.SetDiffuseColor (aColor);
-        aClipPlane->SetCappingMaterial (aMat);
+        if (++anArgIter < theArgNb)
+        {
+          if (*theArgVec[anArgIter] == '-')
+          {
+            --anArgIter;
+            continue;
+          }
+          aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
+        }
       }
-      else if (aCappingArg == "texname") // texture name
+    }
+    else if (anArg == "-resume")
+    {
+      toPlay = Standard_True;
+      aPlayStartTime = anAnimation->ElapsedTime();
+      if (++anArgIter < theArgNb)
       {
-        if (theArgsNb < 6)
+        if (*theArgVec[anArgIter] == '-')
         {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
+          --anArgIter;
+          continue;
         }
 
-        TCollection_AsciiString aTextureName (theArgVec [5]);
+        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;
+      }
 
-        Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
-        if (!aTexture->IsDone ())
-        {
-          aClipPlane->SetCappingTexture (NULL);
-        }
-        else
-        {
-          aTexture->EnableModulate();
-          aTexture->EnableRepeat();
-          aClipPlane->SetCappingTexture (aTexture);
-        }
+      TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
+      Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
+      if (aSplitIndex == 0)
+      {
+        aFpsNum = aFpsArg.IntegerValue();
       }
-      else if (aCappingArg == "texscale") // texture scale
+      else
       {
-        if (aClipPlane->CappingTexture().IsNull())
+        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)
         {
-          theDi << theArgVec[0] << ": no texture is set.\n";
+          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;
+      }
 
-        if (theArgsNb < 7)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\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;
+      }
 
-        Standard_ShortReal aSx = (Standard_ShortReal)atof (theArgVec [5]);
-        Standard_ShortReal aSy = (Standard_ShortReal)atof (theArgVec [6]);
+      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;
+      }
 
-        aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
+      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;
       }
-      else if (aCappingArg == "texorigin") // texture origin
+
+      TCollection_AsciiString anObjName (theArgVec[anArgIter]);
+      const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
+      if (!aMapOfAIS.IsBound2 (anObjName))
       {
-        if (aClipPlane->CappingTexture().IsNull())
-        {
-          theDi << theArgVec[0] << ": no texture is set.\n";
-          return 1;
-        }
+        std::cout << "Syntax error: wrong object name at " << anArg << "\n";
+        return 1;
+      }
 
-        if (theArgsNb < 7)
+      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"))
         {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
+          isTrsfSet = Standard_True;
+          if (aTrsfArgIter + 4 >= theArgNb
+          || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aTrsfArgIter += 4;
         }
-
-        Standard_ShortReal aTx = (Standard_ShortReal)atof (theArgVec [5]);
-        Standard_ShortReal aTy = (Standard_ShortReal)atof (theArgVec [6]);
-
-        aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
-      }
-      else if (aCappingArg == "texrotate") // texture rotation
-      {
-        if (aClipPlane->CappingTexture().IsNull())
+        else if (aTrsfArg.StartsWith ("-location")
+              || aTrsfArg.StartsWith ("-loc"))
         {
-          theDi << theArgVec[0] << ": no texture is set.\n";
-          return 1;
+          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;
+          }
 
-        if (theArgsNb < 6)
+          const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
+          if (!aScaleStr.IsRealValue())
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aScales[anIndex] = aScaleStr.RealValue();
+        }
+        else
         {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
+          anArgIter = aTrsfArgIter - 1;
+          break;
         }
+      }
+      if (!isTrsfSet)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+      else if (aTrsfArgIter >= theArgNb)
+      {
+        anArgIter = theArgNb;
+      }
 
-        Standard_ShortReal aRot = (Standard_ShortReal)atof (theArgVec[5]);
+      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]);
 
-        aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
+      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);
       }
-      else if (aCappingArg == "hatch") // hatch style
+
+      Handle(Graphic3d_Camera) aCams[2] =
       {
-        if (theArgsNb < 6)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
+        new Graphic3d_Camera (aCamAnimation->View()->Camera()),
+        new Graphic3d_Camera (aCamAnimation->View()->Camera())
+      };
 
-        TCollection_AsciiString aHatchStr (theArgVec [5]);
-        if (aHatchStr == "on")
+      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"))
         {
-          aClipPlane->SetCappingHatchOn();
+          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 (aHatchStr == "off")
+        else if (aViewArg.StartsWith ("-eye")
+              || aViewArg.StartsWith ("-center")
+              || aViewArg.StartsWith ("-at")
+              || aViewArg.StartsWith ("-up"))
         {
-          aClipPlane->SetCappingHatchOff();
+          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
         {
-          aClipPlane->SetCappingHatch ((Aspect_HatchStyle)atoi (theArgVec[5]));
+          anArgIter = aViewArgIter - 1;
+          break;
         }
       }
-    }
-
-    ViewerTest::RedrawAllViews();
-
-    return 0;
-  }
-
-  theDi << theArgVec[0] << ": invalid command. Type help for more information.\n";
-  return 1;
-}
+      if (!isTrsfSet)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+      else if (aViewArgIter >= theArgNb)
+      {
+        anArgIter = theArgNb;
+      }
 
-//===============================================================================================
-//function : VSetTextureMode
-//purpose  :
-//===============================================================================================
-static int VSetTextureMode (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
-{
-  if (theArgsNb < 3)
-  {
-    theDi << theArgVec[0] << ": insufficient command arguments. Type help for more information.\n";
-    return 1;
+      aCamAnimation->SetCameraStart(aCams[0]);
+      aCamAnimation->SetCameraEnd  (aCams[1]);
+    }
+    else
+    {
+      std::cout << "Syntax error at " << anArg << ".\n";
+      return 1;
+    }
   }
 
-  TCollection_AsciiString aViewName (theArgVec[1]);
-  if (!ViewerTest_myViews.IsBound1 (aViewName))
+  if (!toPlay)
   {
-    theDi << theArgVec[0] << ": view is not found.\n";
-    return 1;
+    return 0;
   }
 
-  const Handle(V3d_View)& aView = ViewerTest_myViews.Find1 (aViewName);
-  switch (atoi (theArgVec[2]))
+  // 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)
   {
-    case 0: aView->SetSurfaceDetail (V3d_TEX_NONE); break;
-    case 1: aView->SetSurfaceDetail (V3d_TEX_ENVIRONMENT); break;
-    case 2: aView->SetSurfaceDetail (V3d_TEX_ALL); break;
-    default:
-      theDi << theArgVec[0] << ": invalid mode.\n";
-      return 1;
+    aView->Camera()->Copy (aCameraBack);
   }
 
-  aView->Redraw();
-  return 0;
-}
-
-//===============================================================================================
-//function : VZRange
-//purpose  :
-//===============================================================================================
-static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
-{
-  const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
-
-  if (aCurrentView.IsNull())
+  const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
+  if (aFpsNum <= 0)
   {
-    std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
-    return 1;
-  }
+    while (!anAnimation->IsStopped())
+    {
+      aCameraBack->Copy (aView->Camera());
+      const Standard_Real aPts = anAnimation->UpdateTimer();
+      if (isFreeCamera)
+      {
+        aView->Camera()->Copy (aCameraBack);
+      }
 
-  Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
+      if (aPts >= anUpperPts)
+      {
+        anAnimation->Pause();
+        break;
+      }
 
-  if (theArgsNb < 2)
-  {
-    theDi << "ZNear: " << aCamera->ZNear() << "\n";
-    theDi << "ZFar: " << aCamera->ZFar() << "\n";
-    return 0;
-  }
+      if (aView->IsInvalidated())
+      {
+        aView->Redraw();
+      }
+      else
+      {
+        aView->RedrawImmediate();
+      }
 
-  if (theArgsNb == 3)
-  {
-    Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
-    Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
+      if (!isLockLoop)
+      {
+        // handle user events
+        theDI.Eval ("after 1 set waiter 1");
+        theDI.Eval ("vwait waiter");
+      }
+      if (!TheIsAnimating)
+      {
+        anAnimation->Pause();
+        theDI << aPts;
+        break;
+      }
+    }
 
-    if (aNewZNear >= aNewZFar)
+    if (aView->IsInvalidated())
     {
-      std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
-      return 1;
+      aView->Redraw();
     }
-
-    if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
+    else
     {
-      std::cout << theArgVec[0] << ": invalid arguments: ";
-      std::cout << "znear, zfar should be positive for perspective camera.\n";
-      return 1;
+      aView->RedrawImmediate();
     }
-
-    aCamera->SetZRange (aNewZNear, aNewZFar);
   }
   else
   {
-    std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
-    return 1;
-  }
+    OSD_Timer aPerfTimer;
+    aPerfTimer.Start();
 
-  aCurrentView->Redraw();
+    // Manage frame-rated animation here
+    Standard_Real aPts = aPlayStartTime;
+    int64_t aNbFrames = 0;
+    for (; aPts <= anUpperPts;)
+    {
+      const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
+      aPts = aPlayStartTime + aRecPts;
+      ++aNbFrames;
+      if (!anAnimation->Update (aPts))
+      {
+        break;
+      }
 
-  return 0;
-}
+      aView->Redraw();
+    }
 
-//===============================================================================================
-//function : VAutoZFit
-//purpose  :
-//===============================================================================================
-static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
-{
-  const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
+    aPerfTimer.Stop();
+    anAnimation->Stop();
+    const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
+    theDI << "Average FPS: " << aRecFps << "\n"
+          << "Nb. Frames: "  << Standard_Real(aNbFrames);
 
-  if (aCurrentView.IsNull())
-  {
-    std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
-    return 1;
+    aView->Redraw();
   }
 
-  Standard_Real aScale = aCurrentView->View()->AutoZFitScaleFactor();
+  aView->SetImmediateUpdate (wasImmediateUpdate);
+  TheIsAnimating = Standard_False;
+  return 0;
+}
+
 
-  if (theArgsNb > 3)
+//=======================================================================
+//function : VChangeSelected
+//purpose  : Adds the shape to selection or remove one from it
+//=======================================================================
+static Standard_Integer VChangeSelected (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
+{
+  if(argc != 2)
   {
-    std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
+    di<<"Usage : " << argv[0] << " shape \n";
     return 1;
   }
-
-  if (theArgsNb < 2)
+  //get AIS_Shape:
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
+  TCollection_AsciiString aName(argv[1]);
+  Handle(AIS_InteractiveObject) anAISObject;
+
+  if(!aMap.IsBound2(aName))
   {
-    theDi << "Auto z-fit mode: " << "\n"
-          << "On: " << (aCurrentView->View()->AutoZFitMode() ? "enabled" : "disabled") << "\n"
-          << "Scale: " << aScale << "\n";
-    return 0;
+    di<<"Use 'vdisplay' before";
+    return 1;
   }
+  else
+  {
+    anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
+    if(anAISObject.IsNull()){
+      di<<"No interactive object \n";
+      return 1;
+    }
 
-  Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
+    aContext->AddOrRemoveSelected(anAISObject);
+  }
+  return 0;
+}
 
-  if (theArgsNb >= 3)
+//=======================================================================
+//function : VNbSelected
+//purpose  : Returns number of selected objects
+//=======================================================================
+static Standard_Integer VNbSelected (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
+{
+  if(argc != 1)
   {
-    aScale = Draw::Atoi (theArgVec[2]);
+    di << "Usage : " << argv[0] << "\n";
+    return 1;
+  }
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if(aContext.IsNull())
+  {
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
   }
+  di << aContext->NbSelected() << "\n";
+  return 0;
+}
 
-  aCurrentView->View()->SetAutoZFitMode (isOn, aScale);
-  aCurrentView->View()->AutoZFit();
-  aCurrentView->Redraw();
+//=======================================================================
+//function : VPurgeDisplay
+//purpose  : Switches altialiasing on or off
+//=======================================================================
+static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
+{
+  if (argc > 1)
+  {
+    di << "Usage : " << argv[0] << "\n";
+    return 1;
+  }
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
+  {
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
+  }
 
+  di << aContext->PurgeDisplay() << "\n";
   return 0;
 }
 
-//! Auxiliary function to print projection type
-inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
+//=======================================================================
+//function : VSetViewSize
+//purpose  :
+//=======================================================================
+static Standard_Integer VSetViewSize (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
 {
-  switch (theProjType)
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if(aContext.IsNull())
   {
-    case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
-    case Graphic3d_Camera::Projection_Perspective:  return "perspective";
-    case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
-    case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
-    case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
   }
-  return "UNKNOWN";
+  if(argc != 2)
+  {
+    di<<"Usage : " << argv[0] << " Size\n";
+    return 1;
+  }
+  Standard_Real aSize = Draw::Atof (argv[1]);
+  if (aSize <= 0.)
+  {
+    di<<"Bad Size value  : " << aSize << "\n";
+    return 1;
+  }
+
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  aView->SetSize(aSize);
+  return 0;
 }
 
-//===============================================================================================
-//function : VCamera
+//=======================================================================
+//function : VMoveView
 //purpose  :
-//===============================================================================================
-static int VCamera (Draw_Interpretor& theDI,
-                    Standard_Integer  theArgsNb,
-                    const char**      theArgVec)
+//=======================================================================
+static Standard_Integer VMoveView (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
 {
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if(aContext.IsNull())
   {
-    std::cout << "Error: no active view.\n";
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
+  }
+  if(argc < 4 || argc > 5)
+  {
+    di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
     return 1;
   }
+  Standard_Real Dx = Draw::Atof (argv[1]);
+  Standard_Real Dy = Draw::Atof (argv[2]);
+  Standard_Real Dz = Draw::Atof (argv[3]);
+  Standard_Boolean aStart = Standard_True;
+  if (argc == 5)
+  {
+      aStart = (Draw::Atoi (argv[4]) > 0);
+  }
 
-  Handle(Graphic3d_Camera) aCamera = aView->Camera();
-  if (theArgsNb < 2)
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  aView->Move(Dx,Dy,Dz,aStart);
+  return 0;
+}
+
+//=======================================================================
+//function : VTranslateView
+//purpose  :
+//=======================================================================
+static Standard_Integer VTranslateView (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
+{
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if(aContext.IsNull())
   {
-    theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
-    theDI << "FOVy:       " << aCamera->FOVy() << "\n";
-    theDI << "Distance:   " << aCamera->Distance() << "\n";
-    theDI << "IOD:        " << aCamera->IOD() << "\n";
-    theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
-    theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
-    theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
-    return 0;
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
+  }
+  if(argc < 4 || argc > 5)
+  {
+    di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
+    return 1;
+  }
+  Standard_Real Dx = Draw::Atof (argv[1]);
+  Standard_Real Dy = Draw::Atof (argv[2]);
+  Standard_Real Dz = Draw::Atof (argv[3]);
+  Standard_Boolean aStart = Standard_True;
+  if (argc == 5)
+  {
+      aStart = (Draw::Atoi (argv[4]) > 0);
   }
 
-  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  aView->Translate(Dx,Dy,Dz,aStart);
+  return 0;
+}
+
+//=======================================================================
+//function : VTurnView
+//purpose  :
+//=======================================================================
+static Standard_Integer VTurnView (Draw_Interpretor& di,
+                                Standard_Integer argc,
+                                const char ** argv)
+{
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if(aContext.IsNull()) {
+    di << "use 'vinit' command before " << argv[0] << "\n";
+    return 1;
+  }
+  if(argc < 4 || argc > 5){
+    di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
+    return 1;
+  }
+  Standard_Real Ax = Draw::Atof (argv[1]);
+  Standard_Real Ay = Draw::Atof (argv[2]);
+  Standard_Real Az = Draw::Atof (argv[3]);
+  Standard_Boolean aStart = Standard_True;
+  if (argc == 5)
   {
-    Standard_CString        anArg = theArgVec[anArgIter];
-    TCollection_AsciiString anArgCase (anArg);
-    anArgCase.LowerCase();
-    if (anArgCase == "-proj"
-     || anArgCase == "-projection"
-     || anArgCase == "-projtype"
-     || anArgCase == "-projectiontype")
-    {
-      theDI << projTypeName (aCamera->ProjectionType()) << " ";
-    }
-    else if (anArgCase == "-ortho"
-          || anArgCase == "-orthographic")
-    {
-      aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
-    }
-    else if (anArgCase == "-persp"
-          || anArgCase == "-perspective"
-          || anArgCase == "-perspmono"
-          || anArgCase == "-perspectivemono"
-          || anArgCase == "-mono")
-    {
-      aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
-    }
-    else if (anArgCase == "-stereo"
-          || anArgCase == "-stereoscopic"
-          || anArgCase == "-perspstereo"
-          || anArgCase == "-perspectivestereo")
-    {
-      aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
-    }
-    else if (anArgCase == "-left"
-          || anArgCase == "-lefteye"
-          || anArgCase == "-monoleft"
-          || anArgCase == "-monolefteye"
-          || anArgCase == "-perpsleft"
-          || anArgCase == "-perpslefteye")
-    {
-      aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
-    }
-    else if (anArgCase == "-right"
-          || anArgCase == "-righteye"
-          || anArgCase == "-monoright"
-          || anArgCase == "-monorighteye"
-          || anArgCase == "-perpsright")
-    {
-      aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
-    }
-    else if (anArgCase == "-dist"
-          || anArgCase == "-distance")
-    {
-      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
-      if (anArgValue != NULL
-      && *anArgValue != '-')
-      {
-        ++anArgIter;
-        aCamera->SetDistance (Draw::Atof (anArgValue));
-        continue;
+      aStart = (Draw::Atoi (argv[4]) > 0);
+  }
+
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  aView->Turn(Ax,Ay,Az,aStart);
+  return 0;
+}
+
+//==============================================================================
+//function : VTextureEnv
+//purpose  : ENables or disables environment mapping
+//==============================================================================
+class OCC_TextureEnv : public Graphic3d_TextureEnv
+{
+public:
+  OCC_TextureEnv(const Standard_CString FileName);
+  OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
+  void SetTextureParameters(const Standard_Boolean theRepeatFlag,
+                            const Standard_Boolean theModulateFlag,
+                            const Graphic3d_TypeOfTextureFilter theFilter,
+                            const Standard_ShortReal theXScale,
+                            const Standard_ShortReal theYScale,
+                            const Standard_ShortReal theXShift,
+                            const Standard_ShortReal theYShift,
+                            const Standard_ShortReal theAngle);
+  DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
+};
+DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
+
+OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
+  : Graphic3d_TextureEnv(theFileName)
+{
+}
+
+OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
+  : Graphic3d_TextureEnv(theTexId)
+{
+}
+
+void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
+                                          const Standard_Boolean theModulateFlag,
+                                          const Graphic3d_TypeOfTextureFilter theFilter,
+                                          const Standard_ShortReal theXScale,
+                                          const Standard_ShortReal theYScale,
+                                          const Standard_ShortReal theXShift,
+                                          const Standard_ShortReal theYShift,
+                                          const Standard_ShortReal theAngle)
+{
+  myParams->SetRepeat     (theRepeatFlag);
+  myParams->SetModulate   (theModulateFlag);
+  myParams->SetFilter     (theFilter);
+  myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
+  myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
+  myParams->SetRotation   (theAngle);
+}
+
+static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
+{
+  // get the active view
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cerr << "No active view. Please call vinit.\n";
+    return 1;
+  }
+
+  // Checking the input arguments
+  Standard_Boolean anEnableFlag = Standard_False;
+  Standard_Boolean isOk         = theArgNb >= 2;
+  if (isOk)
+  {
+    TCollection_AsciiString anEnableOpt(theArgVec[1]);
+    anEnableFlag = anEnableOpt.IsEqual("on");
+    isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
+  }
+  if (anEnableFlag)
+  {
+    isOk = (theArgNb == 3 || theArgNb == 11);
+    if (isOk)
+    {
+      TCollection_AsciiString aTextureOpt(theArgVec[2]);
+      isOk = (!aTextureOpt.IsIntegerValue() ||
+             (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
+
+      if (isOk && theArgNb == 11)
+      {
+        TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
+                                aModulateOpt(theArgVec[4]),
+                                aFilterOpt  (theArgVec[5]),
+                                aSScaleOpt  (theArgVec[6]),
+                                aTScaleOpt  (theArgVec[7]),
+                                aSTransOpt  (theArgVec[8]),
+                                aTTransOpt  (theArgVec[9]),
+                                anAngleOpt  (theArgVec[10]);
+        isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
+                (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
+                (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
+                aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
+                aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
+                anAngleOpt.IsRealValue());
+      }
+    }
+  }
+
+  if (!isOk)
+  {
+    std::cerr << "Usage :" << std::endl;
+    std::cerr << theArgVec[0] << " off" << std::endl;
+    std::cerr << theArgVec[0] << " on {index_of_std_texture(0..7)|texture_file_name} [{clamp|repeat} {decal|modulate} {nearest|bilinear|trilinear} scale_s scale_t translation_s translation_t rotation_degrees]" << std::endl;
+    return 1;
+  }
+
+  if (anEnableFlag)
+  {
+    TCollection_AsciiString aTextureOpt(theArgVec[2]);
+    Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
+                                     new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
+                                     new OCC_TextureEnv(theArgVec[2]);
+
+    if (theArgNb == 11)
+    {
+      TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
+      aTexEnv->SetTextureParameters(
+        aRepeatOpt.  IsEqual("repeat"),
+        aModulateOpt.IsEqual("modulate"),
+        aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
+                                          aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
+                                                                           Graphic3d_TOTF_TRILINEAR,
+        (Standard_ShortReal)Draw::Atof(theArgVec[6]),
+        (Standard_ShortReal)Draw::Atof(theArgVec[7]),
+        (Standard_ShortReal)Draw::Atof(theArgVec[8]),
+        (Standard_ShortReal)Draw::Atof(theArgVec[9]),
+        (Standard_ShortReal)Draw::Atof(theArgVec[10])
+        );
+    }
+    aView->SetTextureEnv(aTexEnv);
+  }
+  else // Disabling environment mapping
+  {
+    Handle(Graphic3d_TextureEnv) aTexture;
+    aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
+  }
+
+  aView->Redraw();
+  return 0;
+}
+
+namespace
+{
+  typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
+
+  //! Remove registered clipping plane from all views and objects.
+  static void removePlane (MapOfPlanes& theRegPlanes,
+                           const TCollection_AsciiString& theName)
+  {
+    Handle(Graphic3d_ClipPlane) aClipPlane;
+    if (!theRegPlanes.Find (theName, aClipPlane))
+    {
+      std::cout << "Warning: no such plane.\n";
+      return;
+    }
+
+    theRegPlanes.UnBind (theName);
+    for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
+         anIObjIt.More(); anIObjIt.Next())
+    {
+      Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
+      aPrs->RemoveClipPlane (aClipPlane);
+    }
+
+    for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
+         aViewIt.More(); aViewIt.Next())
+    {
+      const Handle(V3d_View)& aView = aViewIt.Key2();
+      aView->RemoveClipPlane(aClipPlane);
+    }
+
+    ViewerTest::RedrawAllViews();
+  }
+}
+
+//===============================================================================================
+//function : VClipPlane
+//purpose  :
+//===============================================================================================
+static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  // use short-cut for created clip planes map of created (or "registered by name") clip planes
+  static MapOfPlanes aRegPlanes;
+
+  if (theArgsNb < 2)
+  {
+    for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
+    {
+      theDi << aPlaneIter.Key() << " ";
+    }
+    return 0;
+  }
+
+  TCollection_AsciiString aCommand (theArgVec[1]);
+  aCommand.LowerCase();
+  const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
+  if (anActiveView.IsNull())
+  {
+    std::cout << "Error: no active view.\n";
+    return 1;
+  }
+
+  // print maximum number of planes for current viewer
+  if (aCommand == "-maxplanes"
+   || aCommand == "maxplanes")
+  {
+    theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
+          << " plane slots provided by driver.\n";
+    return 0;
+  }
+
+  // create / delete plane instance
+  if (aCommand == "-create"
+   || aCommand == "create"
+   || aCommand == "-delete"
+   || aCommand == "delete"
+   || aCommand == "-clone"
+   || aCommand == "clone")
+  {
+    if (theArgsNb < 3)
+    {
+      std::cout << "Syntax error: plane name is required.\n";
+      return 1;
+    }
+
+    Standard_Boolean toCreate = aCommand == "-create"
+                             || aCommand == "create";
+    Standard_Boolean toClone  = aCommand == "-clone"
+                             || aCommand == "clone";
+    Standard_Boolean toDelete = aCommand == "-delete"
+                             || aCommand == "delete";
+    TCollection_AsciiString aPlane (theArgVec[2]);
+
+    if (toCreate)
+    {
+      if (aRegPlanes.IsBound (aPlane))
+      {
+        std::cout << "Warning: existing plane has been overridden.\n";
+        toDelete = true;
+      }
+      else
+      {
+        aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
+        return 0;
+      }
+    }
+    else if (toClone) // toClone
+    {
+      if (!aRegPlanes.IsBound (aPlane))
+      {
+        std::cout << "Error: no such plane.\n";
+        return 1;
+      }
+      else if (theArgsNb < 4)
+      {
+        std::cout << "Syntax error: enter name for new plane.\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aClone (theArgVec[3]);
+      if (aRegPlanes.IsBound (aClone))
+      {
+        std::cout << "Error: plane name is in use.\n";
+        return 1;
+      }
+
+      const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
+
+      aRegPlanes.Bind (aClone, aClipPlane->Clone());
+      return 0;
+    }
+
+    if (toDelete)
+    {
+      if (aPlane == "ALL"
+       || aPlane == "all"
+       || aPlane == "*")
+      {
+        for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
+        {
+          aPlane = aPlaneIter.Key();
+          removePlane (aRegPlanes, aPlane);
+          aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
+        }
+      }
+      else
+      {
+        removePlane (aRegPlanes, aPlane);
+      }
+    }
+
+    if (toCreate)
+    {
+      aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
+    }
+    return 0;
+  }
+
+  // set / unset plane command
+  if (aCommand == "set"
+   || aCommand == "unset")
+  {
+    if (theArgsNb < 5)
+    {
+      std::cout << "Syntax error: need more arguments.\n";
+      return 1;
+    }
+
+    // redirect to new syntax
+    NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
+    anArgVec.SetValue (1, theArgVec[0]);
+    anArgVec.SetValue (2, theArgVec[2]);
+    anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
+    for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
+    {
+      anArgVec.SetValue (anIt, theArgVec[anIt]);
+    }
+
+    return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
+  }
+
+  // change plane command
+  TCollection_AsciiString aPlaneName;
+  Handle(Graphic3d_ClipPlane) aClipPlane;
+  Standard_Integer anArgIter = 0;
+  if (aCommand == "-change"
+   || aCommand == "change")
+  {
+    // old syntax support
+    if (theArgsNb < 3)
+    {
+      std::cout << "Syntax error: need more arguments.\n";
+      return 1;
+    }
+
+    anArgIter  = 3;
+    aPlaneName = theArgVec[2];
+    if (!aRegPlanes.Find (aPlaneName, aClipPlane))
+    {
+      std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
+      return 1;
+    }
+  }
+  else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
+  {
+    anArgIter  = 2;
+    aPlaneName = theArgVec[1];
+  }
+  else
+  {
+    anArgIter  = 2;
+    aPlaneName = theArgVec[1];
+    aClipPlane = new Graphic3d_ClipPlane();
+    aRegPlanes.Bind (aPlaneName, aClipPlane);
+    theDi << "Created new plane " << aPlaneName << ".\n";
+  }
+
+  if (theArgsNb - anArgIter < 1)
+  {
+    std::cout << "Syntax error: need more arguments.\n";
+    return 1;
+  }
+
+  for (; anArgIter < theArgsNb; ++anArgIter)
+  {
+    const char**     aChangeArgs   = theArgVec + anArgIter;
+    Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
+    TCollection_AsciiString aChangeArg (aChangeArgs[0]);
+    aChangeArg.LowerCase();
+
+    Standard_Boolean toEnable = Standard_True;
+    if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
+    {
+      aClipPlane->SetOn (toEnable);
+    }
+    else if (aChangeArg == "-equation"
+          || aChangeArg == "equation")
+    {
+      if (aNbChangeArgs < 5)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
+      Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
+      Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
+      Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
+      aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
+      anArgIter += 4;
+    }
+    else if (aChangeArg == "-capping"
+          || aChangeArg == "capping")
+    {
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
+      {
+        aClipPlane->SetCapping (toEnable);
+        anArgIter += 1;
+      }
+      else
+      {
+        // just skip otherwise (old syntax)
+      }
+    }
+    else if (aChangeArg == "-useobjectmaterial"
+          || aChangeArg == "-useobjectmat"
+          || aChangeArg == "-useobjmat"
+          || aChangeArg == "-useobjmaterial")
+    {
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
+      {
+        aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
+        anArgIter += 1;
+      }
+    }
+    else if (aChangeArg == "-useobjecttexture"
+          || aChangeArg == "-useobjecttex"
+          || aChangeArg == "-useobjtexture"
+          || aChangeArg == "-useobjtex")
+    {
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
+      {
+        aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
+        anArgIter += 1;
+      }
+    }
+    else if (aChangeArg == "-useobjectshader"
+          || aChangeArg == "-useobjshader")
+    {
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
+      {
+        aClipPlane->SetUseObjectShader (toEnable == Standard_True);
+        anArgIter += 1;
+      }
+    }
+    else if (aChangeArg == "-color"
+          || aChangeArg == "color")
+    {
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
+                                                           aChangeArgs + 1,
+                                                           aColor);
+      if (aNbParsed == 0)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
+      aMat.SetAmbientColor (aColor);
+      aMat.SetDiffuseColor (aColor);
+      aClipPlane->SetCappingMaterial (aMat);
+      anArgIter += aNbParsed;
+    }
+    else if (aChangeArg == "-texname"
+          || aChangeArg == "texname")
+    {
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aTextureName (aChangeArgs[1]);
+      Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
+      if (!aTexture->IsDone())
+      {
+        aClipPlane->SetCappingTexture (NULL);
+      }
+      else
+      {
+        aTexture->EnableModulate();
+        aTexture->EnableRepeat();
+        aClipPlane->SetCappingTexture (aTexture);
+      }
+      anArgIter += 1;
+    }
+    else if (aChangeArg == "-texscale"
+          || aChangeArg == "texscale")
+    {
+      if (aClipPlane->CappingTexture().IsNull())
+      {
+        std::cout << "Error: no texture is set.\n";
+        return 1;
+      }
+
+      if (aNbChangeArgs < 3)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
+      Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
+      aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
+      anArgIter += 2;
+    }
+    else if (aChangeArg == "-texorigin"
+          || aChangeArg == "texorigin") // texture origin
+    {
+      if (aClipPlane->CappingTexture().IsNull())
+      {
+        std::cout << "Error: no texture is set.\n";
+        return 1;
+      }
+
+      if (aNbChangeArgs < 3)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
+      Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
+
+      aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
+      anArgIter += 2;
+    }
+    else if (aChangeArg == "-texrotate"
+          || aChangeArg == "texrotate") // texture rotation
+    {
+      if (aClipPlane->CappingTexture().IsNull())
+      {
+        std::cout << "Error: no texture is set.\n";
+        return 1;
+      }
+
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
+      aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
+      anArgIter += 1;
+    }
+    else if (aChangeArg == "-hatch"
+          || aChangeArg == "hatch")
+    {
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aHatchStr (aChangeArgs[1]);
+      aHatchStr.LowerCase();
+      if (aHatchStr == "on")
+      {
+        aClipPlane->SetCappingHatchOn();
+      }
+      else if (aHatchStr == "off")
+      {
+        aClipPlane->SetCappingHatchOff();
+      }
+      else
+      {
+        aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
+      }
+      anArgIter += 1;
+    }
+    else if (aChangeArg == "-delete"
+          || aChangeArg == "delete")
+    {
+      removePlane (aRegPlanes, aPlaneName);
+      return 0;
+    }
+    else if (aChangeArg == "-set"
+          || aChangeArg == "-unset")
+    {
+      // set / unset plane command
+      Standard_Boolean toSet = aChangeArg == "-set";
+      Standard_Integer anIt = 1;
+      for (; anIt < aNbChangeArgs; ++anIt)
+      {
+        TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
+        if (anEntityName.IsEmpty()
+         || anEntityName.Value (1) == '-')
+        {
+          break;
+        }
+        else if (ViewerTest_myViews.IsBound1 (anEntityName))
+        {
+          Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
+          if (toSet)
+          {
+            aView->AddClipPlane (aClipPlane);
+          }
+          else
+          {
+            aView->RemoveClipPlane (aClipPlane);
+          }
+          continue;
+        }
+        else if (GetMapOfAIS().IsBound2 (anEntityName))
+        {
+          Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
+          if (toSet)
+          {
+            aIObj->AddClipPlane (aClipPlane);
+          }
+          else
+          {
+            aIObj->RemoveClipPlane (aClipPlane);
+          }
+        }
+        else
+        {
+          std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
+          return 1;
+        }
+      }
+
+      if (anIt == 1)
+      {
+        // apply to active view
+        if (toSet)
+        {
+          anActiveView->AddClipPlane (aClipPlane);
+        }
+        else
+        {
+          anActiveView->RemoveClipPlane (aClipPlane);
+        }
+      }
+      else
+      {
+        anArgIter = anArgIter + anIt - 1;
+      }
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
+      return 1;
+    }
+  }
+
+  ViewerTest::RedrawAllViews();
+  return 0;
+}
+
+//===============================================================================================
+//function : VZRange
+//purpose  :
+//===============================================================================================
+static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
+
+  if (aCurrentView.IsNull())
+  {
+    std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
+    return 1;
+  }
+
+  Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
+
+  if (theArgsNb < 2)
+  {
+    theDi << "ZNear: " << aCamera->ZNear() << "\n";
+    theDi << "ZFar: " << aCamera->ZFar() << "\n";
+    return 0;
+  }
+
+  if (theArgsNb == 3)
+  {
+    Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
+    Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
+
+    if (aNewZNear >= aNewZFar)
+    {
+      std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
+      return 1;
+    }
+
+    if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
+    {
+      std::cout << theArgVec[0] << ": invalid arguments: ";
+      std::cout << "znear, zfar should be positive for perspective camera.\n";
+      return 1;
+    }
+
+    aCamera->SetZRange (aNewZNear, aNewZFar);
+  }
+  else
+  {
+    std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
+    return 1;
+  }
+
+  aCurrentView->Redraw();
+
+  return 0;
+}
+
+//===============================================================================================
+//function : VAutoZFit
+//purpose  :
+//===============================================================================================
+static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
+
+  if (aCurrentView.IsNull())
+  {
+    std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
+    return 1;
+  }
+
+  Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
+
+  if (theArgsNb > 3)
+  {
+    std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
+    return 1;
+  }
+
+  if (theArgsNb < 2)
+  {
+    theDi << "Auto z-fit mode: \n"
+          << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
+          << "Scale: " << aScale << "\n";
+    return 0;
+  }
+
+  Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
+
+  if (theArgsNb >= 3)
+  {
+    aScale = Draw::Atoi (theArgVec[2]);
+  }
+
+  aCurrentView->SetAutoZFitMode (isOn, aScale);
+  aCurrentView->AutoZFit();
+  aCurrentView->Redraw();
+
+  return 0;
+}
+
+//! Auxiliary function to print projection type
+inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
+{
+  switch (theProjType)
+  {
+    case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
+    case Graphic3d_Camera::Projection_Perspective:  return "perspective";
+    case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
+    case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
+    case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
+  }
+  return "UNKNOWN";
+}
+
+//===============================================================================================
+//function : VCamera
+//purpose  :
+//===============================================================================================
+static int VCamera (Draw_Interpretor& theDI,
+                    Standard_Integer  theArgsNb,
+                    const char**      theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << "Error: no active view.\n";
+    return 1;
+  }
+
+  Handle(Graphic3d_Camera) aCamera = aView->Camera();
+  if (theArgsNb < 2)
+  {
+    theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
+    theDI << "FOVy:       " << aCamera->FOVy() << "\n";
+    theDI << "Distance:   " << aCamera->Distance() << "\n";
+    theDI << "IOD:        " << aCamera->IOD() << "\n";
+    theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
+    theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
+    theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
+    return 0;
+  }
+
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
+  {
+    Standard_CString        anArg = theArgVec[anArgIter];
+    TCollection_AsciiString anArgCase (anArg);
+    anArgCase.LowerCase();
+    if (anArgCase == "-proj"
+     || anArgCase == "-projection"
+     || anArgCase == "-projtype"
+     || anArgCase == "-projectiontype")
+    {
+      theDI << projTypeName (aCamera->ProjectionType()) << " ";
+    }
+    else if (anArgCase == "-ortho"
+          || anArgCase == "-orthographic")
+    {
+      aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
+    }
+    else if (anArgCase == "-persp"
+          || anArgCase == "-perspective"
+          || anArgCase == "-perspmono"
+          || anArgCase == "-perspectivemono"
+          || anArgCase == "-mono")
+    {
+      aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
+    }
+    else if (anArgCase == "-stereo"
+          || anArgCase == "-stereoscopic"
+          || anArgCase == "-perspstereo"
+          || anArgCase == "-perspectivestereo")
+    {
+      aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
+    }
+    else if (anArgCase == "-left"
+          || anArgCase == "-lefteye"
+          || anArgCase == "-monoleft"
+          || anArgCase == "-monolefteye"
+          || anArgCase == "-perpsleft"
+          || anArgCase == "-perpslefteye")
+    {
+      aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
+    }
+    else if (anArgCase == "-right"
+          || anArgCase == "-righteye"
+          || anArgCase == "-monoright"
+          || anArgCase == "-monorighteye"
+          || anArgCase == "-perpsright")
+    {
+      aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
+    }
+    else if (anArgCase == "-dist"
+          || anArgCase == "-distance")
+    {
+      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
+      if (anArgValue != NULL
+      && *anArgValue != '-')
+      {
+        ++anArgIter;
+        aCamera->SetDistance (Draw::Atof (anArgValue));
+        continue;
+      }
+      theDI << aCamera->Distance() << " ";
+    }
+    else if (anArgCase == "-iod")
+    {
+      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
+      if (anArgValue != NULL
+      && *anArgValue != '-')
+      {
+        ++anArgIter;
+        aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
+        continue;
+      }
+      theDI << aCamera->IOD() << " ";
+    }
+    else if (anArgCase == "-iodtype")
+    {
+      Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
+      TCollection_AsciiString anValueCase (anArgValue);
+      anValueCase.LowerCase();
+      if (anValueCase == "abs"
+       || anValueCase == "absolute")
+      {
+        ++anArgIter;
+        aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
+        continue;
+      }
+      else if (anValueCase == "rel"
+            || anValueCase == "relative")
+      {
+        ++anArgIter;
+        aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
+        continue;
+      }
+      else if (*anArgValue != '-')
+      {
+        std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
+        return 1;
+      }
+      switch (aCamera->GetIODType())
+      {
+        case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
+        case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
+      }
+    }
+    else if (anArgCase == "-zfocus")
+    {
+      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
+      if (anArgValue != NULL
+      && *anArgValue != '-')
+      {
+        ++anArgIter;
+        aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
+        continue;
+      }
+      theDI << aCamera->ZFocus() << " ";
+    }
+    else if (anArgCase == "-zfocustype")
+    {
+      Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
+      TCollection_AsciiString anValueCase (anArgValue);
+      anValueCase.LowerCase();
+      if (anValueCase == "abs"
+       || anValueCase == "absolute")
+      {
+        ++anArgIter;
+        aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
+        continue;
+      }
+      else if (anValueCase == "rel"
+            || anValueCase == "relative")
+      {
+        ++anArgIter;
+        aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
+        continue;
+      }
+      else if (*anArgValue != '-')
+      {
+        std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
+        return 1;
+      }
+      switch (aCamera->ZFocusType())
+      {
+        case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
+        case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
+      }
+    }
+    else if (anArgCase == "-fov"
+          || anArgCase == "-fovy")
+    {
+      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
+      if (anArgValue != NULL
+      && *anArgValue != '-')
+      {
+        ++anArgIter;
+        aCamera->SetFOVy (Draw::Atof (anArgValue));
+        continue;
+      }
+      theDI << aCamera->FOVy() << " ";
+    }
+    else
+    {
+      std::cout << "Error: unknown argument '" << anArg << "'\n";
+      return 1;
+    }
+  }
+
+  aView->AutoZFit();
+  aView->Redraw();
+
+  return 0;
+}
+
+//! Parse stereo output mode
+inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
+                                         Graphic3d_StereoMode& theMode)
+{
+  TCollection_AsciiString aFlag (theArg);
+  aFlag.LowerCase();
+  if (aFlag == "quadbuffer")
+  {
+    theMode = Graphic3d_StereoMode_QuadBuffer;
+  }
+  else if (aFlag == "anaglyph")
+  {
+    theMode = Graphic3d_StereoMode_Anaglyph;
+  }
+  else if (aFlag == "row"
+        || aFlag == "rowinterlaced")
+  {
+    theMode = Graphic3d_StereoMode_RowInterlaced;
+  }
+  else if (aFlag == "col"
+        || aFlag == "colinterlaced"
+        || aFlag == "columninterlaced")
+  {
+    theMode = Graphic3d_StereoMode_ColumnInterlaced;
+  }
+  else if (aFlag == "chess"
+        || aFlag == "chessboard")
+  {
+    theMode = Graphic3d_StereoMode_ChessBoard;
+  }
+  else if (aFlag == "sbs"
+        || aFlag == "sidebyside")
+  {
+    theMode = Graphic3d_StereoMode_SideBySide;
+  }
+  else if (aFlag == "ou"
+        || aFlag == "overunder")
+  {
+    theMode = Graphic3d_StereoMode_OverUnder;
+  }
+  else if (aFlag == "pageflip"
+        || aFlag == "softpageflip")
+  {
+    theMode = Graphic3d_StereoMode_SoftPageFlip;
+  }
+  else
+  {
+    return Standard_False;
+  }
+  return Standard_True;
+}
+
+//! Parse anaglyph filter
+inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
+                                             Graphic3d_RenderingParams::Anaglyph& theFilter)
+{
+  TCollection_AsciiString aFlag (theArg);
+  aFlag.LowerCase();
+  if (aFlag == "redcyansimple")
+  {
+    theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
+  }
+  else if (aFlag == "redcyan"
+        || aFlag == "redcyanoptimized")
+  {
+    theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
+  }
+  else if (aFlag == "yellowbluesimple")
+  {
+    theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
+  }
+  else if (aFlag == "yellowblue"
+        || aFlag == "yellowblueoptimized")
+  {
+    theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
+  }
+  else if (aFlag == "greenmagenta"
+        || aFlag == "greenmagentasimple")
+  {
+    theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
+  }
+  else
+  {
+    return Standard_False;
+  }
+  return Standard_True;
+}
+
+//==============================================================================
+//function : VStereo
+//purpose  :
+//==============================================================================
+
+static int VStereo (Draw_Interpretor& theDI,
+                    Standard_Integer  theArgNb,
+                    const char**      theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (theArgNb < 2)
+  {
+    if (aView.IsNull())
+    {
+      std::cout << "Error: no active viewer!\n";
+      return 0;
+    }
+
+    Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
+    theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
+    if (isActive)
+    {
+      TCollection_AsciiString aMode;
+      switch (aView->RenderingParams().StereoMode)
+      {
+        case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
+        case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
+        case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
+        case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
+        case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
+        case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
+        case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
+        case Graphic3d_StereoMode_Anaglyph  :
+          aMode = "anaglyph";
+          switch (aView->RenderingParams().AnaglyphFilter)
+          {
+            case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
+            case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
+            case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
+            case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
+            case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
+            default: break;
+          }
+        default: break;
+      }
+      theDI << "Mode " << aMode << "\n";
+    }
+    return 0;
+  }
+
+  Handle(Graphic3d_Camera) aCamera;
+  Graphic3d_RenderingParams*   aParams   = NULL;
+  Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
+  if (!aView.IsNull())
+  {
+    aParams   = &aView->ChangeRenderingParams();
+    aMode     = aParams->StereoMode;
+    aCamera   = aView->Camera();
+  }
+
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    Standard_CString        anArg = theArgVec[anArgIter];
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (anUpdateTool.parseRedrawMode (aFlag))
+    {
+      continue;
+    }
+    else if (aFlag == "0"
+          || aFlag == "off")
+    {
+      if (++anArgIter < theArgNb)
+      {
+        std::cout << "Error: wrong number of arguments!\n";
+        return 1;
+      }
+
+      if (!aCamera.IsNull()
+       &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
+      {
+        aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
+      }
+      ViewerTest_myDefaultCaps.contextStereo = Standard_False;
+      return 0;
+    }
+    else if (aFlag == "1"
+          || aFlag == "on")
+    {
+      if (++anArgIter < theArgNb)
+      {
+        std::cout << "Error: wrong number of arguments!\n";
+        return 1;
+      }
+
+      if (!aCamera.IsNull())
+      {
+        aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
+      }
+      ViewerTest_myDefaultCaps.contextStereo = Standard_True;
+      return 0;
+    }
+    else if (aFlag == "-reverse"
+          || aFlag == "-reversed"
+          || aFlag == "-swap")
+    {
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams->ToReverseStereo = toEnable;
+    }
+    else if (aFlag == "-noreverse"
+          || aFlag == "-noswap")
+    {
+      Standard_Boolean toDisable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
+      {
+        --anArgIter;
+      }
+      aParams->ToReverseStereo = !toDisable;
+    }
+    else if (aFlag == "-mode"
+          || aFlag == "-stereomode")
+    {
+      if (++anArgIter >= theArgNb
+      || !parseStereoMode (theArgVec[anArgIter], aMode))
+      {
+        std::cout << "Error: syntax error at '" << anArg << "'\n";
+        return 1;
+      }
+
+      if (aMode == Graphic3d_StereoMode_QuadBuffer)
+      {
+        ViewerTest_myDefaultCaps.contextStereo = Standard_True;
+      }
+    }
+    else if (aFlag == "-anaglyph"
+          || aFlag == "-anaglyphfilter")
+    {
+      Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
+      if (++anArgIter >= theArgNb
+      || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
+      {
+        std::cout << "Error: syntax error at '" << anArg << "'\n";
+        return 1;
+      }
+
+      aMode = Graphic3d_StereoMode_Anaglyph;
+      aParams->AnaglyphFilter = aFilter;
+    }
+    else if (parseStereoMode (anArg, aMode)) // short syntax
+    {
+      if (aMode == Graphic3d_StereoMode_QuadBuffer)
+      {
+        ViewerTest_myDefaultCaps.contextStereo = Standard_True;
+      }
+    }
+    else
+    {
+      std::cout << "Error: syntax error at '" << anArg << "'\n";
+      return 1;
+    }
+  }
+
+  if (!aView.IsNull())
+  {
+    aParams->StereoMode = aMode;
+    aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
+  }
+  return 0;
+}
+
+//===============================================================================================
+//function : VDefaults
+//purpose  :
+//===============================================================================================
+static int VDefaults (Draw_Interpretor& theDi,
+                      Standard_Integer  theArgsNb,
+                      const char**      theArgVec)
+{
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  if (aCtx.IsNull())
+  {
+    std::cerr << "No active viewer!\n";
+    return 1;
+  }
+
+  Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
+  if (theArgsNb < 2)
+  {
+    if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
+    {
+      theDi << "DeflType:           relative\n"
+            << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
+    }
+    else
+    {
+      theDi << "DeflType:           absolute\n"
+            << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
+    }
+    theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
+    theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
+    return 0;
+  }
+
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.UpperCase();
+    if (anArg == "-ABSDEFL"
+     || anArg == "-ABSOLUTEDEFLECTION"
+     || anArg == "-DEFL"
+     || anArg == "-DEFLECTION")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Error: wrong syntax at " << anArg << "\n";
+        return 1;
+      }
+      aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
+      aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
+    }
+    else if (anArg == "-RELDEFL"
+          || anArg == "-RELATIVEDEFLECTION"
+          || anArg == "-DEVCOEFF"
+          || anArg == "-DEVIATIONCOEFF"
+          || anArg == "-DEVIATIONCOEFFICIENT")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Error: wrong syntax at " << anArg << "\n";
+        return 1;
+      }
+      aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
+      aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
+    }
+    else if (anArg == "-ANGDEFL"
+          || anArg == "-ANGULARDEFL"
+          || anArg == "-ANGULARDEFLECTION")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Error: wrong syntax at " << anArg << "\n";
+        return 1;
+      }
+      // currently HLRDeviationAngle is used instead of DeviationAngle in most places
+      aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
+    }
+    else if (anArg == "-AUTOTR"
+          || anArg == "-AUTOTRIANG"
+          || anArg == "-AUTOTRIANGULATION")
+    {
+      if (++anArgIter >= theArgsNb)
+      {
+        std::cout << "Error: wrong syntax at " << anArg << "\n";
+        return 1;
+      }
+      TCollection_AsciiString aValue (theArgVec[anArgIter]);
+      aValue.LowerCase();
+      if (aValue == "on"
+       || aValue == "1")
+      {
+        aDefParams->SetAutoTriangulation (Standard_True);
+      }
+      else if (aValue == "off"
+            || aValue == "0")
+      {
+        aDefParams->SetAutoTriangulation (Standard_False);
+      }
+    }
+    else
+    {
+      std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
+    }
+  }
+
+  return 0;
+}
+
+//! Auxiliary method
+inline void addLight (const Handle(V3d_Light)& theLightNew,
+                      const Standard_Boolean   theIsGlobal)
+{
+  if (theLightNew.IsNull())
+  {
+    return;
+  }
+
+  if (theIsGlobal)
+  {
+    ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
+  }
+  else
+  {
+    ViewerTest::CurrentView()->SetLightOn (theLightNew);
+  }
+}
+
+//! Auxiliary method
+inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
+{
+  TCollection_AsciiString anArgNextCase (theArgNext);
+  anArgNextCase.UpperCase();
+  if (anArgNextCase.Length() > 5
+   && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
+  {
+    return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
+  }
+  else
+  {
+    return theArgNext.IntegerValue();
+  }
+}
+
+//===============================================================================================
+//function : VLight
+//purpose  :
+//===============================================================================================
+static int VLight (Draw_Interpretor& theDi,
+                   Standard_Integer  theArgsNb,
+                   const char**      theArgVec)
+{
+  Handle(V3d_View)   aView   = ViewerTest::CurrentView();
+  Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
+  if (aView.IsNull()
+   || aViewer.IsNull())
+  {
+    std::cerr << "No active viewer!\n";
+    return 1;
+  }
+
+  Standard_Real        anXYZ[3];
+  Quantity_Coefficient anAtten[2];
+  if (theArgsNb < 2)
+  {
+    // print lights info
+    Standard_Integer aLightId = 0;
+    for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
+    {
+      Handle(V3d_Light) aLight = aLightIter.Value();
+      const Quantity_Color aColor = aLight->Color();
+      theDi << "Light" << aLightId << "\n";
+      switch (aLight->Type())
+      {
+        case V3d_AMBIENT:
+        {
+          theDi << "  Type:       Ambient\n";
+          theDi << "  Intensity:  " << aLight->Intensity() << "\n";
+          break;
+        }
+        case V3d_DIRECTIONAL:
+        {
+          Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
+          theDi << "  Type:       Directional\n";
+          theDi << "  Intensity:  " << aLight->Intensity() << "\n";
+          theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
+          theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
+          if (!aLightDir.IsNull())
+          {
+            aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
+            theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
+            aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
+            theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
+          }
+          break;
+        }
+        case V3d_POSITIONAL:
+        {
+          Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
+          theDi << "  Type:       Positional\n";
+          theDi << "  Intensity:  " << aLight->Intensity() << "\n";
+          theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
+          theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
+          if (!aLightPos.IsNull())
+          {
+            aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
+            theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
+            aLightPos->Attenuation (anAtten[0], anAtten[1]);
+            theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
+          }
+          break;
+        }
+        case V3d_SPOT:
+        {
+          Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
+          theDi << "  Type:       Spot\n";
+          theDi << "  Intensity:  " << aLight->Intensity() << "\n";
+          theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
+          if (!aLightSpot.IsNull())
+          {
+            aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
+            theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
+            aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
+            theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
+            aLightSpot->Attenuation (anAtten[0], anAtten[1]);
+            theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
+            theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
+            theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
+          }
+          break;
+        }
+        default:
+        {
+          theDi << "  Type:       UNKNOWN\n";
+          break;
+        }
       }
-      theDI << aCamera->Distance() << " ";
+      theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
     }
-    else if (anArgCase == "-iod")
+  }
+
+  Handle(V3d_Light) aLightNew;
+  Handle(V3d_Light) aLightOld;
+  Standard_Boolean  isGlobal = Standard_True;
+  Standard_Boolean  toCreate = Standard_False;
+  for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
+  {
+    Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
+    Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
+    Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
+    Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
+    Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
+
+    TCollection_AsciiString aName, aValue;
+    const TCollection_AsciiString anArg (theArgVec[anArgIt]);
+    TCollection_AsciiString anArgCase (anArg);
+    anArgCase.UpperCase();
+    if (anArgCase.IsEqual ("NEW")
+     || anArgCase.IsEqual ("ADD")
+     || anArgCase.IsEqual ("CREATE"))
     {
-      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
-      if (anArgValue != NULL
-      && *anArgValue != '-')
+      toCreate = Standard_True;
+    }
+    else if (anArgCase.IsEqual ("GLOB")
+          || anArgCase.IsEqual ("GLOBAL"))
+    {
+      isGlobal = Standard_True;
+    }
+    else if (anArgCase.IsEqual ("LOC")
+          || anArgCase.IsEqual ("LOCAL"))
+    {
+      isGlobal = Standard_False;
+    }
+    else if (anArgCase.IsEqual ("DEF")
+          || anArgCase.IsEqual ("DEFAULTS"))
+    {
+      toCreate = Standard_False;
+      aViewer->SetDefaultLights();
+    }
+    else if (anArgCase.IsEqual ("CLR")
+          || anArgCase.IsEqual ("CLEAR"))
+    {
+      toCreate = Standard_False;
+      for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
       {
-        ++anArgIter;
-        aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
-        continue;
+        Handle(V3d_Light) aLight = aLightIter.Value();
+        aViewer->DelLight (aLight);
+        aLightIter = aView->ActiveLightIterator();
+      }
+    }
+    else if (anArgCase.IsEqual ("AMB")
+          || anArgCase.IsEqual ("AMBIENT")
+          || anArgCase.IsEqual ("AMBLIGHT"))
+    {
+      addLight (aLightNew, isGlobal);
+      if (!toCreate)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+      toCreate  = Standard_False;
+      aLightNew = new V3d_AmbientLight (aViewer);
+    }
+    else if (anArgCase.IsEqual ("DIRECTIONAL")
+          || anArgCase.IsEqual ("DIRLIGHT"))
+    {
+      addLight (aLightNew, isGlobal);
+      if (!toCreate)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+      toCreate  = Standard_False;
+      aLightNew = new V3d_DirectionalLight (aViewer);
+    }
+    else if (anArgCase.IsEqual ("SPOT")
+          || anArgCase.IsEqual ("SPOTLIGHT"))
+    {
+      addLight (aLightNew, isGlobal);
+      if (!toCreate)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+      toCreate  = Standard_False;
+      aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
+    }
+    else if (anArgCase.IsEqual ("POSLIGHT")
+          || anArgCase.IsEqual ("POSITIONAL"))
+    {
+      addLight (aLightNew, isGlobal);
+      if (!toCreate)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+      toCreate  = Standard_False;
+      aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
+    }
+    else if (anArgCase.IsEqual ("CHANGE"))
+    {
+      addLight (aLightNew, isGlobal);
+      aLightNew.Nullify();
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
+      Standard_Integer aLightIt = 0;
+      for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
+      {
+        if (aLightIt == aLightId)
+        {
+          aLightOld = aLightIter.Value();
+          break;
+        }
+      }
+
+      if (aLightOld.IsNull())
+      {
+        std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
+        return 1;
+      }
+    }
+    else if (anArgCase.IsEqual ("DEL")
+          || anArgCase.IsEqual ("DELETE"))
+    {
+      Handle(V3d_Light) aLightDel;
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
+      const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
+      Standard_Integer aLightIt = 0;
+      for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
+      {
+        aLightDel = aLightIter.Value();
+        if (aLightIt == aLightDelId)
+        {
+          break;
+        }
+      }
+      if (!aLightDel.IsNull())
+      {
+        aViewer->DelLight (aLightDel);
+      }
+    }
+    else if (anArgCase.IsEqual ("COLOR")
+          || anArgCase.IsEqual ("COLOUR"))
+    {
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
+      anArgNext.UpperCase();
+      const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
+      if (!aLightCurr.IsNull())
+      {
+        aLightCurr->SetColor (aColor);
+      }
+    }
+    else if (anArgCase.IsEqual ("POS")
+          || anArgCase.IsEqual ("POSITION"))
+    {
+      if ((anArgIt + 3) >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      anXYZ[0] = Atof (theArgVec[++anArgIt]);
+      anXYZ[1] = Atof (theArgVec[++anArgIt]);
+      anXYZ[2] = Atof (theArgVec[++anArgIt]);
+      if (!aLightDir.IsNull())
+      {
+        aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+      }
+      else if (!aLightPos.IsNull())
+      {
+        aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+      }
+      else if (!aLightSpot.IsNull())
+      {
+        aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+      }
+      else
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
       }
-      theDI << aCamera->IOD() << " ";
     }
-    else if (anArgCase == "-iodtype")
+    else if (anArgCase.IsEqual ("DIR")
+          || anArgCase.IsEqual ("DIRECTION"))
     {
-      Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
-      TCollection_AsciiString anValueCase (anArgValue);
-      anValueCase.LowerCase();
-      if (anValueCase == "abs"
-       || anValueCase == "absolute")
+      if ((anArgIt + 3) >= theArgsNb)
       {
-        ++anArgIter;
-        aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
-        continue;
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
       }
-      else if (anValueCase == "rel"
-            || anValueCase == "relative")
+
+      anXYZ[0] = Atof (theArgVec[++anArgIt]);
+      anXYZ[1] = Atof (theArgVec[++anArgIt]);
+      anXYZ[2] = Atof (theArgVec[++anArgIt]);
+      if (!aLightDir.IsNull())
       {
-        ++anArgIter;
-        aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
-        continue;
+        aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
       }
-      else if (*anArgValue != '-')
+      else if (!aLightSpot.IsNull())
       {
-        std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
-        return 1;
+        aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
       }
-      switch (aCamera->GetIODType())
+      else
       {
-        case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
-        case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
       }
     }
-    else if (anArgCase == "-zfocus")
+    else if (anArgCase.IsEqual ("SM")
+          || anArgCase.IsEqual ("SMOOTHNESS"))
     {
-      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
-      if (anArgValue != NULL
-      && *anArgValue != '-')
+      if (++anArgIt >= theArgsNb)
       {
-        ++anArgIter;
-        aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
-        continue;
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
       }
-      theDI << aCamera->ZFocus() << " ";
-    }
-    else if (anArgCase == "-zfocustype")
-    {
-      Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
-      TCollection_AsciiString anValueCase (anArgValue);
-      anValueCase.LowerCase();
-      if (anValueCase == "abs"
-       || anValueCase == "absolute")
+
+      Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
+
+      if (fabs (aSmoothness) < Precision::Confusion())
       {
-        ++anArgIter;
-        aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
-        continue;
+        aLightCurr->SetIntensity (1.f);
       }
-      else if (anValueCase == "rel"
-            || anValueCase == "relative")
+      else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
       {
-        ++anArgIter;
-        aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
-        continue;
+        aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
       }
-      else if (*anArgValue != '-')
+      else
       {
-        std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
-        return 1;
+        Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
+        aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
       }
-      switch (aCamera->ZFocusType())
+
+      if (!aLightPos.IsNull())
       {
-        case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
-        case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
+        aLightPos->SetSmoothRadius (aSmoothness);
       }
-    }
-    else if (anArgCase == "-fov"
-          || anArgCase == "-fovy")
-    {
-      Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
-      if (anArgValue != NULL
-      && *anArgValue != '-')
+      else if (!aLightDir.IsNull())
       {
-        ++anArgIter;
-        aCamera->SetFOVy (Draw::Atof (anArgValue));
-        continue;
+        aLightDir->SetSmoothAngle (aSmoothness);
       }
-      theDI << aCamera->FOVy() << " ";
     }
-    else
+    else if (anArgCase.IsEqual ("INT")
+          || anArgCase.IsEqual ("INTENSITY"))
     {
-      std::cout << "Error: unknown argument '" << anArg << "'\n";
-      return 1;
-    }
-  }
-
-  aView->View()->AutoZFit();
-  aView->Redraw();
-
-  return 0;
-}
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-//==============================================================================
-//function : VStereo
-//purpose  :
-//==============================================================================
+      Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
 
-static int VStereo (Draw_Interpretor& theDI,
-                    Standard_Integer  theArgNb,
-                    const char**      theArgVec)
-{
-  if (theArgNb < 2)
-  {
-    Handle(V3d_View) aView = ViewerTest::CurrentView();
-    if (aView.IsNull())
-    {
-      std::cerr << "No active view. Please call vinit.\n";
-      return 0;
+      if (!aLightCurr.IsNull())
+      {
+        aLightCurr->SetIntensity (aIntensity);
+      }
     }
+    else if (anArgCase.IsEqual ("ANG")
+          || anArgCase.IsEqual ("ANGLE"))
+    {
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-    Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
-    theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
-    return 0;
-  }
-
-  ViewerTest_myDefaultCaps.contextStereo = Draw::Atoi (theArgVec[1]) != 0;
-  return 0;
-}
-
-//===============================================================================================
-//function : VDefaults
-//purpose  :
-//===============================================================================================
-static int VDefaults (Draw_Interpretor& theDi,
-                      Standard_Integer  theArgsNb,
-                      const char**      theArgVec)
-{
-  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
-  if (aCtx.IsNull())
-  {
-    std::cerr << "No active viewer!\n";
-    return 1;
-  }
+      Standard_Real anAngle = Atof (theArgVec[anArgIt]);
 
-  Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
-  if (theArgsNb < 2)
-  {
-    if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
-    {
-      theDi << "DeflType:           relative\n"
-            << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
+      if (!aLightSpot.IsNull())
+      {
+        aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
+      }
     }
-    else
+    else if (anArgCase.IsEqual ("CONSTATTEN")
+          || anArgCase.IsEqual ("CONSTATTENUATION"))
     {
-      theDi << "DeflType:           absolute\n"
-            << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
-    }
-    theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
-    return 0;
-  }
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
 
-  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
-  {
-    TCollection_AsciiString anArg (theArgVec[anArgIter]);
-    TCollection_AsciiString aKey, aValue;
-    if (!ViewerTest::SplitParameter (anArg, aKey, aValue)
-     || aValue.IsEmpty())
-    {
-      std::cerr << "Error, wrong syntax at: '" << anArg.ToCString() << "'!\n";
-      return 1;
+      if (!aLightPos.IsNull())
+      {
+        aLightPos->Attenuation (anAtten[0], anAtten[1]);
+        anAtten[0] = Atof (theArgVec[anArgIt]);
+        aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
+      }
+      else if (!aLightSpot.IsNull())
+      {
+        aLightSpot->Attenuation (anAtten[0], anAtten[1]);
+        anAtten[0] = Atof (theArgVec[anArgIt]);
+        aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
+      }
+      else
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
     }
-
-    aKey.UpperCase();
-    if (aKey == "ABSDEFL"
-     || aKey == "ABSOLUTEDEFLECTION"
-     || aKey == "DEFL"
-     || aKey == "DEFLECTION")
+    else if (anArgCase.IsEqual ("LINATTEN")
+          || anArgCase.IsEqual ("LINEARATTEN")
+          || anArgCase.IsEqual ("LINEARATTENUATION"))
     {
-      aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
-      aDefParams->SetMaximalChordialDeviation (aValue.RealValue());
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      if (!aLightPos.IsNull())
+      {
+        aLightPos->Attenuation (anAtten[0], anAtten[1]);
+        anAtten[1] = Atof (theArgVec[anArgIt]);
+        aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
+      }
+      else if (!aLightSpot.IsNull())
+      {
+        aLightSpot->Attenuation (anAtten[0], anAtten[1]);
+        anAtten[1] = Atof (theArgVec[anArgIt]);
+        aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
+      }
+      else
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
     }
-    else if (aKey == "RELDEFL"
-          || aKey == "RELATIVEDEFLECTION"
-          || aKey == "DEVCOEFF"
-          || aKey == "DEVIATIONCOEFF"
-          || aKey == "DEVIATIONCOEFFICIENT")
+    else if (anArgCase.IsEqual ("EXP")
+          || anArgCase.IsEqual ("EXPONENT")
+          || anArgCase.IsEqual ("SPOTEXP")
+          || anArgCase.IsEqual ("SPOTEXPONENT"))
     {
-      aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
-      aDefParams->SetDeviationCoefficient (aValue.RealValue());
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      if (!aLightSpot.IsNull())
+      {
+        aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
+      }
+      else
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
     }
-    else if (aKey == "ANGDEFL"
-          || aKey == "ANGULARDEFL"
-          || aKey == "ANGULARDEFLECTION")
+    else if (anArgCase.IsEqual ("HEAD")
+          || anArgCase.IsEqual ("HEADLIGHT"))
     {
-      // currently HLRDeviationAngle is used instead of DeviationAngle in most places
-      aDefParams->SetHLRAngle (M_PI * aValue.RealValue() / 180.0);
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      if (aLightAmb.IsNull()
+       && !aLightCurr.IsNull())
+      {
+        aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
+      }
+      else
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
     }
     else
     {
-      std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
+      std::cerr << "Warning: unknown argument '" << anArg << "'\n";
     }
   }
 
-  return 0;
-}
-
-//! Auxiliary method
-inline void addLight (const Handle(V3d_Light)& theLightNew,
-                      const Standard_Boolean   theIsGlobal)
-{
-  if (theLightNew.IsNull())
-  {
-    return;
-  }
+  addLight (aLightNew, isGlobal);
+  aViewer->UpdateLights();
 
-  if (theIsGlobal)
-  {
-    ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
-  }
-  else
-  {
-    ViewerTest::CurrentView()->SetLightOn (theLightNew);
-  }
+  return 0;
 }
 
-//! Auxiliary method
-inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
-{
-  TCollection_AsciiString anArgNextCase (theArgNext);
-  anArgNextCase.UpperCase();
-  if (anArgNextCase.Length() > 5
-   && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
-  {
-    return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
-  }
-  else
-  {
-    return theArgNext.IntegerValue();
-  }
-}
+//=======================================================================
+//function : VRenderParams
+//purpose  : Enables/disables rendering features
+//=======================================================================
 
-//===============================================================================================
-//function : VLight
-//purpose  :
-//===============================================================================================
-static int VLight (Draw_Interpretor& theDi,
-                   Standard_Integer  theArgsNb,
-                   const char**      theArgVec)
+static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
+                                       Standard_Integer  theArgNb,
+                                       const char**      theArgVec)
 {
-  Handle(V3d_View)   aView   = ViewerTest::CurrentView();
-  Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
-  if (aView.IsNull()
-   || aViewer.IsNull())
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    std::cerr << "No active viewer!\n";
+    std::cerr << "Error: no active viewer!\n";
     return 1;
   }
 
-  Standard_Real        anXYZ[3];
-  Quantity_Coefficient anAtten[2];
-  if (theArgsNb < 2)
+  Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
+  TCollection_AsciiString aCmdName (theArgVec[0]);
+  aCmdName.LowerCase();
+  if (aCmdName == "vraytrace")
   {
-    // print lights info
-    Standard_Integer aLightId = 0;
-    for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightId)
+    if (theArgNb == 1)
     {
-      Handle(V3d_Light) aLight = aView->ActiveLight();
-      const Quantity_Color aColor = aLight->Color();
-      theDi << "Light" << aLightId << "\n";
-      switch (aLight->Type())
+      theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
+      return 0;
+    }
+    else if (theArgNb == 2)
+    {
+      TCollection_AsciiString aValue (theArgVec[1]);
+      aValue.LowerCase();
+      if (aValue == "on"
+       || aValue == "1")
       {
-        case V3d_AMBIENT:
-        {
-          theDi << "  Type:      Ambient\n";
-          break;
-        }
-        case V3d_DIRECTIONAL:
-        {
-          Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
-          theDi << "  Type:      Directional\n";
-          theDi << "  Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
-          if (!aLightDir.IsNull())
-          {
-            aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
-            theDi << "  Position:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
-            aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
-            theDi << "  Direction: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
-          }
-          break;
-        }
-        case V3d_POSITIONAL:
-        {
-          Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
-          theDi << "  Type:      Positional\n";
-          theDi << "  Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
-          if (!aLightPos.IsNull())
-          {
-            aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
-            theDi << "  Position:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
-            aLightPos->Attenuation (anAtten[0], anAtten[1]);
-            theDi << "  Atten.:    " << anAtten[0] << " " << anAtten[1] << "\n";
-          }
-          break;
-        }
-        case V3d_SPOT:
-        {
-          Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
-          theDi << "  Type:      Spot\n";
-          theDi << "  Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
-          if (!aLightSpot.IsNull())
-          {
-            aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
-            theDi << "  Position:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
-            aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
-            theDi << "  Direction: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
-            aLightSpot->Attenuation (anAtten[0], anAtten[1]);
-            theDi << "  Atten.:    " << anAtten[0] << " " << anAtten[1] << "\n";
-            theDi << "  Angle:     " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
-            theDi << "  Exponent:  " << aLightSpot->Concentration() << "\n";
-          }
-          break;
-        }
-        default:
-        {
-          theDi << "  Type:      UNKNOWN\n";
-          break;
-        }
+        aParams.Method = Graphic3d_RM_RAYTRACING;
+        aView->Redraw();
+        return 0;
       }
-      theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
+      else if (aValue == "off"
+            || aValue == "0")
+      {
+        aParams.Method = Graphic3d_RM_RASTERIZATION;
+        aView->Redraw();
+        return 0;
+      }
+      else
+      {
+        std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
+        return 1;
+      }
+    }
+    else
+    {
+      std::cout << "Error: wrong number of arguments\n";
+      return 1;
     }
   }
 
-  Handle(V3d_Light) aLightNew;
-  Handle(V3d_Light) aLightOld;
-  Standard_Boolean  isGlobal = Standard_True;
-  Standard_Boolean  toCreate = Standard_False;
-  for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
+  if (theArgNb < 2)
   {
-    Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
-    Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
-    Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
-    Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
-    Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
-
-    TCollection_AsciiString aName, aValue;
-    const TCollection_AsciiString anArg (theArgVec[anArgIt]);
-    TCollection_AsciiString anArgCase (anArg);
-    anArgCase.UpperCase();
-    if (anArgCase.IsEqual ("NEW")
-     || anArgCase.IsEqual ("ADD")
-     || anArgCase.IsEqual ("CREATE"))
+    theDI << "renderMode:  ";
+    switch (aParams.Method)
     {
-      toCreate = Standard_True;
+      case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
+      case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
     }
-    else if (anArgCase.IsEqual ("GLOB")
-          || anArgCase.IsEqual ("GLOBAL"))
+    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 << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
+    theDI << "shadingModel: ";
+    switch (aView->ShadingModel())
     {
-      isGlobal = Standard_True;
+      case V3d_COLOR:   theDI << "color";   break;
+      case V3d_FLAT:    theDI << "flat";    break;
+      case V3d_GOURAUD: theDI << "gouraud"; break;
+      case V3d_PHONG:   theDI << "phong";   break;
     }
-    else if (anArgCase.IsEqual ("LOC")
-          || anArgCase.IsEqual ("LOCAL"))
+    theDI << "\n";
+    return 0;
+  }
+
+  Standard_Boolean toPrint = Standard_False;
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  {
+    Standard_CString        anArg (theArgVec[anArgIter]);
+    TCollection_AsciiString aFlag (anArg);
+    aFlag.LowerCase();
+    if (anUpdateTool.parseRedrawMode (aFlag))
     {
-      isGlobal = Standard_False;
+      continue;
     }
-    else if (anArgCase.IsEqual ("DEF")
-          || anArgCase.IsEqual ("DEFAULTS"))
+    else if (aFlag == "-echo"
+          || aFlag == "-print")
     {
-      toCreate = Standard_False;
-      aViewer->SetDefaultLights();
+      toPrint = Standard_True;
+      anUpdateTool.Invalidate();
     }
-    else if (anArgCase.IsEqual ("CLR")
-          || anArgCase.IsEqual ("CLEAR"))
+    else if (aFlag == "-mode"
+          || aFlag == "-rendermode"
+          || aFlag == "-render_mode")
     {
-      toCreate = Standard_False;
-      aView->InitActiveLights();
-      while (aView->MoreActiveLights())
+      if (toPrint)
+      {
+        switch (aParams.Method)
+        {
+          case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
+          case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
+        }
+        continue;
+      }
+      else
       {
-        aViewer->DelLight (aView->ActiveLight());
-        aView->InitActiveLights();
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
       }
     }
-    else if (anArgCase.IsEqual ("AMB")
-          || anArgCase.IsEqual ("AMBIENT")
-          || anArgCase.IsEqual ("AMBLIGHT"))
+    else if (aFlag == "-ray"
+          || aFlag == "-raytrace")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
+        continue;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_AmbientLight (aViewer);
+
+      aParams.Method = Graphic3d_RM_RAYTRACING;
     }
-    else if (anArgCase.IsEqual ("DIRECTIONAL")
-          || anArgCase.IsEqual ("DIRLIGHT"))
+    else if (aFlag == "-rast"
+          || aFlag == "-raster"
+          || aFlag == "-rasterization")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
+        continue;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_DirectionalLight (aViewer);
+
+      aParams.Method = Graphic3d_RM_RASTERIZATION;
     }
-    else if (anArgCase.IsEqual ("SPOT")
-          || anArgCase.IsEqual ("SPOTLIGHT"))
+    else if (aFlag == "-msaa")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        theDI << aParams.NbMsaaSamples << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
         return 1;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
-    }
-    else if (anArgCase.IsEqual ("POSLIGHT")
-          || anArgCase.IsEqual ("POSITIONAL"))
-    {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+
+      const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
+      if (aNbSamples < 0)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
         return 1;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
+      else
+      {
+        aParams.NbMsaaSamples = aNbSamples;
+      }
     }
-    else if (anArgCase.IsEqual ("CHANGE"))
+    else if (aFlag == "-raydepth"
+          || aFlag == "-ray_depth")
     {
-      addLight (aLightNew, isGlobal);
-      aLightNew.Nullify();
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << aParams.RaytracingDepth << " ";
+        continue;
       }
-
-      const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
-      Standard_Integer aLightIt = 0;
-      for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
+      else if (++anArgIter >= theArgNb)
       {
-        if (aLightIt == aLightId)
-        {
-          aLightOld = aView->ActiveLight();
-          break;
-        }
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
       }
 
-      if (aLightOld.IsNull())
+      const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
+
+      // We allow RaytracingDepth be more than 10 in case of GI enabled
+      if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
       {
-        std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
+        std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
         return 1;
       }
+      else
+      {
+        aParams.RaytracingDepth = aDepth;
+      }
     }
-    else if (anArgCase.IsEqual ("DEL")
-          || anArgCase.IsEqual ("DELETE"))
+    else if (aFlag == "-shad"
+          || aFlag == "-shadows")
     {
-      Handle(V3d_Light) aLightDel;
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
+        continue;
       }
 
-      const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
-      const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
-      Standard_Integer aLightIt = 0;
-      for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightDel = aView->ActiveLight();
-        if (aLightIt == aLightDelId)
-        {
-          break;
-        }
+        --anArgIter;
       }
-      if (!aLightDel.IsNull())
+      aParams.IsShadowEnabled = toEnable;
+    }
+    else if (aFlag == "-refl"
+          || aFlag == "-reflections")
+    {
+      if (toPrint)
       {
-        aViewer->DelLight (aLightDel);
+        theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
       }
+      aParams.IsReflectionEnabled = toEnable;
     }
-    else if (anArgCase.IsEqual ("COLOR")
-          || anArgCase.IsEqual ("COLOUR"))
+    else if (aFlag == "-fsaa")
     {
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
+        continue;
       }
 
-      TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
-      anArgNext.UpperCase();
-      const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
-      if (!aLightCurr.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightCurr->SetColor (aColor);
+        --anArgIter;
       }
+      aParams.IsAntialiasingEnabled = toEnable;
     }
-    else if (anArgCase.IsEqual ("POS")
-          || anArgCase.IsEqual ("POSITION"))
+    else if (aFlag == "-gleam")
     {
-      if ((anArgIt + 3) >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
+        continue;
       }
 
-      anXYZ[0] = Atof (theArgVec[++anArgIt]);
-      anXYZ[1] = Atof (theArgVec[++anArgIt]);
-      anXYZ[2] = Atof (theArgVec[++anArgIt]);
-      if (!aLightDir.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+        --anArgIter;
       }
-      else if (!aLightPos.IsNull())
+      aParams.IsTransparentShadowEnabled = toEnable;
+    }
+    else if (aFlag == "-gi")
+    {
+      if (toPrint)
       {
-        aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+        theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
+        continue;
       }
-      else if (!aLightSpot.IsNull())
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+        --anArgIter;
       }
-      else
+      aParams.IsGlobalIlluminationEnabled = toEnable;
+      if (!toEnable)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
       }
     }
-    else if (anArgCase.IsEqual ("DIR")
-          || anArgCase.IsEqual ("DIRECTION"))
+    else if (aFlag == "-blockedrng"
+          || aFlag == "-brng")
     {
-      if ((anArgIt + 3) >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
+        continue;
       }
 
-      anXYZ[0] = Atof (theArgVec[++anArgIt]);
-      anXYZ[1] = Atof (theArgVec[++anArgIt]);
-      anXYZ[2] = Atof (theArgVec[++anArgIt]);
-      if (!aLightDir.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
+        --anArgIter;
       }
-      else if (!aLightSpot.IsNull())
+      aParams.CoherentPathTracingMode = toEnable;
+    }
+    else if (aFlag == "-iss")
+    {
+      if (toPrint)
       {
-        aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
+        theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
+        continue;
       }
-      else
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        --anArgIter;
       }
+      aParams.AdaptiveScreenSampling = toEnable;
     }
-    else if (anArgCase.IsEqual ("ANG")
-          || anArgCase.IsEqual ("ANGLE"))
+    else if (aFlag == "-issd")
     {
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
+        continue;
       }
 
-      Standard_Real anAngle = Atof (theArgVec[anArgIt]);
-
-      if (!aLightSpot.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
+        --anArgIter;
       }
+      aParams.ShowSamplingTiles = toEnable;
     }
-    else if (anArgCase.IsEqual ("CONSTATTEN")
-          || anArgCase.IsEqual ("CONSTATTENUATION"))
+    else if (aFlag == "-env")
     {
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
+        continue;
       }
 
-      if (!aLightPos.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightPos->Attenuation (anAtten[0], anAtten[1]);
-        anAtten[0] = Atof (theArgVec[anArgIt]);
-        aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
+        --anArgIter;
       }
-      else if (!aLightSpot.IsNull())
+      aParams.UseEnvironmentMapBackground = toEnable;
+    }
+    else if (aFlag == "-twoside")
+    {
+      if (toPrint)
       {
-        aLightSpot->Attenuation (anAtten[0], anAtten[1]);
-        anAtten[0] = Atof (theArgVec[anArgIt]);
-        aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
+        theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
+        continue;
       }
-      else
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        --anArgIter;
       }
+      aParams.TwoSidedBsdfModels = toEnable;
     }
-    else if (anArgCase.IsEqual ("LINATTEN")
-          || anArgCase.IsEqual ("LINEARATTEN")
-          || anArgCase.IsEqual ("LINEARATTENUATION"))
+    else if (aFlag == "-shademodel"
+          || aFlag == "-shadingmodel"
+          || aFlag == "-shading")
     {
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        switch (aView->ShadingModel())
+        {
+          case V3d_COLOR:   theDI << "color ";   break;
+          case V3d_FLAT:    theDI << "flat ";    break;
+          case V3d_GOURAUD: theDI << "gouraud "; break;
+          case V3d_PHONG:   theDI << "phong ";   break;
+        }
+        continue;
       }
 
-      if (!aLightPos.IsNull())
+      if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+      }
+
+      TCollection_AsciiString aMode (theArgVec[anArgIter]);
+      aMode.LowerCase();
+      if (aMode == "color"
+       || aMode == "none")
+      {
+        aView->SetShadingModel (V3d_COLOR);
+      }
+      else if (aMode == "flat"
+            || aMode == "facet")
+      {
+        aView->SetShadingModel (V3d_FLAT);
+      }
+      else if (aMode == "gouraud"
+            || aMode == "vertex"
+            || aMode == "vert")
       {
-        aLightPos->Attenuation (anAtten[0], anAtten[1]);
-        anAtten[1] = Atof (theArgVec[anArgIt]);
-        aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
+        aView->SetShadingModel (V3d_GOURAUD);
       }
-      else if (!aLightSpot.IsNull())
+      else if (aMode == "phong"
+            || aMode == "fragment"
+            || aMode == "frag"
+            || aMode == "pixel")
       {
-        aLightSpot->Attenuation (anAtten[0], anAtten[1]);
-        anAtten[1] = Atof (theArgVec[anArgIt]);
-        aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
+        aView->SetShadingModel (V3d_PHONG);
       }
       else
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        std::cout << "Error: unknown shading model '" << aMode << "'\n";
         return 1;
       }
     }
-    else if (anArgCase.IsEqual ("EXP")
-          || anArgCase.IsEqual ("EXPONENT")
-          || anArgCase.IsEqual ("SPOTEXP")
-          || anArgCase.IsEqual ("SPOTEXPONENT"))
+    else if (aFlag == "-resolution")
     {
-      if (++anArgIt >= theArgsNb)
+      if (++anArgIter >= theArgNb)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
         return 1;
       }
 
-      if (!aLightSpot.IsNull())
+      TCollection_AsciiString aResolution (theArgVec[anArgIter]);
+      if (aResolution.IsIntegerValue())
       {
-        aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
+        aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
       }
       else
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
         return 1;
       }
     }
-    else if (anArgCase.IsEqual ("HEAD")
-          || anArgCase.IsEqual ("HEADLIGHT"))
+    else if (aFlag == "-rebuildglsl"
+          || aFlag == "-rebuild")
     {
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
+        continue;
       }
 
-      if (aLightAmb.IsNull()
-       && !aLightCurr.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+          && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
+        --anArgIter;
       }
-      else
+      aParams.RebuildRayTracingShaders = toEnable;
+    }
+    else
+    {
+      std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : VProgressiveMode
+//purpose  :
+//=======================================================================
+#if defined(_WIN32)
+static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
+                                          Standard_Integer  /*theNbArgs*/,
+                                          const char**      /*theArgs*/)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cerr << "Error: no active viewer!\n";
+    return 1;
+  }
+
+  std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
+
+  for (;;)
+  {
+    aView->Redraw();
+
+    Standard_Boolean toExit = Standard_False;
+
+    MSG aMsg;
+    while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
+    {
+      if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        toExit = Standard_True;
       }
+
+      TranslateMessage (&aMsg);
+      DispatchMessageW (&aMsg);
     }
-    else
+
+    if (toExit)
     {
-      std::cerr << "Warning: unknown argument '" << anArg << "'\n";
+      break;
     }
   }
 
-  addLight (aLightNew, isGlobal);
-  aViewer->UpdateLights();
+  return 0;
+}
+#endif
+
+//=======================================================================
+//function : VFrustumCulling
+//purpose  : enables/disables view volume's culling.
+//=======================================================================
+static int VFrustumCulling (Draw_Interpretor& theDI,
+                            Standard_Integer  theArgNb,
+                            const char**      theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
+    return 1;
+  }
+
+  if (theArgNb < 2)
+  {
+    theDI << (aView->IsCullingEnabled() ? "on" : "off");
+    return 0;
+  }
+  else if (theArgNb != 2)
+  {
+    std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
+    return 1;
+  }
+
+  TCollection_AsciiString aModeStr (theArgVec[1]);
+  aModeStr.LowerCase();
+  Standard_Boolean toEnable = 0;
+  if (aModeStr == "on")
+  {
+    toEnable = 1;
+  }
+  else if (aModeStr == "off")
+  {
+    toEnable = 0;
+  }
+  else
+  {
+    toEnable = Draw::Atoi (theArgVec[1]) != 0;
+  }
+
+  aView->SetFrustumCulling (toEnable);
+  aView->Redraw();
+  return 0;
+}
+
+//=======================================================================
+//function : VHighlightSelected
+//purpose  : 
+//=======================================================================
+static int VHighlightSelected (Draw_Interpretor& theDI,
+                               Standard_Integer  theArgNb,
+                               const char**      theArgVec)
+{
+  if (ViewerTest::GetAISContext().IsNull())
+  {
+    std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
+    return 1;
+  }
+
+  const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+
+  if (theArgNb < 2)
+  {
+    theDI << (aContext->ToHilightSelected() ? "on" : "off");
+    return 0;
+  }
+
+  if (theArgNb != 2)
+  {
+    std::cout  << theArgVec[0] << " error : wrong number of parameters."
+          << "Type 'help" << theArgVec[0] << "' for more information.";
+    return 1;
+  }
+
+  // Parse parameter
+  TCollection_AsciiString aMode (theArgVec[1]);
+  aMode.LowerCase();
+  Standard_Boolean toEnable = Standard_False;
+  if (aMode.IsEqual ("on"))
+  {
+    toEnable = Standard_True;
+  }
+  else if (aMode.IsEqual ("off"))
+  {
+    toEnable = Standard_False;
+  }
+  else
+  {
+    toEnable = Draw::Atoi (theArgVec[1]) != 0;
+  }
+
+  if (toEnable != aContext->ToHilightSelected())
+  {
+    aContext->SetToHilightSelected (toEnable);
+
+    // Move cursor to null position and  back to process updating of detection
+    // and highlighting of selected object immediatly.
+    Standard_Integer aPixX = 0;
+    Standard_Integer aPixY = 0;
+    const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
+
+    anEventManager->GetCurrentPosition (aPixX, aPixY);
+    anEventManager->MoveTo (0, 0);
+    anEventManager->MoveTo (aPixX, aPixY);
+  }
+
+  return 0;
+}
+
+//=======================================================================
+//function : VXRotate
+//purpose  :
+//=======================================================================
+static Standard_Integer VXRotate (Draw_Interpretor& di,
+                                   Standard_Integer argc,
+                                   const char ** argv)
+{
+  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
+  {
+    di << argv[0] << "ERROR : use 'vinit' command before \n";
+    return 1;
+  }
+  
+  if (argc != 3)
+  {
+    di << "ERROR : Usage : " << argv[0] << " name angle\n";
+    return 1;
+  }
+
+  TCollection_AsciiString aName (argv[1]);
+  Standard_Real anAngle = Draw::Atof (argv[2]);
+
+  // find object
+  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
+  Handle(AIS_InteractiveObject) anIObj;
+  if (!aMap.IsBound2 (aName) )
+  {
+    di << "Use 'vdisplay' before\n";
+    return 1;
+  }
+  else
+  {
+    anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
+
+    gp_Trsf aTransform;
+    aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
+    aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
+
+    aContext->SetLocation (anIObj, aTransform);
+    aContext->UpdateCurrentViewer();
+  }
+
+  return 0;
+}
+
+//===============================================================================================
+//class   : ViewerTest_AISManipulator
+//purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
+//===============================================================================================
+DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
+
+class ViewerTest_AISManipulator : public AIS_Manipulator
+{
+public:
+
+  ViewerTest_AISManipulator() : AIS_Manipulator()
+  {
+    GetMapOfAISManipulators().Add (this);
+  }
+
+  virtual ~ViewerTest_AISManipulator()
+  {
+    GetMapOfAISManipulators().Remove (this);
+  }
+
+  DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
+};
+
+IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
+IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
+
+//===============================================================================================
+//function : VManipulator
+//purpose  :
+//===============================================================================================
+static int VManipulator (Draw_Interpretor& theDi,
+                         Standard_Integer  theArgsNb,
+                         const char**      theArgVec)
+{
+  Handle(V3d_View)   aView   = ViewerTest::CurrentView();
+  Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
+  ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
+  if (aView.IsNull()
+   || aViewer.IsNull())
+  {
+    std::cerr << "No active viewer!\n";
+    return 1;
+  }
+
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
+  Standard_Integer anArgIter = 1;
+  for (; anArgIter < theArgsNb; ++anArgIter)
+  {
+    anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
+  }
 
-  return 0;
-}
+  ViewerTest_CmdParser aCmd;
+  aCmd.AddDescription ("Manages manipulator for interactive objects:");
+  aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
+  aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
+  aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
+  aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
+  aCmd.AddOption ("detach",         "...       - detach manipulator");
 
-//=======================================================================
-//function : VRenderParams
-//purpose  : Enables/disables rendering features
-//=======================================================================
+  aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
+  aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
+  aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
 
-static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
-                                       Standard_Integer  theArgNb,
-                                       const char**      theArgVec)
-{
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  aCmd.AddOption ("move",   "... x y z - move object");
+  aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
+  aCmd.AddOption ("scale",  "... factor - scale object");
+
+  aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
+  aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
+  aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
+  aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
+  aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
+  aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
+  aCmd.AddOption ("size",              "... size - set size of manipulator");
+  aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
+
+  aCmd.Parse (theArgsNb, theArgVec);
+
+  if (aCmd.HasOption ("help"))
   {
-    std::cerr << "Error: no active viewer!\n";
+    theDi.PrintHelp (theArgVec[0]);
+    return 0;
+  }
+
+  ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
+
+  TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
+
+  if (aName.IsEmpty())
+  {
+    std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
     return 1;
   }
 
-  Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
-  TCollection_AsciiString aCmdName (theArgVec[0]);
-  aCmdName.LowerCase();
-  if (aCmdName == "vraytrace")
+  // ----------------------------------
+  // detach existing manipulator object
+  // ----------------------------------
+
+  if (aCmd.HasOption ("detach"))
   {
-    if (theArgNb == 1)
+    if (!aMapAIS.IsBound2 (aName))
     {
-      theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
-      return 0;
+      std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
+      return 1;
     }
-    else if (theArgNb == 2)
+
+    Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
+    if (aManipulator.IsNull())
     {
-      TCollection_AsciiString aValue (theArgVec[1]);
-      aValue.LowerCase();
-      if (aValue == "on"
-       || aValue == "1")
-      {
-        aParams.Method = Graphic3d_RM_RAYTRACING;
-        aView->Redraw();
-        return 0;
-      }
-      else if (aValue == "off"
-            || aValue == "0")
-      {
-        aParams.Method = Graphic3d_RM_RASTERIZATION;
-        aView->Redraw();
-        return 0;
-      }
-      else
-      {
-        std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
-        return 1;
-      }
+      std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
+      return 1;
     }
-    else
+
+    aManipulator->Detach();
+    aMapAIS.UnBind2 (aName);
+    ViewerTest::GetAISContext()->Remove (aManipulator);
+
+    return 0;
+  }
+
+  // -----------------------------------------------
+  // find or create manipulator if it does not exist
+  // -----------------------------------------------
+
+  Handle(AIS_Manipulator) aManipulator;
+  if (!aMapAIS.IsBound2 (aName))
+  {
+    std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
+
+    aManipulator = new ViewerTest_AISManipulator();
+    aMapAIS.Bind (aManipulator, aName);
+  }
+  else
+  {
+    aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
+    if (aManipulator.IsNull())
     {
-      std::cout << "Error: wrong number of arguments\n";
+      std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
       return 1;
     }
   }
 
-  if (theArgNb < 2)
+  // -----------------------------------------
+  // change properties of manipulator instance
+  // -----------------------------------------
+
+  if (aCmd.HasOption ("autoActivate", 1, Standard_True))
   {
-    theDI << "renderMode:  ";
-    switch (aParams.Method)
+    aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
+  }
+  if (aCmd.HasOption ("followTranslation", 1, Standard_True))
+  {
+    aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
+  }
+  if (aCmd.HasOption ("followRotation", 1, Standard_True))
+  {
+    aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
+  }
+  if (aCmd.HasOption ("gap", 1, Standard_True))
+  {
+    aManipulator->SetGap (aCmd.ArgFloat ("gap"));
+  }
+  if (aCmd.HasOption ("part", 3, Standard_True))
+  {
+    Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
+    Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
+    Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
+    if (aMode < 1 || aMode > 3)
     {
-      case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
-      case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
+      std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
+      return 1;
     }
-    theDI << "\n";
-    theDI << "fsaa:         " << (aParams.IsAntialiasingEnabled      ? "on" : "off") << "\n";
-    theDI << "shadows:      " << (aParams.IsShadowEnabled            ? "on" : "off") << "\n";
-    theDI << "reflections:  " << (aParams.IsReflectionEnabled        ? "on" : "off") << "\n";
-    theDI << "rayDepth:     " <<  aParams.RaytracingDepth                            << "\n";
-    theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
-    theDI << "shadingModel: ";
-    switch (aView->ShadingModel())
+
+    aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
+  }
+  if (aCmd.HasOption ("pos", 3, Standard_True))
+  {
+    gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
+    gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
+    gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
+
+    aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
+  }
+  if (aCmd.HasOption ("size", 1, Standard_True))
+  {
+    aManipulator->SetSize (aCmd.ArgFloat ("size"));
+  }
+  if (aCmd.HasOption ("zoomable", 1, Standard_True))
+  {
+    aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
+
+    if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
     {
-      case V3d_COLOR:   theDI << "color";   break;
-      case V3d_FLAT:    theDI << "flat";    break;
-      case V3d_GOURAUD: theDI << "gouraud"; break;
-      case V3d_PHONG:   theDI << "phong";   break;
+      ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
+      ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
     }
-    theDI << "\n";
-    return 0;
   }
 
-  Standard_Boolean toPrint = Standard_False;
-  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
-  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+  // ---------------------------------------------------
+  // attach, detach or access manipulator from an object
+  // ---------------------------------------------------
+
+  if (aCmd.HasOption ("attach"))
   {
-    Standard_CString        anArg (theArgVec[anArgIter]);
-    TCollection_AsciiString aFlag (anArg);
-    aFlag.LowerCase();
-    if (anUpdateTool.parseRedrawMode (aFlag))
+    // Find an object and attach manipulator to it
+    if (!aCmd.HasOption ("attach", 1, Standard_True))
     {
-      continue;
+      return 1;
     }
-    else if (aFlag == "-echo"
-          || aFlag == "-print")
+
+    TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
+    if (!aMapAIS.IsBound2 (anObjName))
     {
-      toPrint = Standard_True;
-      anUpdateTool.Invalidate();
+      std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
+      return 1;
     }
-    else if (aFlag == "-mode"
-          || aFlag == "-rendermode"
-          || aFlag == "-render_mode")
+
+    Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
+    ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
+    for (; anIt.More(); anIt.Next())
     {
-      if (toPrint)
-      {
-        switch (aParams.Method)
-        {
-          case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
-          case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
-        }
-        continue;
-      }
-      else
+      if (anIt.Value()->IsAttached()
+       && anIt.Value()->Object() == anObject)
       {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
         return 1;
       }
     }
-    else if (aFlag == "-ray"
-          || aFlag == "-raytrace")
-    {
-      if (toPrint)
-      {
-        theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
-        continue;
-      }
 
-      aParams.Method = Graphic3d_RM_RAYTRACING;
+    AIS_Manipulator::OptionsForAttach anOptions;
+    if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
+    {
+      anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
     }
-    else if (aFlag == "-rast"
-          || aFlag == "-raster"
-          || aFlag == "-rasterization")
+    if (aCmd.HasOption ("adjustSize", 1, Standard_True))
     {
-      if (toPrint)
-      {
-        theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
-        continue;
-      }
-
-      aParams.Method = Graphic3d_RM_RASTERIZATION;
+      anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
     }
-    else if (aFlag == "-raydepth"
-          || aFlag == "-ray_depth")
+    if (aCmd.HasOption ("enableModes", 1, Standard_True))
     {
-      if (toPrint)
-      {
-        theDI << aParams.RaytracingDepth << " ";
-        continue;
-      }
-      else if (++anArgIter >= theArgNb)
-      {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
-        return 1;
-      }
+      anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
+    }
 
-      const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
-      if (aDepth < 1 || aDepth > 10)
-      {
-        std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
-        return 1;
-      }
-      else
-      {
-        aParams.RaytracingDepth = aDepth;
-      }
+    aManipulator->Attach (anObject, anOptions);
+  }
+
+  // --------------------------------------
+  // apply transformation using manipulator
+  // --------------------------------------
+
+  if (aCmd.HasOption ("startTransform", 2, Standard_True))
+  {
+    aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
+  }
+  if (aCmd.HasOption ("transform", 2, Standard_True))
+  {
+    aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
+  }
+  if (aCmd.HasOption ("stopTransform"))
+  {
+    Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
+
+    aManipulator->StopTransform (toApply);
+  }
+
+  gp_Trsf aT;
+  if (aCmd.HasOption ("move", 3, Standard_True))
+  {
+    aT.SetTranslationPart (aCmd.ArgVec ("move"));
+  }
+  if (aCmd.HasOption ("rotate", 7, Standard_True))
+  {
+    aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
+  }
+  if (aCmd.HasOption ("scale", 1))
+  {
+    aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
+  }
+
+  if (aT.Form() != gp_Identity)
+  {
+    aManipulator->Transform (aT);
+  }
+
+  ViewerTest::GetAISContext()->Redisplay (aManipulator);
+
+  return 0;
+}
+
+//===============================================================================================
+//function : VSelectionProperties
+//purpose  :
+//===============================================================================================
+static int VSelectionProperties (Draw_Interpretor& theDi,
+                                 Standard_Integer  theArgsNb,
+                                 const char**      theArgVec)
+{
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  if (aCtx.IsNull())
+  {
+    std::cerr << "No active viewer!\n";
+    return 1;
+  }
+
+  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 (aFlag == "-shad"
-          || aFlag == "-shadows")
+    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")
     {
-      if (toPrint)
-      {
-        theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
-        continue;
-      }
-
       Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      if (anArgIter + 1 < theArgsNb
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
       {
-        --anArgIter;
+        ++anArgIter;
       }
-      aParams.IsShadowEnabled = toEnable;
+      aCtx->SetAutoActivateSelection (toEnable);
     }
-    else if (aFlag == "-refl"
-          || aFlag == "-reflections")
+    else if (anArg == "-pixtol"
+          && anArgIter + 1 < theArgsNb)
     {
-      if (toPrint)
+      aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
+    }
+    else if ((anArg == "-mode"
+           || anArg == "-dispmode")
+          && anArgIter + 1 < theArgsNb)
+    {
+      if (aType == Prs3d_TypeOfHighlight_None)
       {
-        theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
-        continue;
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
 
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.IsReflectionEnabled = toEnable;
+      const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetDisplayMode (aDispMode);
+      toRedraw = Standard_True;
     }
-    else if (aFlag == "-fsaa")
+    else if (anArg == "-layer"
+          && anArgIter + 1 < theArgsNb)
     {
-      if (toPrint)
+      if (aType == Prs3d_TypeOfHighlight_None)
       {
-        theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
-        continue;
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
 
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
+      if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
       {
-        --anArgIter;
+        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;
+        }
       }
-      aParams.IsAntialiasingEnabled = toEnable;
+
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetZLayer (aNewLayer);
+      toRedraw = Standard_True;
     }
-    else if (aFlag == "-gleam")
+    else if (anArg == "-hicolor"
+          || anArg == "-selcolor"
+          || anArg == "-color")
     {
-      if (toPrint)
+      if (anArg.StartsWith ("-hi"))
       {
-        theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
-        continue;
+        aType = Prs3d_TypeOfHighlight_Dynamic;
       }
-
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      else if (anArg.StartsWith ("-sel"))
       {
-        --anArgIter;
+        aType = Prs3d_TypeOfHighlight_Selected;
       }
-      aParams.IsTransparentShadowEnabled = toEnable;
-    }
-    else if (aFlag == "-shademodel"
-          || aFlag == "-shadingmodel"
-          || aFlag == "-shading")
-    {
-      if (toPrint)
+      else if (aType == Prs3d_TypeOfHighlight_None)
       {
-        switch (aView->ShadingModel())
-        {
-          case V3d_COLOR:   theDI << "color ";   break;
-          case V3d_FLAT:    theDI << "flat ";    break;
-          case V3d_GOURAUD: theDI << "gouraud "; break;
-          case V3d_PHONG:   theDI << "phong ";   break;
-        }
-        continue;
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
 
-      if (++anArgIter >= theArgNb)
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           aColor);
+      if (aNbParsed == 0)
       {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
       }
+      anArgIter += aNbParsed;
 
-      TCollection_AsciiString aMode (theArgVec[anArgIter]);
-      aMode.LowerCase();
-      if (aMode == "color"
-       || aMode == "none")
+      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"))
       {
-        aView->SetShadingModel (V3d_COLOR);
+        aType = Prs3d_TypeOfHighlight_Dynamic;
       }
-      else if (aMode == "flat"
-            || aMode == "facet")
+      else if (anArg.StartsWith ("-sel"))
       {
-        aView->SetShadingModel (V3d_FLAT);
+        aType = Prs3d_TypeOfHighlight_Selected;
       }
-      else if (aMode == "gouraud"
-            || aMode == "vertex"
-            || aMode == "vert")
+      else if (aType == Prs3d_TypeOfHighlight_None)
       {
-        aView->SetShadingModel (V3d_GOURAUD);
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
-      else if (aMode == "phong"
-            || aMode == "fragment"
-            || aMode == "frag"
-            || aMode == "pixel")
+
+      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)
       {
-        aView->SetShadingModel (V3d_PHONG);
+        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
       {
-        std::cout << "Error: unknown shading model '" << aMode << "'\n";
-        return 1;
+        aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
       }
+      toRedraw = Standard_True;
     }
     else
     {
-      std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
-      return 1;
+      std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
     }
   }
-  return 0;
-}
-
-//=======================================================================
-//function : VFrustumCulling
-//purpose  : enables/disables view volume's culling.
-//=======================================================================
-static int VFrustumCulling (Draw_Interpretor& theDI,
-                            Standard_Integer  theArgNb,
-                            const char**      theArgVec)
-{
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
-  {
-    std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
-    return 1;
-  }
 
-  if (theArgNb < 2)
+  if (toPrint)
   {
-    theDI << (aView->IsCullingEnabled() ? "on" : "off");
-    return 0;
-  }
-  else if (theArgNb != 2)
-  {
-    std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
-    return 1;
+    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";
   }
 
-  TCollection_AsciiString aModeStr (theArgVec[1]);
-  aModeStr.LowerCase();
-  Standard_Boolean toEnable = 0;
-  if (aModeStr == "on")
-  {
-    toEnable = 1;
-  }
-  else if (aModeStr == "off")
-  {
-    toEnable = 0;
-  }
-  else
+  if (aCtx->NbSelected() != 0 && toRedraw)
   {
-    toEnable = Draw::Atoi (theArgVec[1]) != 0;
+    aCtx->HilightSelected (Standard_True);
   }
 
-  aView->SetFrustumCulling (toEnable);
-  aView->Redraw();
   return 0;
 }
 
-//=======================================================================
-//function : VHighlightSelected
-//purpose  : 
-//=======================================================================
-static int VHighlightSelected (Draw_Interpretor& theDI,
-                               Standard_Integer  theArgNb,
-                               const char**      theArgVec)
+//===============================================================================================
+//function : VDumpSelectionImage
+//purpose  :
+//===============================================================================================
+static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
+                                Standard_Integer  theArgsNb,
+                                const char**      theArgVec)
 {
-  if (ViewerTest::GetAISContext().IsNull())
+  if (theArgsNb < 2)
   {
-    std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
+    std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
     return 1;
   }
 
-  const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-
-  if (theArgNb < 2)
-  {
-    theDI << (aContext->ToHilightSelected() ? "on" : "off");
-    return 0;
-  }
-
-  if (theArgNb != 2)
+  const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
   {
-    std::cout  << theArgVec[0] << " error : wrong number of parameters."
-          << "Type 'help" << theArgVec[0] << "' for more information.";
+    std::cout << "Error: no active view.\n";
     return 1;
   }
 
-  // Parse parameter
-  TCollection_AsciiString aMode (theArgVec[1]);
-  aMode.LowerCase();
-  Standard_Boolean toEnable = Standard_False;
-  if (aMode.IsEqual ("on"))
-  {
-    toEnable = Standard_True;
-  }
-  else if (aMode.IsEqual ("off"))
-  {
-    toEnable = Standard_False;
-  }
-  else
-  {
-    toEnable = Draw::Atoi (theArgVec[1]) != 0;
-  }
-
-  if (toEnable != aContext->ToHilightSelected())
+  TCollection_AsciiString aFile;
+  StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
+  Image_PixMap::ImgFormat anImgFormat = Image_PixMap::ImgBGR;
+  Standard_Integer aPickedIndex = 1;
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
   {
-    aContext->SetToHilightSelected (toEnable);
+    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;
+      }
 
-    // Move cursor to null position and  back to process updating of detection
-    // and highlighting of selected object immediatly.
-    Standard_Integer aPixX = 0;
-    Standard_Integer aPixY = 0;
-    const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
+      TCollection_AsciiString aValue (theArgVec[anArgIter]);
+      aValue.LowerCase();
+      if (aValue == "depth"
+       || aValue == "normdepth"
+       || aValue == "normalizeddepth")
+      {
+        aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
+        anImgFormat = Image_PixMap::ImgGrayF;
+      }
+      if (aValue == "depthinverted"
+       || aValue == "normdepthinverted"
+       || aValue == "normalizeddepthinverted"
+       || aValue == "inverted")
+      {
+        aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
+        anImgFormat = Image_PixMap::ImgGrayF;
+      }
+      else if (aValue == "unnormdepth"
+            || aValue == "unnormalizeddepth")
+      {
+        aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
+        anImgFormat = Image_PixMap::ImgGrayF;
+      }
+      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;
+      }
 
-    anEventManager->GetCurrentPosition (aPixX, aPixY);
-    anEventManager->MoveTo (0, 0);
-    anEventManager->MoveTo (aPixX, aPixY);
+      aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
+    }
+    else if (aFile.IsEmpty())
+    {
+      aFile = theArgVec[anArgIter];
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
+      return 1;
+    }
   }
-
-  return 0;
-}
-
-//=======================================================================
-//function : VXRotate
-//purpose  :
-//=======================================================================
-static Standard_Integer VXRotate (Draw_Interpretor& di,
-                                   Standard_Integer argc,
-                                   const char ** argv)
-{
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if (aContext.IsNull())
+  if (aFile.IsEmpty())
   {
-    di << argv[0] << "ERROR : use 'vinit' command before " << "\n";
+    std::cout << "Syntax error: image file name is missing.\n";
     return 1;
   }
-  
-  if (argc != 3)
+
+  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))
   {
-    di << "ERROR : Usage : " << argv[0] << " name angle" << "\n";
+    std::cout << "Error: can't allocate image.\n";
     return 1;
   }
-
-  TCollection_AsciiString aName (argv[1]);
-  Standard_Real anAngle = Draw::Atof (argv[2]);
-
-  // find object
-  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
-  Handle(AIS_InteractiveObject) anIObj;
-  if (!aMap.IsBound2 (aName) )
+  if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
   {
-    di << "Use 'vdisplay' before" << "\n";
+    std::cout << "Error: can't generate selection image.\n";
     return 1;
   }
-  else
+  if (!aPixMap.Save (aFile))
   {
-    anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
-
-    gp_Trsf aTransform;
-    aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
-    aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
-
-    aContext->SetLocation (anIObj, aTransform);
-    aContext->UpdateCurrentViewer();
+    std::cout << "Error: can't save selection image.\n";
+    return 0;
   }
-
   return 0;
 }
 
@@ -7171,31 +10385,32 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "vhelp            : display help on the viewer commands",
     __FILE__,VHelp,group);
   theCommands.Add("vtop" ,
-    "vtop or <T>      : Top view" ,
+    "vtop or <T>      : Top view. Orientation +X+Y" ,
     __FILE__,VTop,group);
   theCommands.Add("vbottom" ,
-    "vbottom          : Bottom view" ,
+    "vbottom          : Bottom view. Orientation +X-Y" ,
     __FILE__,VBottom,group);
   theCommands.Add("vleft" ,
-    "vleft            : Left view" ,
+    "vleft            : Left view. Orientation -Y+Z" ,
     __FILE__,VLeft,group);
   theCommands.Add("vright" ,
-    "vright           : Right view" ,
+    "vright           : Right view. Orientation +Y+Z" ,
     __FILE__,VRight,group);
   theCommands.Add("vaxo" ,
-    " vaxo or <A>     : Axonometric view ",
+    " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
     __FILE__,VAxo,group);
   theCommands.Add("vfront" ,
-    "vfront           : Front view" ,
+    "vfront           : Front view. Orientation +X+Z" ,
     __FILE__,VFront,group);
   theCommands.Add("vback" ,
-    "vback            : Back view" ,
+    "vback            : Back view. Orientation -X+Z" ,
     __FILE__,VBack,group);
   theCommands.Add("vpick" ,
     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
     VPick,group);
-  theCommands.Add("vfit"    ,
-    "vfit or <F>         : vfit",
+  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",
     "vfitarea x1 y1 x2 y2"
@@ -7211,7 +10426,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "vrepaint        : vrepaint, force redraw",
     __FILE__,VRepaint,group);
   theCommands.Add("vclear",
-    "vclear          : vclear",
+    "vclear          : vclear"
+    "\n\t\t: remove all the object from the viewer",
     __FILE__,VClear,group);
   theCommands.Add("vsetbg",
     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
@@ -7228,16 +10444,28 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add("vsetcolorbg",
     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
     __FILE__,VSetColorBg,group);
+  theCommands.Add("vsetdefaultbg",
+    "vsetdefaultbg r g b\n"
+    "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
+    "\n\t\t: Set default viewer background fill color (flat/gradient).",
+    __FILE__,VSetDefaultBg,group);
   theCommands.Add("vscale",
     "vscale          : vscale X Y Z",
     __FILE__,VScale,group);
   theCommands.Add("vzbufftrihedron",
-    "vzbufftrihedron [center|left_lower|left_upper|right_lower|right_upper"
-    " textR=255 textG=255 textB=255 scale=0.1 wireframe|zbuffer]"
-    " : Displays a V3d_ZBUFFER'ed or V3d_WIREFRAME'd trihedron",
-    __FILE__,VTestZBuffTrihedron,group);
+            "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
+    "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
+    "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
+    "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
+    "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
+    "\n\t\t: Displays a trihedron",
+    __FILE__,VZBuffTrihedron,group);
   theCommands.Add("vrotate",
-    "vrotate         : vrotate AX AY AZ [X Y Z]",
+    "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
+    "\n                : Option -mouseStart starts rotation according to the mouse position"
+    "\n                : Option -mouseMove continues rotation with angle computed"
+    "\n                : from last and new mouse position."
+    "\n                : vrotate AX AY AZ [X Y Z]",
     __FILE__,VRotate,group);
   theCommands.Add("vzoom",
     "vzoom           : vzoom coef",
@@ -7251,38 +10479,80 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " : notice that EMF format requires patched gl2ps",
     __FILE__,VExport,group);
   theCommands.Add("vcolorscale",
-    "vcolorscale     : vcolorscale [RangeMin = 0 RangeMax = 100 Intervals = 10 HeightFont = 16 Position = 2 X = 0 Y = 0]: draw color scale",
-    __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 : 1/0 (display/erase) [Xname Yname Zname [Font [isMultibyte]]]",
+    "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
+    "\t[-namefont Name] [-valuesfont Name]\n"
+    "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
+    "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
+    "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
+    "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
+    "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
+    "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
+    "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
+    "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
+    "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
+    "\t[-drawgrid on/off] [-drawaxes on/off]\n"
+    " - Displays or erases graduated trihedron"
+    " - xname, yname, zname - names of axes, default: X, Y, Z\n"
+    " - namefont - font of axes names. Default: Arial\n"
+    " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
+    " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
+    " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
+    " - valuesfont - font of axes values. Default: Arial\n"
+    " - xcolor, ycolor, zcolor - color of axis and values\n"
+    " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
+    " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
     __FILE__,VGraduatedTrihedron,group);
-  theCommands.Add("vprintview" ,
-    "vprintview : width height filename [algo=0] [tile_width tile_height] : Test print algorithm: algo = 0 - stretch, algo = 1 - tile",
-    __FILE__,VPrintView,group);
+  theCommands.Add("vtile" ,
+            "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
+    "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
+    "\n\t\t:  -totalSize the size of virtual bigger viewport"
+    "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
+    "\n\t\t:  -lowerLeft tile offset as lower left corner"
+    "\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"
-    " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    disables given setting for the z layer\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("voverlaytext",
-    "voverlaytext : text x y [height] [font_name] [text_color: R G B] [display_type] [background_color: R G B]"
-    " : height - pixel height of the text (default=10.0)"
-    " : font_name - name of font (default=courier)"
-    " : text_color - three values: RedColor GreenColor BlueColor (default = 255.0 255.0 255.0) "
-    " : display_type = {normal/subtitle/decal/blend}, (default=normal) "
-    " : background_color - three values: RedColor GreenColor BlueColor (default = 255.0 255.0 255.0), the parameter is defined for subtitle and decal display types ",
-    __FILE__,VOverlayText,group);
   theCommands.Add("vlayerline",
     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
     __FILE__,VLayerLine,group);
@@ -7291,31 +10561,85 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " : Mode - rectangular or circular"
     " : Type - lines or points",
     __FILE__, VGrid, group);
+  theCommands.Add ("vpriviledgedplane",
+    "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
+    "\n\t\t:   Ox, Oy, Oz - plane origin"
+    "\n\t\t:   Nx, Ny, Nz - plane normal direction"
+    "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
+    "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
+    __FILE__, VPriviledgedPlane, group);
+  theCommands.Add ("vconvert",
+    "vconvert v [Mode={window|view}]"
+    "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
+    "\n\t\t: vconvert x y z [Mode={window|grid}]"
+    "\n\t\t:   window - convert to window coordinates, pixels"
+    "\n\t\t:   view   - convert to view projection plane"
+    "\n\t\t:   grid   - convert to model coordinates, given on grid"
+    "\n\t\t:   ray    - convert projection ray to model coordiantes"
+    "\n\t\t: - vconvert v window : convert view to window;"
+    "\n\t\t: - vconvert v view   : convert window to view;"
+    "\n\t\t: - vconvert x y window : convert view to window;"
+    "\n\t\t: - vconvert x y view : convert window to view;"
+    "\n\t\t: - vconvert x y : convert window to model;"
+    "\n\t\t: - vconvert x y grid : convert window to model using grid;"
+    "\n\t\t: - vconvert x y ray : convert window projection line to model;"
+    "\n\t\t: - vconvert x y z window : convert model to window;"
+    "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
+    "\n\t\t: Converts the given coordinates to window/view/model space.",
+    __FILE__, VConvert, group);
   theCommands.Add ("vfps",
     "vfps [framesNb=100] : estimate average frame rate for active view",
     __FILE__, VFps, group);
   theCommands.Add ("vgldebug",
-    "vgldebug [{0|1}] : request debug GL context, should be called before vinit\n"
-    "                : this function is implemented only for Windows\n"
-    "                : GL_ARB_debug_output extension should be exported by OpenGL driver!",
+            "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
+    "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
+    "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
+    "\n\t\t: Debug context can be requested only on Windows"
+    "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
+    "\n\t\t:  -sync     - request synchronized debug GL context"
+    "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
+    "\n\t\t:              which are suppressed by default,"
+    "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
+    "\n\t\t:              which are suppressed by default",
     __FILE__, VGlDebug, group);
   theCommands.Add ("vvbo",
     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
     __FILE__, VVbo, group);
   theCommands.Add ("vstereo",
-    "\nvstereo [{0|1}] : turn stereo usage On/Off; affects only newly displayed objects",
+            "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
+    "\n\t\t:         [-anaglyph Filter]"
+    "\n\t\t: Control stereo output mode. Available modes for -mode:"
+    "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
+    "\n\t\t:                     requires driver support."
+    "\n\t\t:                     Should be called BEFORE vinit!"
+    "\n\t\t:  anaglyph         - Anaglyph glasses"
+    "\n\t\t:  rowInterlaced    - row-interlaced display"
+    "\n\t\t:  columnInterlaced - column-interlaced display"
+    "\n\t\t:  chessBoard       - chess-board output"
+    "\n\t\t:  sideBySide       - horizontal pair"
+    "\n\t\t:  overUnder        - vertical   pair"
+    "\n\t\t: Available Anaglyph filters for -anaglyph:"
+    "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
+    "\n\t\t:  greenMagentaSimple",
     __FILE__, VStereo, group);
   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:       [-quadBuffer {0|1}] [-stereo {0|1}]"
     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
     "\n\t\t: Modify particular graphic driver options:"
     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
     "\n\t\t:             built-in GLSL programs"
+    "\n\t\t:            (requires compatible profile)"
     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
     "\n\t\t:             arrays to GPU memory)"
     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
-    "\n\t\t:  softMode - use software OpenGL implementation,"
-    "\n\t\t:             should be set BEFORE viewer creation"
+    "\n\t\t:  vsync    - switch VSync on or off"
+    "\n\t\t: Context creation options:"
+    "\n\t\t:  softMode          - software OpenGL implementation"
+    "\n\t\t:  compatibleProfile - backward-compatible profile"
+    "\n\t\t:  quadbuffer        - QuadBuffer"
     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
     "\n\t\t: rendering paths producing the same visual result when"
     "\n\t\t: possible."
@@ -7333,44 +10657,95 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
     __FILE__, VDiffImage, group);
   theCommands.Add ("vselect",
-    "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [shift_selection = 0|1]\n"
+    "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
     "- emulates different types of selection:\n"
     "- 1) single click selection\n"
     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
-    "- 4) any of these selections with shift button pressed",
+    "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
+    "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
+    "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
+    " (partial inclusion - overlap - is not allowed by default)\n"
+    "- 5) any of these selections with shift button pressed",
     __FILE__, VSelect, group);
   theCommands.Add ("vmoveto",
     "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",
                __FILE__, VChangeSelected, group);
-  theCommands.Add("vzclipping",
-    "vzclipping [mode] [depth width]\n"
-    "- mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]\n"
-    "- gets or sets ZClipping mode, width and depth",
-    __FILE__,VZClipping,group);
   theCommands.Add ("vnbselected",
-    "vnbselected", __FILE__, VNbSelected, group);
+    "vnbselected"
+    "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
   theCommands.Add ("vcamera",
               "vcamera [-ortho] [-projtype]"
       "\n\t\t:         [-persp]"
@@ -7405,9 +10780,6 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "   vzrange                - without parameters shows current values\n"
     "   vzrange [znear] [zfar] - applies provided values to view",
     __FILE__,VZRange, group);
-  theCommands.Add("vantialiasing",
-    "vantialiasing 1|0",
-    __FILE__,VAntialiasing,group);
   theCommands.Add ("vpurgedisplay",
     "vpurgedisplay"
     "- removes structures which don't belong to objects displayed in neutral point",
@@ -7452,34 +10824,43 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "If shapes are not given HLR algoithm of given type is applied"
     " to all shapes in the view\n",
     __FILE__,VHLRType,group);
-  theCommands.Add("vclipplane", "vclipplane usage: \n"
-    "  maxplanes <view_name> - get plane limit for view.\n"
-    "  create <plane_name> - create new plane.\n"
-    "  delete <plane_name> - delete plane.\n"
-    "  clone <source_plane> <plane_name> - clone the plane definition.\n"
-    "  set/unset <plane_name> object <object list> - set/unset plane for IO.\n"
-    "  set/unset <plane_name> view <view list> - set/unset plane for view.\n"
-    "  change <plane_name> on/off - turn clipping on/off.\n"
-    "  change <plane_name> equation <a> <b> <c> <d> - change plane equation.\n"
-    "  change <plane_name> capping on/off - turn capping on/off.\n"
-    "  change <plane_name> capping color <r> <g> <b> - set color.\n"
-    "  change <plane name> capping texname <texture> - set texture.\n"
-    "  change <plane_name> capping texscale <sx> <sy> - set tex scale.\n"
-    "  change <plane_name> capping texorigin <tx> <ty> - set tex origin.\n"
-    "  change <plane_name> capping texrotate <angle> - set tex rotation.\n"
-    "  change <plane_name> capping hatch on/off/<id> - set hatching mask.\n"
-    "  please use VSetTextureMode command to enable texture rendering in view.\n"
-    , __FILE__, VClipPlane, group);
-  theCommands.Add("vsettexturemode", "vsettexturemode view_name mode \n"
-    "  mode can be:\n"
-    "  0 - no textures enabled in view.\n"
-    "  1 - only environment textures enabled.\n"
-    "  2 - all textures enabled.\n"
-    "  this command sets texture details mode for the specified view.\n"
-    , __FILE__, VSetTextureMode, group);
+  theCommands.Add("vclipplane",
+              "vclipplane planeName [{0|1}]"
+      "\n\t\t:   [-equation A B C D]"
+      "\n\t\t:   [-set|-unset [objects|views]]"
+      "\n\t\t:   [-maxPlanes]"
+      "\n\t\t:   [-capping {0|1}]"
+      "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
+      "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
+      "\n\t\t:       [-texRotate Angle]"
+      "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
+      "\n\t\t:       [-useObjShader {0|1}]"
+      "\n\t\t: Clipping planes management:"
+      "\n\t\t:   -maxPlanes   print plane limit for view"
+      "\n\t\t:   -delete      delete plane with given name"
+      "\n\t\t:   {off|on|0|1} turn clipping on/off"
+      "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
+      "\n\t\t:                applied to active View when list is omitted"
+      "\n\t\t:   -equation A B C D change plane equation"
+      "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
+      "\n\t\t: Capping options:"
+      "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
+      "\n\t\t:   -color R G B          set capping color"
+      "\n\t\t:   -texName Texture      set capping texture"
+      "\n\t\t:   -texScale SX SY       set capping tex scale"
+      "\n\t\t:   -texOrigin TX TY      set capping tex origin"
+      "\n\t\t:   -texRotate Angle      set capping tex rotation"
+      "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
+      "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
+      "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
+      "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
+      __FILE__, VClipPlane, group);
   theCommands.Add("vdefaults",
-    "vdefaults [absDefl=value] [devCoeff=value] [angDefl=value]",
-    __FILE__, VDefaults, group);
+               "vdefaults [-absDefl value]"
+       "\n\t\t:           [-devCoeff value]"
+       "\n\t\t:           [-angDefl value]"
+       "\n\t\t:           [-autoTriang {off/on | 0/1}]"
+    , __FILE__, VDefaults, group);
   theCommands.Add("vlight",
     "tool to manage light sources, without arguments shows list of lights."
     "\n    Main commands: "
@@ -7493,6 +10874,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
     "\n        color colorName"
     "\n        {head}light 0|1"
+    "\n        {sm}oothness value"
+    "\n        {int}ensity value"
     "\n        {constAtten}uation value"
     "\n        {linearAtten}uation value"
     "\n        angle angleDeg"
@@ -7503,21 +10886,30 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     __FILE__, VLight, group);
   theCommands.Add("vraytrace",
             "vraytrace [0|1]"
-    "\n\t\t: Turn on/off raytracing renderer."
+    "\n\t\t: Turns on/off ray-tracing renderer."
     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
     __FILE__, VRenderParams, group);
   theCommands.Add("vrenderparams",
     "\n    Manages rendering parameters: "
-    "\n      '-rayTrace'             Enables  GPU ray-tracing"
     "\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      '-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      '-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    Unlike vcaps, these parameters dramatically change visual properties."
     "\n    Command is intended to control presentation quality depending on"
     "\n    hardware capabilities and performance.",
@@ -7537,4 +10929,58 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "vxrotate",
     __FILE__,VXRotate,group);
 
+    theCommands.Add("vmanipulator",
+      "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
+      "\n    tool to create and manage AIS manipulators."
+      "\n    Options: "
+      "\n      '-attach AISObject'                 attach manipulator to AISObject"
+      "\n      '-adjustPosition {0|1}'             adjust position when attaching"
+      "\n      '-adjustSize     {0|1}'             adjust size when attaching"
+      "\n      '-enableModes    {0|1}'             enable modes when attaching"
+      "\n      '-detach'                           detach manipulator"
+      "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
+      "\n      '-transform      mouse_x mouse_y' - invoke transformation"
+      "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
+      "\n      '-move x y z'                     - move attached object"
+      "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
+      "\n      '-scale factor'                   - scale attached object"
+      "\n      '-autoActivate      {0|1}'        - set activation on detection"
+      "\n      '-followTranslation {0|1}'        - set following translation transform"
+      "\n      '-followRotation    {0|1}'        - set following rotation transform"
+      "\n      '-gap value'                      - set gap between sub-parts"
+      "\n      '-part axis mode    {0|1}'        - set visual part"
+      "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
+      "\n      '-size value'                     - set size of manipulator"
+      "\n      '-zoomable {0|1}'                 - set zoom persistence",
+    __FILE__, VManipulator, group);
+
+  theCommands.Add("vselprops",
+    "\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    -pixTol    value        : sets up pixel tolerance"
+    "\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",
+    __FILE__, VProgressiveMode, group);
+#endif
 }