0028110: Configuration - specify Unicode charset instead of multibyte in project...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
index 9642900..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_InteractiveObject.hxx>
 #include <AIS_ListOfInteractive.hxx>
@@ -35,6 +41,7 @@
 #include <ViewerTest_EventManager.hxx>
 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
+#include <ViewerTest_CmdParser.hxx>
 #include <V3d_AmbientLight.hxx>
 #include <V3d_DirectionalLight.hxx>
 #include <V3d_PositionalLight.hxx>
@@ -46,7 +53,6 @@
 #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>
 #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
@@ -169,8 +170,6 @@ 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
@@ -186,13 +185,46 @@ static struct
 //==============================================================================
 
 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;
+}
 
 //==============================================================================
 
@@ -215,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;
@@ -419,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
@@ -531,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;
   }
@@ -620,8 +661,7 @@ 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());
+    a3DViewer = new V3d_Viewer(aGraphicDriver);
     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
                                            ViewerTest_DefaultBackground.GradientColor2,
@@ -677,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)
@@ -935,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 =
@@ -1105,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());
@@ -1281,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
@@ -1293,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";
               }
@@ -1451,24 +1491,6 @@ void VT_ProcessKeyPress (const char* buf_ret)
       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());
@@ -1552,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;
@@ -1627,41 +1655,6 @@ void VT_ProcessButton3Release()
   }
 }
 
-//==============================================================================
-//function : ProcessZClipMotion
-//purpose  : Zoom
-//==============================================================================
-
-void ProcessZClipMotion()
-{
-  Handle(V3d_View)  a3DView = ViewerTest::CurrentView();
-  if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
-
-    //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 aDx = a3DView->Convert(X_Motion - X_ButtonPress);
-
-    // Front = Depth + width/2.
-    Standard_Real aDepth = 0.5;
-    Standard_Real aWidth = 0.1;
-    a3DView->ZClipping(aDepth,aWidth);
-
-    aDepth += aDx;
-
-    //printf("dx %lf Depth %lf Width %lf\n", dx, D, W);
-
-    a3DView->SetZClippingDepth(aDepth);
-
-    a3DView->Redraw();
-
-    X_ButtonPress = X_Motion;
-    Y_ButtonPress = Y_Motion;
-  }
-}
-
 //==============================================================================
 //function : ProcessControlButton1Motion
 //purpose  : Zoom
@@ -1733,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;
   }
 
@@ -1827,39 +1820,39 @@ 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;
 }
@@ -1899,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 );
@@ -1968,7 +2007,7 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
   if (aView.IsNull())
   {
-    return DefWindowProc( hwnd, Msg, wParam, lParam );
+    return DefWindowProcW (hwnd, Msg, wParam, lParam);
   }
 
     PAINTSTRUCT    ps;
@@ -2051,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)
@@ -2099,64 +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;
 }
 
-
-
-
 //==============================================================================
 //function : ViewerMainLoop
 //purpose  : Get a Event on the view and dispatch it
@@ -2177,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);
       }
     }
 
@@ -2297,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();
@@ -2350,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
           {
@@ -2371,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();
@@ -2496,33 +2506,42 @@ static void OSWindowSetup()
 
 //==============================================================================
 //function : VFit
-
-//purpose  : Fitall, no DRAW arguments
-//Draw arg : No args
+//purpose  :
 //==============================================================================
 
-static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv)
+static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
 {
-  if (theArgc > 2)
+  const Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
   {
-    std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl;
+    std::cout << "Error: no active viewer!\n";
+    return 1;
   }
 
-  const Handle(V3d_View) aView = ViewerTest::CurrentView();
-
-  if (theArgc == 2)
+  Standard_Boolean toFit = Standard_True;
+  ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    TCollection_AsciiString anArg (theArgv[1]);
+    TCollection_AsciiString anArg (theArgv[anArgIter]);
     anArg.LowerCase();
-    if (anArg == "-selected")
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      ViewerTest::GetAISContext()->FitSelected (aView);
-      return 0;
+      continue;
+    }
+    else if (anArg == "-selected")
+    {
+      ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
+      toFit = Standard_False;
+    }
+    else
+    {
+      std::cout << "Syntax error at '" << anArg << "'\n";
     }
   }
-  if (aView.IsNull() == Standard_False) {
 
-    aView->FitAll();
+  if (toFit)
+  {
+    aView->FitAll (0.01, Standard_False);
   }
   return 0;
 }
@@ -2657,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;
 }
 
@@ -2676,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;
   }
 
@@ -2699,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;
     }
   }
@@ -2719,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;
   }
 
@@ -2739,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();
@@ -2755,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;
   }
 
@@ -2784,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;
     }
 
@@ -2807,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;
   }
 
@@ -2824,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;
     }
 
@@ -2847,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;
   }
 
@@ -2936,7 +2955,7 @@ static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv
   if ( V3dView.IsNull() ) return 1;
 
   if ( argc != 4 ) {
-    di << argv[0] << "Invalid number of arguments" << "\n";
+    di << argv[0] << "Invalid number of arguments\n";
     return 1;
   }
   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
@@ -3267,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;
   }
 }
@@ -3291,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;
   }
 }
@@ -3390,6 +3409,7 @@ static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** arg
     return 1;
   }
 
+  Standard_DISABLE_DEPRECATION_WARNINGS
   try
   {
     if (!V3dView->Export (argv[1], anExpFormat))
@@ -3402,41 +3422,10 @@ 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
-//==============================================================================
-
-static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
-                                    const TCollection_AsciiString& theGreen,
-                                    const TCollection_AsciiString& theBlue,
-                                                    Standard_Real& theRedValue,
-                                                    Standard_Real& theGreenValue,
-                                                    Standard_Real& theBlueValue)
-{
-  if (!theRed.IsRealValue()
-   || !theGreen.IsRealValue()
-   || !theBlue.IsRealValue())
-  {
-    std::cout << "Error: RGB color values should be real!\n";
-    return Standard_True;
-  }
-  theRedValue = theRed    .RealValue();
-  theGreenValue = theGreen.RealValue();
-  theBlueValue = theBlue  .RealValue();
-  if (theRedValue < 0.0 || theRedValue > 1.0
-   || theGreenValue < 0.0 || theGreenValue > 1.0
-   || theBlueValue < 0.0 || theBlueValue > 1.0)
-  {
-    std::cout << "Error: RGB color values should be within range 0..1!\n";
-    return Standard_True;
-  }
-  return Standard_False;
-}
-
 static int VColorScale (Draw_Interpretor& theDI,
                         Standard_Integer  theArgNb,
                         const char**      theArgVec)
@@ -3454,56 +3443,35 @@ static int VColorScale (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Handle(AIS_ColorScale) aCS;
-  // find object
-  Handle(AIS_InteractiveObject) anIObj;
+  Handle(AIS_ColorScale) aColorScale;
   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
   {
-    aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
-    if (aCS.IsNull())
+    // find existing object
+    aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
+    if (aColorScale.IsNull())
     {
       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
       return 1;
     }
   }
-  else
-  {
-    aCS = new AIS_ColorScale();
-    GetMapOfAIS().Bind (aCS,theArgVec[1]);
-  }
-
-  if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
-  {
-    aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
-  }
-  if (aCS->GetTransformPersistenceMode() != Graphic3d_TMF_2d)
-  {
-    aCS->SetTransformPersistence (Graphic3d_TMF_2d, gp_Pnt (-1,-1,0));
-  }
-
-  Standard_Real                   aMinRange    = aCS->GetMin();
-  Standard_Real                   aMaxRange    = aCS->GetMax();
-  Standard_Integer                aWidth       = aCS->GetWidth();
-  Standard_Integer                aHeight      = aCS->GetHeight();
-  Standard_Integer                aNbIntervals = aCS->GetNumberOfIntervals();
-  Standard_Integer                aTextHeight  = aCS->GetTextHeight();
-  Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition();
-  Standard_Integer                aPosX = aCS->GetXPosition();
-  Standard_Integer                aPosY = aCS->GetYPosition();
-
-  ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
 
   if (theArgNb <= 2)
   {
+    if (aColorScale.IsNull())
+    {
+      std::cout << "Syntax error: colorscale with a given name does not exist.\n";
+      return 1;
+    }
+
     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
-          << "Min range: " << aMinRange << "\n"
-          << "Max range: " << aMaxRange << "\n"
-          << "Number of intervals: " << aNbIntervals << "\n"
-          << "Text height: " << aTextHeight << "\n"
-          << "Color scale position: " << aPosX <<" "<< aPosY<< "\n"
-          << "Color scale title: " << aCS->GetTitle() << "\n"
+          << "Min range: "            << aColorScale->GetMin() << "\n"
+          << "Max range: "            << aColorScale->GetMax() << "\n"
+          << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
+          << "Text height: "          << aColorScale->GetTextHeight() << "\n"
+          << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
+          << "Color scale title: "    << aColorScale->GetTitle() << "\n"
           << "Label position: ";
-    switch (aLabPosition)
+    switch (aColorScale->GetLabelPosition())
     {
       case Aspect_TOCSP_NONE:
         theDI << "None\n";
@@ -3521,6 +3489,14 @@ static int VColorScale (Draw_Interpretor& theDI,
     return 0;
   }
 
+  if (aColorScale.IsNull())
+  {
+    aColorScale = new AIS_ColorScale();
+    aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
+    aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
+  }
+
+  ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
   {
     Standard_CString        anArg = theArgVec[anArgIter];
@@ -3538,28 +3514,23 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
-      TCollection_AsciiString anArg2 (theArgVec[++anArgIter]);
-      TCollection_AsciiString anArg3 (theArgVec[++anArgIter]);
-      if (!anArg1.IsRealValue())
+      const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
+      const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
+      const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
+      if (!aRangeMin.IsRealValue()
+       || !aRangeMax.IsRealValue())
       {
-        std::cout << "Error: the minRange value should be real!\n";
+        std::cout << "Error: the range values should be real!\n";
         return 1;
       }
-      else if (!anArg2.IsRealValue())
-      {
-        std::cout << "Error: the maxRange value should be real!\n";
-        return 1;
-      }
-      else if (!anArg3.IsIntegerValue())
+      else if (!aNbIntervals.IsIntegerValue())
       {
         std::cout << "Error: the number of intervals should be integer!\n";
         return 1;
       }
 
-      aMinRange    = anArg1.RealValue();
-      aMaxRange    = anArg2.RealValue();
-      aNbIntervals = anArg3.IntegerValue();
+      aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
+      aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
     }
     else if (aFlag == "-font")
     {
@@ -3575,7 +3546,7 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      aTextHeight = aFontArg.IntegerValue();
+      aColorScale->SetTextHeight (aFontArg.IntegerValue());
       anArgIter += 1;
     }
     else if (aFlag == "-textpos")
@@ -3585,8 +3556,10 @@ static int VColorScale (Draw_Interpretor& theDI,
         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
         return 1;
       }
+
       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
       aTextPosArg.LowerCase();
+      Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
       if (aTextPosArg == "none")
       {
         aLabPosition = Aspect_TOCSP_NONE;
@@ -3608,6 +3581,7 @@ static int VColorScale (Draw_Interpretor& theDI,
         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
         return 1;
       }
+      aColorScale->SetLabelPosition (aLabPosition);
     }
     else if (aFlag == "-logarithmic"
           || aFlag == "-log")
@@ -3617,13 +3591,71 @@ static int VColorScale (Draw_Interpretor& theDI,
         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
         return 1;
       }
+
       Standard_Boolean IsLog;
       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
       {
         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
         return 1;
       }
-      aCS->SetLogarithmic (IsLog);
+      aColorScale->SetLogarithmic (IsLog);
+    }
+    else if (aFlag == "-huerange"
+          || aFlag == "-hue")
+    {
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      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;
+      }
+
+      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")
     {
@@ -3633,20 +3665,20 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString aX (theArgVec[++anArgIter]);
-      TCollection_AsciiString aY (theArgVec[++anArgIter]);
-      if (!aX.IsIntegerValue()
-       || !aY.IsIntegerValue())
+      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;
       }
 
-      aPosX = aX.IntegerValue();
-      aPosY = aY.IntegerValue();
+      aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
     }
     else if (aFlag == "-width"
-          || aFlag == "-w")
+          || aFlag == "-w"
+          || aFlag == "-breadth")
     {
       if (anArgIter + 1 >= theArgNb)
       {
@@ -3654,14 +3686,13 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString aW (theArgVec[++anArgIter]);
-      if (!aW.IsIntegerValue())
+      const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
+      if (!aBreadth.IsIntegerValue())
       {
         std::cout << "Error: a width should be an integer value!\n";
         return 1;
       }
-
-      aWidth = aW.IntegerValue();
+      aColorScale->SetBreadth (aBreadth.IntegerValue());
     }
     else if (aFlag == "-height"
           || aFlag == "-h")
@@ -3672,76 +3703,56 @@ static int VColorScale (Draw_Interpretor& theDI,
         return 1;
       }
 
-      TCollection_AsciiString aH (theArgVec[++anArgIter]);
-      if (!aH.IsIntegerValue())
+      const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
+      if (!aHeight.IsIntegerValue())
       {
         std::cout << "Error: a width should be an integer value!\n";
         return 1;
       }
-
-      aHeight = aH.IntegerValue();
+      aColorScale->SetHeight (aHeight.IntegerValue());
     }
     else if (aFlag == "-color")
     {
-      if (aCS->GetColorType() != Aspect_TOCSD_USER)
+      if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
       {
         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
         return 1;
       }
-
-      Quantity_NameOfColor aColorName;
-      if (anArgIter + 4 >= theArgNb)
+      else if (anArgIter + 2 >= theArgNb)
       {
-        if (anArgIter + 2 >= theArgNb)
-        {
-          std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
-          return 1;
-        }
-        else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
-        {
-          std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n";
-          return 1;
-        }
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
       }
 
-      TCollection_AsciiString anInd (theArgVec[anArgIter + 1]);
+      const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
       if (!anInd.IsIntegerValue())
       {
         std::cout << "Error: Index value should be integer!\n";
         return 1;
       }
-
-      Standard_Integer anIndex = anInd.IntegerValue();
-      if (anIndex < 0
-       || anIndex > aNbIntervals - 1)
+      const Standard_Integer anIndex = anInd.IntegerValue();
+      if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
       {
-        std::cout << "Error: Index value should be within range 0..." << (aNbIntervals - 1) <<"!\n";
+        std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
         return 1;
       }
 
-      if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
-      {
-        aCS->SetColor    (Quantity_Color (aColorName), anIndex);
-        aCS->SetColorType (Aspect_TOCSD_USER);
-        anArgIter += 2;
-        continue;
-      }
-
-      TCollection_AsciiString aRed   (theArgVec[anArgIter + 2]);
-      TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]);
-      TCollection_AsciiString aBlue  (theArgVec[anArgIter + 4]);
-      Standard_Real aRedValue,aGreenValue, aBlueValue;
-      if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
+                                                           theArgVec + (anArgIter + 1),
+                                                           aColor);
+      if (aNbParsed == 0)
       {
+        std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
         return 1;
       }
-      aCS->SetColor     (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex);
-      aCS->SetColorType (Aspect_TOCSD_USER);
-      anArgIter += 4;
+      aColorScale->SetIntervalColor (aColor, anIndex);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
+      anArgIter += aNbParsed;
     }
     else if (aFlag == "-label")
     {
-      if (aCS->GetColorType() != Aspect_TOCSD_USER)
+      if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
       {
         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
         return 1;
@@ -3753,91 +3764,115 @@ static int VColorScale (Draw_Interpretor& theDI,
       }
 
       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
-      if (anIndex < 0
-       || anIndex > aNbIntervals)
+      if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
       {
-        std::cout << "Error: Index value should be within range 0..." << aNbIntervals <<"!\n";
+        std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
         return 1;
       }
 
       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
-      aCS->SetLabel     (aText, anIndex);
-      aCS->SetLabelType (Aspect_TOCSD_USER);
+      aColorScale->SetLabel     (aText, anIndex);
+      aColorScale->SetLabelType (Aspect_TOCSD_USER);
       anArgIter += 2;
     }
-    else if (aFlag == "-colors")
+    else if (aFlag == "-labelat"
+          || aFlag == "-labat"
+          || aFlag == "-labelatborder"
+          || aFlag == "-labatborder"
+          || aFlag == "-labelatcenter"
+          || aFlag == "-labatcenter")
     {
-      Aspect_SequenceOfColor aSeq;
-      if (anArgIter + aNbIntervals + 1 > theArgNb)
-      {
-        std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
-                  << aNbIntervals << " intervals\n";
-        return 1;
-      }
-
-      Standard_Integer aColorIter = anArgIter + 1;
-      while (aColorIter < theArgNb)
+      Standard_Boolean toEnable = Standard_True;
+      if (aFlag == "-labelat"
+       || aFlag == "-labat")
       {
-        if (theArgVec[aColorIter][0] == '-')
+        Standard_Integer aLabAtBorder = -1;
+        if (++anArgIter >= theArgNb)
         {
-          break;
-        }
-
-        else if (theArgVec[aColorIter][0] >= 97
-              && theArgVec[aColorIter][0] <= 122)
-        {
-          Quantity_NameOfColor aColorName;
-          if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName))
+          TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
+          anAtBorder.LowerCase();
+          if (anAtBorder == "border")
           {
-            std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n";
-            return 1;
+            aLabAtBorder = 1;
           }
-          aSeq.Append (Quantity_Color (aColorName));
-          aColorIter++;
-          anArgIter++;
-        }
-        else
-        {
-          TCollection_AsciiString aRed   (theArgVec[aColorIter]);
-          TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]);
-          TCollection_AsciiString aBlue  (theArgVec[aColorIter + 2]);
-          Standard_Real aRedValue,aGreenValue, aBlueValue;
-          if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
+          else if (anAtBorder == "center")
           {
-            return 1;
+            aLabAtBorder = 0;
           }
-          aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB));
-          aColorIter += 3;
-          anArgIter += 3;
         }
+        if (aLabAtBorder == -1)
+        {
+          std::cout << "Syntax error at argument '" << anArg << "'!\n";
+          return 1;
+        }
+        toEnable = (aLabAtBorder == 1);
+      }
+      else if (anArgIter + 1 < theArgNb
+            && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
+      {
+        ++anArgIter;
+      }
+      aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
+                                  || aFlag == "-labatcenter"
+                                   ? !toEnable
+                                   :  toEnable);
+    }
+    else if (aFlag == "-colors")
+    {
+      Aspect_SequenceOfColor aSeq;
+      for (;;)
+      {
+        Quantity_Color aColor;
+        Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
+                                                             theArgVec + (anArgIter + 1),
+                                                             aColor);
+        if (aNbParsed == 0)
+        {
+          break;
+        }
+        anArgIter += aNbParsed;
+        aSeq.Append (aColor);
       }
-      if (aSeq.Length() < aNbIntervals)
+      if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
       {
         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
-                  << aNbIntervals << " intervals\n";
+                  << aColorScale->GetNumberOfIntervals() << " intervals\n";
         return 1;
       }
 
-      aCS->SetColors    (aSeq);
-      aCS->SetColorType (Aspect_TOCSD_USER);
+      aColorScale->SetColors    (aSeq);
+      aColorScale->SetColorType (Aspect_TOCSD_USER);
     }
-    else if (aFlag == "-labels")
+    else if (aFlag == "-labels"
+          || aFlag == "-freelabels")
     {
-      if (anArgIter + aNbIntervals + 1 >= theArgNb)
+      if (anArgIter + 1 >= theArgNb)
       {
-        std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1)
-                  << " text labels for " << aNbIntervals << " intervals.\n";
+        std::cout << "Syntax error at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
+                                 ? aColorScale->GetNumberOfIntervals() + 1
+                                 : aColorScale->GetNumberOfIntervals();
+      if (aFlag == "-freelabels")
+      {
+        ++anArgIter;
+        aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
+      }
+      if (anArgIter + aNbLabels >= theArgNb)
+      {
+        std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
         return 1;
       }
 
       TColStd_SequenceOfExtendedString aSeq;
-      for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1)
+      for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
       {
-        aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter]));
+        aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
       }
-      aCS->SetLabels (aSeq);
-      aCS->SetLabelType (Aspect_TOCSD_USER);
-      anArgIter += aSeq.Length();
+      aColorScale->SetLabels (aSeq);
+      aColorScale->SetLabelType (Aspect_TOCSD_USER);
     }
     else if (aFlag == "-title")
     {
@@ -3852,29 +3887,31 @@ static int VColorScale (Draw_Interpretor& theDI,
       {
         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
         aSecondArg.LowerCase();
+      Standard_DISABLE_DEPRECATION_WARNINGS
         if (aSecondArg == "none")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_NONE);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
           isTwoArgs = Standard_True;
         }
         else if (aSecondArg == "left")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_LEFT);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
           isTwoArgs = Standard_True;
         }
         else if (aSecondArg == "right")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_RIGHT);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
           isTwoArgs = Standard_True;
         }
         else if (aSecondArg == "center")
         {
-          aCS->SetTitlePosition (Aspect_TOCSP_CENTER);
+          aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
           isTwoArgs = Standard_True;
         }
+      Standard_ENABLE_DEPRECATION_WARNINGS
       }
 
-      aCS->SetTitle (theArgVec[anArgIter + 1]);
+      aColorScale->SetTitle (theArgVec[anArgIter + 1]);
       if (isTwoArgs)
       {
         anArgIter += 1;
@@ -3884,17 +3921,36 @@ static int VColorScale (Draw_Interpretor& theDI,
     else if (aFlag == "-demoversion"
           || aFlag == "-demo")
     {
-      aPosX        = 0;
-      aPosY        = 0;
-      aTextHeight  = 16;
-      aMinRange    = 0.0;
-      aMaxRange    = 100;
-      aNbIntervals = 10;
-      aWidth       = 0;
-      aHeight      = 0;
-      aLabPosition = Aspect_TOCSP_RIGHT;
-      aCS->SetColorType (Aspect_TOCSD_AUTO);
-      aCS->SetLabelType (Aspect_TOCSD_AUTO);
+      aColorScale->SetPosition (0, 0);
+      aColorScale->SetTextHeight (16);
+      aColorScale->SetRange (0.0, 100.0);
+      aColorScale->SetNumberOfIntervals (10);
+      aColorScale->SetBreadth (0);
+      aColorScale->SetHeight  (0);
+      aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
+      aColorScale->SetColorType (Aspect_TOCSD_AUTO);
+      aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
+    }
+    else if (aFlag == "-findcolor")
+    {
+      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;
+      }
+
+      Quantity_Color aColor;
+      aColorScale->FindColor (anArg1.RealValue(), aColor);
+      theDI << Quantity_Color::StringName (aColor.Name());
+      return 0;
     }
     else
     {
@@ -3902,29 +3958,19 @@ static int VColorScale (Draw_Interpretor& theDI,
       return 1;
     }
   }
-  if (!aWidth || !aHeight)
+
+  Standard_Integer aWinWidth = 0, aWinHeight = 0;
+  aView->Window()->Size (aWinWidth, aWinHeight);
+  if (aColorScale->GetBreadth() == 0)
   {
-    Standard_Integer aWinWidth, aWinHeight;
-    aView->Window()->Size (aWinWidth, aWinHeight);
-    if (!aWidth)
-    {
-      aWidth = aWinWidth;
-    }
-    if (!aHeight)
-    {
-      aHeight = aWinHeight;
-    }
+    aColorScale->SetBreadth (aWinWidth);
   }
-  aCS->SetSize              (aWidth, aHeight);
-  aCS->SetPosition          (aPosX, aPosY);
-  aCS->SetTextHeight        (aTextHeight);
-  aCS->SetRange             (aMinRange, aMaxRange);
-  aCS->SetNumberOfIntervals (aNbIntervals);
-  aCS->SetLabelPosition     (aLabPosition);
-  aCS->SetBGColor           (aView->BackgroundColor());
-  aCS->SetToUpdate();
-  aContext->Display (aCS);
-
+  if (aColorScale->GetHeight() == 0)
+  {
+    aColorScale->SetHeight (aWinHeight);
+  }
+  aColorScale->SetToUpdate();
+  ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
   return 0;
 }
 
@@ -4053,7 +4099,7 @@ static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer th
   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
   if (anAISContext.IsNull())
   {
-    std::cout << theArgs[0] << ": " << " please use 'vinit' command to initialize view.\n";
+    std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
     return 1;
   }
 
@@ -4267,383 +4313,482 @@ static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer th
 }
 
 //==============================================================================
-//function : VPrintView
-//purpose  : Test printing algorithm, print the view to image file with given
-//           width and height. Printing implemented only for WNT.
+//function : VTile
+//purpose  :
 //==============================================================================
-static int VPrintView (Draw_Interpretor& di, Standard_Integer argc,
-                       const char** argv)
+static int VTile (Draw_Interpretor& theDI,
+                  Standard_Integer  theArgNb,
+                  const char**      theArgVec)
 {
-#ifndef _WIN32
-  di << "Printing implemented only for WNT!\n";
-  return 0;
-#else
-
-  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();
-  }
-
-  // check for errors
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
   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";
+    std::cerr << "Error: no active viewer.\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]);
-
-  Standard_Integer aTileWidth  = 0;
-  Standard_Integer aTileHeight = 0;
-  Standard_Boolean isTileSizeProvided = Standard_False;
-  if (argc == 7)
+  Graphic3d_CameraTile aTile = aView->Camera()->Tile();
+  if (theArgNb < 2)
   {
-    isTileSizeProvided = Standard_True;
-    aTileWidth  = Draw::Atoi (argv[5]);
-    aTileHeight = Draw::Atoi (argv[6]);
+    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;
   }
 
-  // check the input parameters
-  if (aWidth <= 0 || aHeight <= 0)
+  aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
-    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
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anArg == "-lowerleft"
+     || anArg == "-upperleft")
     {
-      if (isTileSizeProvided)
+      if (anArgIter + 3 < theArgNb)
       {
-        Handle(Graphic3d_CView) aGraphicView = ViewerTest::CurrentView()->View();
-        Graphic3d_PtrFrameBuffer anOldBuffer = aGraphicView->FBO();
-        Graphic3d_PtrFrameBuffer aNewBuffer  = aGraphicView->FBOCreate (aTileWidth, aTileHeight);
-        aGraphicView->SetFBO (aNewBuffer);
-
-        isPrinted = aView->Print (anDC, 1, 1, 0, Aspect_PA_TILE);
-
-        aGraphicView->FBORelease (aNewBuffer);
-        aGraphicView->SetFBO (anOldBuffer);
+        std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
+        return 1;
       }
-      else
+      aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
+      aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
+      aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
+    }
+    else if (anArg == "-total"
+          || anArg == "-totalsize"
+          || anArg == "-viewsize")
+    {
+      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)
       {
-        isPrinted = aView->Print (anDC, 1, 1, 0, Aspect_PA_TILE);
+        std::cerr << "Error: total size is incorrect.\n";
+        return 1;
       }
     }
-
-    // successfully printed into an intermediate buffer
-    if (isPrinted)
+    else if (anArg == "-tilesize")
     {
-      Image_PixMap aWrapper;
-      aWrapper.InitWrapper (Image_PixMap::ImgBGR, (Standard_Byte* )aBitsOut, aWidth, aHeight, aWidth * 3 + aWidth % 4);
-      aWrapper.SetTopDown (false);
+      if (anArgIter + 3 < theArgNb)
+      {
+        std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
+        return 1;
+      }
 
-      Image_AlienPixMap anImageBitmap;
-      anImageBitmap.InitCopy (aWrapper);
-      isSaved = anImageBitmap.Save (aFileName);
+      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
+    else if (anArg == "-unset")
     {
-      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";
+      aView->Camera()->SetTile (Graphic3d_CameraTile());
+      aView->Redraw();
+      return 0;
     }
   }
-  else
-  {
-    di << "Can't allocate memory for intermediate buffer\n";
-    di << "Please use smaller dimensions\n";
-  }
 
-  if (aMemoryBitmap)
+  if (aTile.TileSize.x() < 1
+   || aTile.TileSize.y() < 1)
   {
-    SelectObject (anDC, anOldBitmap);
-    DeleteObject (aMemoryBitmap);
-    DeleteDC(anDC);
+    std::cerr << "Error: tile size is undefined.\n";
+    return 1;
   }
-
-  if (!isSaved)
+  else if (aTile.TotalSize.x() < 1
+        || aTile.TotalSize.y() < 1)
   {
-    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";
+    std::cerr << "Error: total size is undefined.\n";
     return 1;
   }
 
+  aView->Camera()->SetTile (aTile);
+  aView->Redraw();
   return 0;
+}
 
-#endif
+//! Format ZLayer ID.
+inline const char* formZLayerId (const Standard_Integer theLayerId)
+{
+  switch (theLayerId)
+  {
+    case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
+    case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
+    case Graphic3d_ZLayerId_Top:     return "[TOP]";
+    case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
+    case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
+    case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
+  }
+  return "";
+}
+
+//! Print the ZLayer information.
+inline void printZLayerInfo (Draw_Interpretor& theDI,
+                             const Graphic3d_ZLayerSettings& theLayer)
+{
+  if (!theLayer.Name().IsEmpty())
+  {
+    theDI << "  Name: " << theLayer.Name() << "\n";
+  }
+  if (theLayer.IsImmediate())
+  {
+    theDI << "  Immediate: TRUE\n";
+  }
+  theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
+  theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
+  theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
+  theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
+  if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
+  {
+    theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
+  }
 }
 
 //==============================================================================
 //function : VZLayer
 //purpose  : Test z layer operations for v3d viewer
 //==============================================================================
-static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+static int VZLayer (Draw_Interpretor& theDI,
+                    Standard_Integer  theArgNb,
+                    const char**      theArgVec)
 {
-  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
+  Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
   if (aContextAIS.IsNull())
   {
-    di << "Call vinit before!\n";
-    return 1;
-  }
-  else if (argc < 2)
-  {
-    di << "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";
+    std::cout << "No active viewer!\n";
     return 1;
   }
 
   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
-  if (aViewer.IsNull())
+  if (theArgNb < 2)
   {
-    di << "No active viewer!\n";
+    TColStd_SequenceOfInteger aLayers;
+    aViewer->GetAllZLayers (aLayers);
+    for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
+    {
+      theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
+      printZLayerInfo (theDI, aSettings);
+    }
     return 1;
   }
 
-  // perform operation
-  TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
-  if (anOp == "add")
+  Standard_Integer anArgIter = 1;
+  Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
+  ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
+  if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
   {
-    Standard_Integer aNewId;
-    if (!aViewer->AddZLayer (aNewId))
-    {
-      di << "Impossible to add new z layer!\n";
-      return 1;
-    }
+    ++anArgIter;
+  }
 
-    di << "New z layer added with index: " << aNewId << "\n";
+  TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
+  if (aFirstArg.IsIntegerValue())
+  {
+    ++anArgIter;
+    aLayerId = aFirstArg.IntegerValue();
   }
-  else if (anOp == "del")
+  else
   {
-    if (argc < 3)
-    {
-      di << "Please also provide as argument id of z layer to remove\n";
-      return 1;
-    }
-
-    Standard_Integer aDelId = Draw::Atoi (argv[2]);
-    if (!aViewer->RemoveZLayer (aDelId))
+    aFirstArg.LowerCase();
+    if (aFirstArg == "default"
+     || aFirstArg == "def")
     {
-      di << "Impossible to remove the z layer or invalid id!\n";
-      return 1;
+      aLayerId = Graphic3d_ZLayerId_Default;
+      ++anArgIter;
     }
-
-    for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
-         anObjIter.More(); anObjIter.Next())
+    else if (aFirstArg == "top")
     {
-      Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
-      if (aPrs.IsNull()
-       || aPrs->ZLayer() != aDelId)
-      {
-        continue;
-      }
-      aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
+      aLayerId = Graphic3d_ZLayerId_Top;
+      ++anArgIter;
     }
-
-    di << "Z layer " << aDelId << " has been removed\n";
-  }
-  else if (anOp == "get")
-  {
-    TColStd_SequenceOfInteger anIds;
-    aViewer->GetAllZLayers (anIds);
-    for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
+    else if (aFirstArg == "topmost")
     {
-      di << anIds.Value (aSeqIdx) << " ";
+      aLayerId = Graphic3d_ZLayerId_Topmost;
+      ++anArgIter;
     }
-
-    di << "\n";
-  }
-  else if (anOp == "settings")
-  {
-    if (argc < 3)
+    else if (aFirstArg == "overlay"
+          || aFirstArg == "toposd")
     {
-      di << "Please also provide an id\n";
-      return 1;
+      aLayerId = Graphic3d_ZLayerId_TopOSD;
+      ++anArgIter;
     }
-
-    Standard_Integer anId = Draw::Atoi (argv[2]);
-    Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
-
-    di << "Depth test - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthTest) ? "enabled" : "disabled") << "\n";
-    di << "Depth write - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? "enabled" : "disabled") << "\n";
-    di << "Depth buffer clearing - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthClear) ? "enabled" : "disabled") << "\n";
-    di << "Depth offset - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthOffset) ? "enabled" : "disabled") << "\n";
-
-  }
-  else if (anOp == "enable")
-  {
-    if (argc < 3)
+    else if (aFirstArg == "underlay"
+          || aFirstArg == "botosd")
     {
-      di << "Please also provide an option to enable\n";
-      return 1;
+      aLayerId = Graphic3d_ZLayerId_BotOSD;
+      ++anArgIter;
     }
-
-    if (argc < 4)
+    else
     {
-      di << "Please also provide a layer id\n";
-      return 1;
+      TColStd_SequenceOfInteger aLayers;
+      aViewer->GetAllZLayers (aLayers);
+      for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
+      {
+        Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
+        if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
+        {
+          aLayerId = aLayeriter.Value();
+          ++anArgIter;
+          break;
+        }
+      }
     }
+  }
 
-    TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
-    Standard_Integer anId = Draw::Atoi (argv[3]);
-    Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
-
-    if (aSubOp == "depthtest" || aSubOp == "test")
-    {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthTest);
-    }
-    else if (aSubOp == "depthwrite" || aSubOp == "write")
+  for (; anArgIter < theArgNb; ++anArgIter)
+  {
+    // perform operation
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthWrite);
+      //
     }
-    else if (aSubOp == "depthclear" || aSubOp == "clear")
+    else if (anArg == "-add"
+          || anArg == "add")
     {
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthClear);
+      aLayerId = Graphic3d_ZLayerId_UNKNOWN;
+      if (!aViewer->AddZLayer (aLayerId))
+      {
+        std::cout << "Error: can not add a new z layer!\n";
+        return 0;
+      }
+
+      theDI << aLayerId;
     }
-    else if (aSubOp == "depthoffset" || aSubOp == "offset")
+    else if (anArg == "-del"
+          || anArg == "-delete"
+          || anArg == "del")
     {
-      if (argc < 6)
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
       {
-        di << "Please also provide a factor and units values for depth offset\n";
-        di << "Format is: vzlayer enable offset [factor] [units] [layerId]\n";
-        return 1;
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of z layer to remove is missing\n";
+          return 1;
+        }
+
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
       }
 
-      Standard_ShortReal aFactor = static_cast<Standard_ShortReal> (Draw::Atof (argv[3]));
-      Standard_ShortReal aUnits  = static_cast<Standard_ShortReal> (Draw::Atof (argv[4]));
-      anId = Draw::Atoi (argv[5]);
-      aSettings = aViewer->ZLayerSettings (anId);
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
+       || aLayerId == Graphic3d_ZLayerId_Default
+       || aLayerId == Graphic3d_ZLayerId_Top
+       || aLayerId == Graphic3d_ZLayerId_Topmost
+       || aLayerId == Graphic3d_ZLayerId_TopOSD
+       || aLayerId == Graphic3d_ZLayerId_BotOSD)
+      {
+        std::cout << "Syntax error: standard Z layer can not be removed\n";
+        return 1;
+      }
 
-      aSettings.DepthOffsetFactor = aFactor;
-      aSettings.DepthOffsetUnits  = aUnits;
+      // move all object displayed in removing layer to default layer
+      for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
+           anObjIter.More(); anObjIter.Next())
+      {
+        Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
+        if (aPrs.IsNull()
+         || aPrs->ZLayer() != aLayerId)
+        {
+          continue;
+        }
+        aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
+      }
 
-      aSettings.EnableSetting (Graphic3d_ZLayerDepthOffset);
-    }
-    else if (aSubOp == "positiveoffset" || aSubOp == "poffset")
-    {
-      aSettings.SetDepthOffsetPositive();
+      if (!aViewer->RemoveZLayer (aLayerId))
+      {
+        std::cout << "Z layer can not be removed!\n";
+      }
+      else
+      {
+        theDI << aLayerId << " ";
+      }
     }
-    else if (aSubOp == "negativeoffset" || aSubOp == "noffset")
+    else if (anArg == "-get"
+          || anArg == "get")
     {
-      aSettings.SetDepthOffsetNegative();
-    }
+      TColStd_SequenceOfInteger aLayers;
+      aViewer->GetAllZLayers (aLayers);
+      for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
+      {
+        theDI << aLayeriter.Value() << " ";
+      }
 
-    aViewer->SetZLayerSettings (anId, aSettings);
-  }
-  else if (anOp == "disable")
-  {
-    if (argc < 3)
-    {
-      di << "Please also provide an option to disable\n";
-      return 1;
+      theDI << "\n";
     }
-
-    if (argc < 4)
+    else if (anArg == "-name")
     {
-      di << "Please also provide a layer id\n";
-      return 1;
-    }
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        std::cout << "Syntax error: id of Z layer is missing\n";
+        return 1;
+      }
 
-    TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
-    Standard_Integer anId = Draw::Atoi (argv[3]);
-    Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error: name is missing\n";
+        return 1;
+      }
 
-    if (aSubOp == "depthtest" || aSubOp == "test")
-    {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthTest);
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      aSettings.SetName (theArgVec[anArgIter]);
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
     }
-    else if (aSubOp == "depthwrite" || aSubOp == "write")
+    else if (anArg == "-origin")
     {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthWrite);
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        std::cout << "Syntax error: id of Z layer is missing\n";
+        return 1;
+      }
+
+      if (anArgIter + 2 >= theArgNb)
+      {
+        std::cout << "Syntax error: origin coordinates are missing\n";
+        return 1;
+      }
+
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      gp_XYZ anOrigin;
+      anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
+      anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
+      anOrigin.SetZ (0.0);
+      if (anArgIter + 3 < theArgNb)
+      {
+        anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
+        anArgIter += 3;
+      }
+      else
+      {
+        anArgIter += 2;
+      }
+      aSettings.SetOrigin (anOrigin);
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
     }
-    else if (aSubOp == "depthclear" || aSubOp == "clear")
+    else if (anArg == "-settings"
+          || anArg == "settings")
     {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthClear);
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of Z layer is missing\n";
+          return 1;
+        }
+
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
+      }
+
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      printZLayerInfo (theDI, aSettings);
     }
-    else if (aSubOp == "depthoffset" || aSubOp == "offset")
+    else if (anArg == "-enable"
+          || anArg == "enable"
+          || anArg == "-disable"
+          || anArg == "disable")
     {
-      aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
-    }
+      const Standard_Boolean toEnable = anArg == "-enable"
+                                     || anArg == "enable";
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error: option name is missing\n";
+        return 1;
+      }
 
-    aViewer->SetZLayerSettings (anId, aSettings);
-  }
-  else
-  {
-    di << "Invalid operation, please use { add / del / get / settings / enable / disable}\n";
-    return 1;
-  }
+      TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
+      aSubOp.LowerCase();
+      if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        if (++anArgIter >= theArgNb)
+        {
+          std::cout << "Syntax error: id of Z layer is missing\n";
+          return 1;
+        }
 
-  return 0;
-}
+        aLayerId = Draw::Atoi (theArgVec[anArgIter]);
+      }
+
+      Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
+      if (aSubOp == "depthtest"
+       || aSubOp == "test")
+      {
+        aSettings.SetEnableDepthTest (toEnable);
+      }
+      else if (aSubOp == "depthwrite"
+            || aSubOp == "write")
+      {
+        aSettings.SetEnableDepthWrite (toEnable);
+      }
+      else if (aSubOp == "depthclear"
+            || aSubOp == "clear")
+      {
+        aSettings.SetClearDepth (toEnable);
+      }
+      else if (aSubOp == "depthoffset"
+            || aSubOp == "offset")
+      {
+        Graphic3d_PolygonOffset aParams;
+        aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
+        if (toEnable)
+        {
+          if (anArgIter + 2 >= theArgNb)
+          {
+            std::cout << "Syntax error: factor and units values for depth offset are missing\n";
+            return 1;
+          }
+
+          aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
+          aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
+        }
+        aSettings.SetPolygonOffset (aParams);
+      }
+      else if (aSubOp == "positiveoffset"
+            || aSubOp == "poffset")
+      {
+        if (toEnable)
+        {
+          aSettings.SetDepthOffsetPositive();
+        }
+        else
+        {
+          aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
+        }
+      }
+      else if (aSubOp == "negativeoffset"
+            || aSubOp == "noffset")
+      {
+        if (toEnable)
+        {
+          aSettings.SetDepthOffsetNegative();
+        }
+        else
+        {
+          aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
+        }
+      }
+      else if (aSubOp == "textureenv")
+      {
+        aSettings.SetEnvironmentTexture (toEnable);
+      }
+
+      aViewer->SetZLayerSettings (aLayerId, aSettings);
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
+      return 1;
+    }
+  }
+
+  return 0;
+}
 
 // The interactive presentation of 2d layer item
 // for "vlayerline" command it provides a presentation of
@@ -4652,7 +4797,7 @@ class V3d_LineItem : public AIS_InteractiveObject
 {
 public:
   // CASCADE RTTI
-  DEFINE_STANDARD_RTTI(V3d_LineItem, AIS_InteractiveObject)
+  DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
 
   // constructor
   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
@@ -4665,10 +4810,11 @@ public:
 
   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
                 const Handle(Prs3d_Presentation)& thePresentation,
-                const Standard_Integer theMode);
+                const Standard_Integer theMode) Standard_OVERRIDE;
 
   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
-                         const Standard_Integer /*aMode*/){};
+                         const Standard_Integer /*aMode*/) Standard_OVERRIDE
+  {}
 
 private:
 
@@ -4743,17 +4889,21 @@ static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char**
   Standard_Real X2 = Draw::Atof(argv[3]);
   Standard_Real Y2 = Draw::Atof(argv[4]);
 
-  Standard_Real    aWidth = 0.5;
-  Standard_Integer aType  = 0;
-  Standard_Real    aTransparency = 1.0;
+  Standard_Real aWidth = 0.5;
+  Standard_Real aTransparency = 1.0;
 
   // has width
   if (argc > 5)
     aWidth = Draw::Atof(argv[5]);
 
-  // has type
-  if (argc > 6)
-     aType = (Standard_Integer) Draw::Atoi(argv[6]);
+  // select appropriate line type
+  Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
+  if (argc > 6
+  && !ViewerTest::ParseLineType (argv[6], aLineType))
+  {
+    std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
+    return 1;
+  }
 
   // has transparency
   if (argc > 7)
@@ -4763,26 +4913,6 @@ static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char**
       aTransparency = 1.0;
   }
 
-  // select appropriate line type
-  Aspect_TypeOfLine aLineType;
-  switch (aType)
-  {
-    case 1:
-      aLineType = Aspect_TOL_DASH;
-    break;
-
-    case 2:
-      aLineType = Aspect_TOL_DOT;
-    break;
-
-    case 3:
-      aLineType = Aspect_TOL_DOTDASH;
-    break;
-
-    default:
-      aLineType = Aspect_TOL_SOLID;
-  }
-
   static Handle (V3d_LineItem) aLine;
   if (!aLine.IsNull())
   {
@@ -4792,7 +4922,7 @@ static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char**
                             aLineType, aWidth,
                             aTransparency);
 
-  aLine->SetTransformPersistence (Graphic3d_TMF_2d,gp_Pnt(-1,-1,0));
+  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);
@@ -5593,7 +5723,7 @@ static int VReadPixel (Draw_Interpretor& theDI,
     return 1;
   }
 
-  Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+  Image_PixMap::ImgFormat aFormat     = Image_PixMap::ImgRGBA;
   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
 
   Standard_Integer aWidth, aHeight;
@@ -5613,12 +5743,12 @@ static int VReadPixel (Draw_Interpretor& theDI,
     const char* aParam = theArgVec[anIter];
     if ( strcasecmp( aParam, "rgb" ) == 0 )
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
+      aFormat     = Image_PixMap::ImgRGB;
       aBufferType = Graphic3d_BT_RGB;
     }
     else if ( strcasecmp( aParam, "hls" ) == 0 )
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
+      aFormat     = Image_PixMap::ImgRGB;
       aBufferType = Graphic3d_BT_RGB;
       toShowHls   = Standard_True;
     }
@@ -5629,7 +5759,7 @@ static int VReadPixel (Draw_Interpretor& theDI,
     }
     else if ( strcasecmp( aParam, "rgba" ) == 0 )
     {
-      aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+      aFormat     = Image_PixMap::ImgRGBA;
       aBufferType = Graphic3d_BT_RGBA;
     }
     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
@@ -5772,7 +5902,7 @@ static Standard_Integer VSelect (Draw_Interpretor& di,
 {
   if(argc < 3)
   {
-    di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]" << "\n";
+    di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
     return 1;
   }
 
@@ -5799,7 +5929,7 @@ static Standard_Integer VSelect (Draw_Interpretor& di,
     }
 
     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
-    myAIScontext->MainSelector()->AllowOverlapDetection((Standard_Boolean)isToAllow);
+    myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
     aCoordsNb -= 2;
   }
 
@@ -5844,7 +5974,7 @@ static Standard_Integer VMoveTo (Draw_Interpretor& di,
 {
   if(argc != 3)
   {
-    di << "Usage : " << argv[0] << " x y" << "\n";
+    di << "Usage : " << argv[0] << " x y\n";
     return 1;
   }
 
@@ -5858,407 +5988,983 @@ static Standard_Integer VMoveTo (Draw_Interpretor& di,
   return 0;
 }
 
-//=================================================================================================
-//function : VViewParams
-//purpose  : Gets or sets AIS View characteristics
-//=================================================================================================
-static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+namespace
 {
-  Handle(V3d_View) anAISView = ViewerTest::CurrentView();
-  if (anAISView.IsNull())
-  {
-    std::cout << theArgVec[0] << ": please initialize or activate view.\n";
-    return 1;
-  }
+  //! Global map storing all animations registered in ViewerTest.
+  static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
 
-  if (theArgsNb == 1)
+  //! The animation calling the Draw Harness command.
+  class ViewerTest_AnimationProc : public AIS_Animation
   {
-    // 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;
-  }
+  public:
 
-  // -------------------------
-  //  Parse options and values
-  // -------------------------
+    //! Main constructor.
+    ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
+                              Draw_Interpretor* theDI,
+                              const TCollection_AsciiString& theCommand)
+    : AIS_Animation (theAnimationName),
+      myDrawInter(theDI),
+      myCommand  (theCommand)
+    {
+      //
+    }
 
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfKeysByValues;
-  TCollection_AsciiString aParseKey;
-  for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
-  {
-    TCollection_AsciiString anArg (theArgVec [anArgIt]);
+  protected:
 
-    if (anArg.Value (1) == '-' && !anArg.IsRealValue())
+    //! Evaluate the command.
+    virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
     {
-      aParseKey = anArg;
-      aParseKey.Remove (1);
-      aParseKey.UpperCase();
-      aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
-      continue;
+      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());
     }
 
-    if (aParseKey.IsEmpty())
+    //! 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)
     {
-      std::cout << theArgVec[0] << ": values should be passed with key.\n";
-      std::cout << "Type help for more information.\n";
-      return 1;
-    }
+      TCollection_AsciiString aCmd (theCmd);
+      aCmd.LowerCase();
+      const Standard_Integer aPos = aCmd.Search (theKey);
+      if (aPos == -1)
+      {
+        return;
+      }
 
-    aMapOfKeysByValues(aParseKey)->Append (anArg);
-  }
+      TCollection_AsciiString aPart1, aPart2;
+      Standard_Integer aPart1To = aPos - 1;
+      if (aPart1To >= 1
+       && aPart1To <= theCmd.Length())
+      {
+        aPart1 = theCmd.SubString (1, aPart1To);
+      }
 
-  // ---------------------------------------------
-  //  Change or print parameters, order plays role
-  // ---------------------------------------------
+      Standard_Integer aPart2From = aPos + theKey.Length();
+      if (aPart2From >= 1
+       && aPart2From <= theCmd.Length())
+      {
+        aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
+      }
 
-  // Check arguments for validity
-  NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfKeysByValues);
-  for (; aMapIt.More(); aMapIt.Next())
-  {
-    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;
+      theCmd = aPart1 + theVal + aPart2;
     }
-  }
 
-  Handle(TColStd_HSequenceOfAsciiString) aValues;
+  protected:
+
+    Draw_Interpretor*       myDrawInter;
+    TCollection_AsciiString myCommand;
+
+  };
 
-  // Change view parameters in proper order
-  if (aMapOfKeysByValues.Find ("SCALE", aValues))
+  //! Replace the animation with the new one.
+  static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
+                                Handle(AIS_Animation)&       theAnimation,
+                                const Handle(AIS_Animation)& theAnimationNew)
   {
-    if (aValues->IsEmpty())
+    theAnimationNew->CopyFrom (theAnimation);
+    if (!theParentAnimation.IsNull())
     {
-      theDi << "Scale: " << anAISView->Scale() << "\n";
+      theParentAnimation->Replace (theAnimation, theAnimationNew);
     }
     else
     {
-      anAISView->SetScale (aValues->Value(1).RealValue());
+      ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
+      ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
     }
+    theAnimation = theAnimationNew;
   }
-  if (aMapOfKeysByValues.Find ("SIZE", aValues))
+
+  //! Parse the point.
+  static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
   {
-    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
+    const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
+    if (!anXYZ[0].IsRealValue()
+     || !anXYZ[1].IsRealValue()
+     || !anXYZ[2].IsRealValue())
     {
-      anAISView->SetSize (aValues->Value(1).RealValue());
+      return Standard_False;
     }
+
+    thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
+    return Standard_True;
   }
-  if (aMapOfKeysByValues.Find ("EYE", aValues))
+
+  //! Parse the quaternion.
+  static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
   {
-    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
+    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())
     {
-      anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      return Standard_False;
     }
+
+    theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
+    return Standard_True;
+  }
+
+}
+
+//=================================================================================================
+//function : VViewParams
+//purpose  : Gets or sets AIS View characteristics
+//=================================================================================================
+static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cout << theArgVec[0] << ": please initialize or activate view.\n";
+    return 1;
   }
-  if (aMapOfKeysByValues.Find ("AT", aValues))
+
+  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)
   {
-    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
-    {
-      anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
-    }
+    // 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;
   }
-  if (aMapOfKeysByValues.Find ("PROJ", aValues))
+
+  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
+  for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
   {
-    if (aValues->IsEmpty())
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
-      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";
+      continue;
     }
-    else
+    else if (anArg == "-cmd"
+          || anArg == "-command"
+          || anArg == "-args")
+    {
+      char aText[4096];
+      Sprintf (aText,
+               "-scale %g "
+               "-proj %g %g %g "
+               "-up %g %g %g "
+               "-at %g %g %g\n",
+                aViewScale,
+                aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
+                aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
+                aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
+      theDi << aText;
+    }
+    else if (anArg == "-scale"
+          || anArg == "-size")
+    {
+      if (anArgIter + 1 < theArgsNb
+       && *theArgVec[anArgIter + 1] != '-')
+      {
+        const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
+        if (aValueArg.IsRealValue())
+        {
+          ++anArgIter;
+          if (anArg == "-scale")
+          {
+            toSetScale = Standard_True;
+            aViewScale = aValueArg.RealValue();
+          }
+          else if (anArg == "-size")
+          {
+            toSetSize = Standard_True;
+            aViewSize = aValueArg.RealValue();
+          }
+          continue;
+        }
+      }
+      if (anArg == "-scale")
+      {
+        theDi << "Scale: " << aView->Scale() << "\n";
+      }
+      else if (anArg == "-size")
+      {
+        Graphic3d_Vec2d aSizeXY;
+        aView->Size (aSizeXY.x(), aSizeXY.y());
+        theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
+      }
+    }
+    else if (anArg == "-eye"
+          || anArg == "-at"
+          || anArg == "-up"
+          || anArg == "-proj")
     {
-      anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      if (anArgIter + 3 < theArgsNb)
+      {
+        gp_XYZ anXYZ;
+        if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
+        {
+          anArgIter += 3;
+          if (anArg == "-eye")
+          {
+            toSetEye = Standard_True;
+            aViewEye = anXYZ;
+          }
+          else if (anArg == "-at")
+          {
+            toSetAt = Standard_True;
+            aViewAt = anXYZ;
+          }
+          else if (anArg == "-up")
+          {
+            toSetUp = Standard_True;
+            aViewUp = anXYZ;
+          }
+          else if (anArg == "-proj")
+          {
+            toSetProj = Standard_True;
+            aViewProj = anXYZ;
+          }
+          continue;
+        }
+      }
+
+      if (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";
+      }
     }
-  }
-  if (aMapOfKeysByValues.Find ("UP", aValues))
-  {
-    if (aValues->IsEmpty())
+    else if (anArg == "-center")
     {
-      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";
+      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
     {
-      anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
+      std::cout << "Syntax error at '" << anArg << "'\n";
+      return 1;
     }
   }
-  if (aMapOfKeysByValues.Find ("CENTER", aValues))
+
+  // 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)
   {
-    anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue());
+    aView->SetCenter (aCenter2d.x(), aCenter2d.y());
   }
 
   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 : VAnimation
+//purpose  :
+//==============================================================================
+static Standard_Integer VAnimation (Draw_Interpretor& theDI,
+                                    Standard_Integer  theArgNb,
+                                    const char**      theArgVec)
 {
-  if(argc != 2)
+  Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  if (theArgNb < 2)
   {
-    di<<"Usage : " << argv[0] << " shape \n";
-    return 1;
+    for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
+         anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
+    {
+      theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
+    }
+    return 0;
   }
-  //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))
+  if (aCtx.IsNull())
   {
-    di<<"Use 'vdisplay' before";
+    std::cout << "Error: no active view\n";
     return 1;
   }
-  else
-  {
-    anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
-    if(anAISObject.IsNull()){
-      di<<"No interactive object \n";
-      return 1;
-    }
 
-    aContext->AddOrRemoveSelected(anAISObject);
+  Standard_Integer anArgIter = 1;
+  TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
+  if (aNameArg.IsEmpty())
+  {
+    std::cout << "Syntax error: animation name is not defined.\n";
+    return 1;
   }
-  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)
-{
-  if(argc>4)
+  TCollection_AsciiString aNameArgLower = aNameArg;
+  aNameArgLower.LowerCase();
+  if (aNameArgLower == "-reset"
+   || aNameArgLower == "-clear")
   {
-    di << "Usage : " << argv[0] << " [mode] [depth  width]" << "\n"
-      <<"mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
-    return -1;
+    ViewerTest_AnimationTimelineMap.Clear();
+    return 0;
   }
-  Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  else if (aNameArg.Value (1) == '-')
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
+    std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
     return 1;
   }
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  V3d_TypeOfZclipping aZClippingMode = V3d_OFF;
-  if(argc==1)
+
+  const char* aNameSplitter = "/";
+  Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
+  if (aSplitPos == -1)
   {
-    TCollection_AsciiString aZClippingModeString;
-    Quantity_Length aDepth, aWidth;
-    aZClippingMode = aView->ZClipping(aDepth, aWidth);
-    switch (aZClippingMode)
-    {
-    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;
-    }
-    di << "ZClippingMode = " << aZClippingModeString.ToCString() << "\n"
-      << "ZClipping depth = " << aDepth << "\n"
-      << "ZClipping width = " << aWidth << "\n";
+    aNameSplitter = ".";
+    aSplitPos = aNameArg.Search (aNameSplitter);
   }
-  else
+
+  // find existing or create a new animation by specified name within syntax "parent.child".
+  Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
+  for (; !aNameArg.IsEmpty();)
   {
-    if(argc !=3)
+    TCollection_AsciiString aNameParent;
+    if (aSplitPos != -1)
     {
-      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;
-      }
-      if ( strcmp (argv [1], "FRONT") == 0 ) {
-        aStatus = 1;
-        aZClippingMode = V3d_FRONT;
-      }
-      if ( strcmp (argv [1], "SLICE") == 0 ) {
-        aStatus = 1;
-        aZClippingMode = V3d_SLICE;
-      }
-      if (aStatus != 1)
+      if (aSplitPos == aNameArg.Length())
       {
-        di << "Bad mode; Usage : " << argv[0] << " [mode] [depth width]" << "\n"
-          << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
+        std::cout << "Syntax error: animation name is not defined.\n";
         return 1;
       }
-      aView->SetZClippingType(aZClippingMode);
-    }
-    if(argc >2)
+
+      aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
+      aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
+
+      aSplitPos = aNameArg.Search (aNameSplitter);
+    }
+    else
+    {
+      aNameParent = aNameArg;
+      aNameArg.Clear();
+    }
+
+    if (anAnimation.IsNull())
+    {
+      if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
+      {
+        anAnimation = new AIS_Animation (aNameParent);
+        ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
+      }
+      aRootAnimation = anAnimation;
+    }
+    else
+    {
+      aParentAnimation = anAnimation;
+      anAnimation = aParentAnimation->Find (aNameParent);
+      if (anAnimation.IsNull())
+      {
+        anAnimation = new AIS_Animation (aNameParent);
+        aParentAnimation->Add (anAnimation);
+      }
+    }
+  }
+
+  if (anArgIter >= theArgNb)
+  {
+    // just print the list of children
+    for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
+    {
+      theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
+    }
+    return 0;
+  }
+
+  // animation parameters
+  Standard_Boolean toPlay = Standard_False;
+  Standard_Real aPlaySpeed     = 1.0;
+  Standard_Real aPlayStartTime = anAnimation->StartPts();
+  Standard_Real aPlayDuration  = anAnimation->Duration();
+  Standard_Integer aFpsNum     = 0;
+  Standard_Integer aFpsDen     = 1;
+  Standard_Boolean isFreeCamera = Standard_False;
+  Standard_Boolean isLockLoop   = Standard_False;
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  for (; anArgIter < theArgNb; ++anArgIter)
+  {
+    TCollection_AsciiString anArg (theArgVec[anArgIter]);
+    anArg.LowerCase();
+    // general options
+    if (anArg == "-reset"
+     || anArg == "-clear")
+    {
+      anAnimation->Clear();
+    }
+    else if (anArg == "-remove"
+          || anArg == "-del"
+          || anArg == "-delete")
+    {
+      if (!aParentAnimation.IsNull())
+      {
+        ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
+      }
+      else
+      {
+        aParentAnimation->Remove (anAnimation);
+      }
+    }
+    // playback options
+    else if (anArg == "-play")
+    {
+      toPlay = Standard_True;
+      if (++anArgIter < theArgNb)
+      {
+        if (*theArgVec[anArgIter] == '-')
+        {
+          --anArgIter;
+          continue;
+        }
+        aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
+
+        if (++anArgIter < theArgNb)
+        {
+          if (*theArgVec[anArgIter] == '-')
+          {
+            --anArgIter;
+            continue;
+          }
+          aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
+        }
+      }
+    }
+    else if (anArg == "-resume")
+    {
+      toPlay = Standard_True;
+      aPlayStartTime = anAnimation->ElapsedTime();
+      if (++anArgIter < theArgNb)
+      {
+        if (*theArgVec[anArgIter] == '-')
+        {
+          --anArgIter;
+          continue;
+        }
+
+        aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
+      }
+    }
+    else if (anArg == "-playspeed"
+          || anArg == "-speed")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+      aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
+    }
+    else if (anArg == "-lock"
+          || anArg == "-lockloop"
+          || anArg == "-playlockloop")
+    {
+      isLockLoop = Standard_True;
+    }
+    else if (anArg == "-freecamera"
+          || anArg == "-playfreecamera"
+          || anArg == "-freelook")
+    {
+      isFreeCamera = Standard_True;
+    }
+    else if (anArg == "-fps")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
+      Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
+      if (aSplitIndex == 0)
+      {
+        aFpsNum = aFpsArg.IntegerValue();
+      }
+      else
+      {
+        const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
+        aFpsArg.Split (aFpsArg.Length() - 1);
+        const TCollection_AsciiString aNumStr = aFpsArg;
+        aFpsNum = aNumStr.IntegerValue();
+        aFpsDen = aDenStr.IntegerValue();
+        if (aFpsDen < 1)
+        {
+          std::cout << "Syntax error at " << anArg << ".\n";
+          return 1;
+        }
+      }
+    }
+    // animation definition options
+    else if (anArg == "-start"
+          || anArg == "-starttime"
+          || anArg == "-startpts")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
+      aRootAnimation->UpdateTotalDuration();
+    }
+    else if (anArg == "-end"
+          || anArg == "-endtime"
+          || anArg == "-endpts")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
+      aRootAnimation->UpdateTotalDuration();
+    }
+    else if (anArg == "-dur"
+          || anArg == "-duration")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
+      aRootAnimation->UpdateTotalDuration();
+    }
+    else if (anArg == "-command"
+          || anArg == "-cmd"
+          || anArg == "-invoke"
+          || anArg == "-eval"
+          || anArg == "-proc")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
+      }
+
+      Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
+      replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
+    }
+    else if (anArg == "-objecttrsf"
+          || anArg == "-objectransformation"
+          || anArg == "-objtransformation"
+          || anArg == "-objtrsf"
+          || anArg == "-object"
+          || anArg == "-obj")
     {
-      Quantity_Length aDepth = 0., aWidth = 1.;
-      if(argc == 3)
+      if (++anArgIter >= theArgNb)
       {
-        aDepth = Draw::Atof (argv[1]);
-        aWidth = Draw::Atof (argv[2]);
+        std::cout << "Syntax error at " << anArg << ".\n";
+        return 1;
       }
-      else if(argc == 4)
+
+      TCollection_AsciiString anObjName (theArgVec[anArgIter]);
+      const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
+      if (!aMapOfAIS.IsBound2 (anObjName))
       {
-        aDepth = Draw::Atof (argv[2]);
-        aWidth = Draw::Atof (argv[3]);
+        std::cout << "Syntax error: wrong object name at " << anArg << "\n";
+        return 1;
       }
 
-      if(aDepth<0. || aDepth>1.)
+      Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
+      gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
+      gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
+      gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
+      Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
+      Standard_Boolean isTrsfSet = Standard_False;
+      Standard_Integer aTrsfArgIter = anArgIter + 1;
+      for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
+      {
+        TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
+        aTrsfArg.LowerCase();
+        const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
+        if (aTrsfArg.StartsWith ("-rotation")
+         || aTrsfArg.StartsWith ("-rot"))
+        {
+          isTrsfSet = Standard_True;
+          if (aTrsfArgIter + 4 >= theArgNb
+          || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aTrsfArgIter += 4;
+        }
+        else if (aTrsfArg.StartsWith ("-location")
+              || aTrsfArg.StartsWith ("-loc"))
+        {
+          isTrsfSet = Standard_True;
+          if (aTrsfArgIter + 3 >= theArgNb
+          || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aTrsfArgIter += 3;
+        }
+        else if (aTrsfArg.StartsWith ("-scale"))
+        {
+          isTrsfSet = Standard_True;
+          if (++aTrsfArgIter >= theArgNb)
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+
+          const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
+          if (!aScaleStr.IsRealValue())
+          {
+            std::cout << "Syntax error at " << aTrsfArg << ".\n";
+            return 1;
+          }
+          aScales[anIndex] = aScaleStr.RealValue();
+        }
+        else
+        {
+          anArgIter = aTrsfArgIter - 1;
+          break;
+        }
+      }
+      if (!isTrsfSet)
       {
-        di << "Bad depth; Usage : " << argv[0] << " [mode] [depth width]" << "\n"
-        << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
+        std::cout << "Syntax error at " << anArg << ".\n";
         return 1;
       }
-      if(aWidth<0. || aWidth>1.)
+      else if (aTrsfArgIter >= theArgNb)
+      {
+        anArgIter = theArgNb;
+      }
+
+      aTrsfs[0].SetRotation        (aRotQuats[0]);
+      aTrsfs[1].SetRotation        (aRotQuats[1]);
+      aTrsfs[0].SetTranslationPart (aLocPnts[0]);
+      aTrsfs[1].SetTranslationPart (aLocPnts[1]);
+      aTrsfs[0].SetScaleFactor     (aScales[0]);
+      aTrsfs[1].SetScaleFactor     (aScales[1]);
+
+      Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
+      replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
+    }
+    else if (anArg == "-viewtrsf"
+          || anArg == "-view")
+    {
+      Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
+      if (aCamAnimation.IsNull())
+      {
+        aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
+        replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
+      }
+
+      Handle(Graphic3d_Camera) aCams[2] =
+      {
+        new Graphic3d_Camera (aCamAnimation->View()->Camera()),
+        new Graphic3d_Camera (aCamAnimation->View()->Camera())
+      };
+
+      Standard_Boolean isTrsfSet = Standard_False;
+      Standard_Integer aViewArgIter = anArgIter + 1;
+      for (; aViewArgIter < theArgNb; ++aViewArgIter)
+      {
+        TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
+        aViewArg.LowerCase();
+        const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
+        if (aViewArg.StartsWith ("-scale"))
+        {
+          isTrsfSet = Standard_True;
+          if (++aViewArgIter >= theArgNb)
+          {
+            std::cout << "Syntax error at " << anArg << ".\n";
+            return 1;
+          }
+
+          const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
+          if (!aScaleStr.IsRealValue())
+          {
+            std::cout << "Syntax error at " << aViewArg << ".\n";
+            return 1;
+          }
+          Standard_Real aScale = aScaleStr.RealValue();
+          aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
+          aCams[anIndex]->SetScale (aScale);
+        }
+        else if (aViewArg.StartsWith ("-eye")
+              || aViewArg.StartsWith ("-center")
+              || aViewArg.StartsWith ("-at")
+              || aViewArg.StartsWith ("-up"))
+        {
+          isTrsfSet = Standard_True;
+          gp_XYZ anXYZ;
+          if (aViewArgIter + 3 >= theArgNb
+          || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
+          {
+            std::cout << "Syntax error at " << aViewArg << ".\n";
+            return 1;
+          }
+          aViewArgIter += 3;
+
+          if (aViewArg.StartsWith ("-eye"))
+          {
+            aCams[anIndex]->SetEye (anXYZ);
+          }
+          else if (aViewArg.StartsWith ("-center")
+                || aViewArg.StartsWith ("-at"))
+          {
+            aCams[anIndex]->SetCenter (anXYZ);
+          }
+          else if (aViewArg.StartsWith ("-up"))
+          {
+            aCams[anIndex]->SetUp (anXYZ);
+          }
+        }
+        else
+        {
+          anArgIter = aViewArgIter - 1;
+          break;
+        }
+      }
+      if (!isTrsfSet)
       {
-        di << "Bad width; Usage : " << argv[0] << " [mode] [depth width]" << "\n"
-        << "mode = OFF|BACK|FRONT|SLICE depth = [0..1] width = [0..1]" << "\n";
+        std::cout << "Syntax error at " << anArg << ".\n";
         return 1;
       }
+      else if (aViewArgIter >= theArgNb)
+      {
+        anArgIter = theArgNb;
+      }
+
+      aCamAnimation->SetCameraStart(aCams[0]);
+      aCamAnimation->SetCameraEnd  (aCams[1]);
+    }
+    else
+    {
+      std::cout << "Syntax error at " << anArg << ".\n";
+      return 1;
+    }
+  }
+
+  if (!toPlay)
+  {
+    return 0;
+  }
+
+  // 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)
+  {
+    aView->Camera()->Copy (aCameraBack);
+  }
+
+  const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
+  if (aFpsNum <= 0)
+  {
+    while (!anAnimation->IsStopped())
+    {
+      aCameraBack->Copy (aView->Camera());
+      const Standard_Real aPts = anAnimation->UpdateTimer();
+      if (isFreeCamera)
+      {
+        aView->Camera()->Copy (aCameraBack);
+      }
+
+      if (aPts >= anUpperPts)
+      {
+        anAnimation->Pause();
+        break;
+      }
+
+      if (aView->IsInvalidated())
+      {
+        aView->Redraw();
+      }
+      else
+      {
+        aView->RedrawImmediate();
+      }
+
+      if (!isLockLoop)
+      {
+        // handle user events
+        theDI.Eval ("after 1 set waiter 1");
+        theDI.Eval ("vwait waiter");
+      }
+      if (!TheIsAnimating)
+      {
+        anAnimation->Pause();
+        theDI << aPts;
+        break;
+      }
+    }
+
+    if (aView->IsInvalidated())
+    {
+      aView->Redraw();
+    }
+    else
+    {
+      aView->RedrawImmediate();
+    }
+  }
+  else
+  {
+    OSD_Timer aPerfTimer;
+    aPerfTimer.Start();
+
+    // 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;
+      }
 
-      aView->SetZClippingDepth(aDepth);
-      aView->SetZClippingWidth(aWidth);
+      aView->Redraw();
     }
+
+    aPerfTimer.Stop();
+    anAnimation->Stop();
+    const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
+    theDI << "Average FPS: " << aRecFps << "\n"
+          << "Nb. Frames: "  << Standard_Real(aNbFrames);
+
     aView->Redraw();
   }
+
+  aView->SetImmediateUpdate (wasImmediateUpdate);
+  TheIsAnimating = Standard_False;
   return 0;
 }
 
+
 //=======================================================================
-//function : VNbSelected
-//purpose  : Returns number of selected objects
+//function : VChangeSelected
+//purpose  : Adds the shape to selection or remove one from it
 //=======================================================================
-static Standard_Integer VNbSelected (Draw_Interpretor& di,
+static Standard_Integer VChangeSelected (Draw_Interpretor& di,
                                 Standard_Integer argc,
                                 const char ** argv)
 {
-  if(argc != 1)
+  if(argc != 2)
   {
-    di << "Usage : " << argv[0] << "\n";
+    di<<"Usage : " << argv[0] << " shape \n";
     return 1;
   }
+  //get AIS_Shape:
   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
-  if(aContext.IsNull())
+  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
+  TCollection_AsciiString aName(argv[1]);
+  Handle(AIS_InteractiveObject) anAISObject;
+
+  if(!aMap.IsBound2(aName))
   {
-    di << "use 'vinit' command before " << argv[0] << "\n";
+    di<<"Use 'vdisplay' before";
     return 1;
   }
-  di << aContext->NbSelected() << "\n";
+  else
+  {
+    anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
+    if(anAISObject.IsNull()){
+      di<<"No interactive object \n";
+      return 1;
+    }
+
+    aContext->AddOrRemoveSelected(anAISObject);
+  }
   return 0;
 }
 
 //=======================================================================
-//function : VAntialiasing
-//purpose  : Switches altialiasing on or off
+//function : VNbSelected
+//purpose  : Returns number of selected objects
 //=======================================================================
-static Standard_Integer VAntialiasing (Draw_Interpretor& di,
+static Standard_Integer VNbSelected (Draw_Interpretor& di,
                                 Standard_Integer argc,
                                 const char ** argv)
 {
-  if(argc > 2)
+  if(argc != 1)
   {
-    di << "Usage : " << argv[0] << " [1|0]" << "\n";
+    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;
   }
-
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-
-  if((argc == 2) && (atof(argv[1]) == 0))
-    aView->SetAntialiasingOff();
-  else
-    aView->SetAntialiasingOn();
-  aView->Update();
+  di << aContext->NbSelected() << "\n";
   return 0;
 }
 
@@ -6281,7 +6987,7 @@ static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
     di << "use 'vinit' command before " << argv[0] << "\n";
     return 1;
   }
-  aContext->CloseAllContexts(Standard_False);
+
   di << aContext->PurgeDisplay() << "\n";
   return 0;
 }
@@ -6431,12 +7137,9 @@ public:
                             const Standard_ShortReal theXShift,
                             const Standard_ShortReal theYShift,
                             const Standard_ShortReal theAngle);
-  DEFINE_STANDARD_RTTI(OCC_TextureEnv, Graphic3d_TextureEnv);
+  DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
 };
-DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv);
-
-
-
+DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
 
 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
   : Graphic3d_TextureEnv(theFileName)
@@ -6545,11 +7248,9 @@ static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb,
         );
     }
     aView->SetTextureEnv(aTexEnv);
-    aView->SetSurfaceDetail(V3d_TEX_ENVIRONMENT);
   }
   else // Disabling environment mapping
   {
-    aView->SetSurfaceDetail(V3d_TEX_NONE);
     Handle(Graphic3d_TextureEnv) aTexture;
     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
   }
@@ -6558,6 +7259,40 @@ static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb,
   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  :
@@ -6565,425 +7300,487 @@ static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb,
 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
-  typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
   static MapOfPlanes aRegPlanes;
 
   if (theArgsNb < 2)
   {
-    theDi << theArgVec[0] << ": command argument is required. Type help for more information.\n";
-    return 1;
+    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")
+  if (aCommand == "-maxplanes"
+   || aCommand == "maxplanes")
   {
-    if (theArgsNb < 3)
-    {
-      theDi << theArgVec[0] << ": view name is required. Type help for more information.\n";
-      return 1;
-    }
-
-    TCollection_AsciiString aViewName (theArgVec[2]);
-
-    if (!ViewerTest_myViews.IsBound1 (aViewName))
-    {
-      theDi << theArgVec[0] << ": view is not found.\n";
-      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";
-
+    theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
+          << " plane slots provided by driver.\n";
     return 0;
   }
 
   // create / delete plane instance
-  if (aCommand == "create" || aCommand == "delete" || aCommand == "clone")
+  if (aCommand == "-create"
+   || aCommand == "create"
+   || aCommand == "-delete"
+   || aCommand == "delete"
+   || aCommand == "-clone"
+   || aCommand == "clone")
   {
     if (theArgsNb < 3)
     {
-      theDi << theArgVec[0] << ": plane name is required. Type help for more information.\n";
+      std::cout << "Syntax error: plane name is required.\n";
       return 1;
     }
 
-    Standard_Boolean toCreate = (aCommand == "create");
-    Standard_Boolean toClone  = (aCommand == "clone");
+    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))
       {
-        theDi << theArgVec[0] << ": plane name is in use.\n";
-        return 1;
+        std::cout << "Warning: existing plane has been overridden.\n";
+        toDelete = true;
+      }
+      else
+      {
+        aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
+        return 0;
       }
-
-      aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
     }
     else if (toClone) // toClone
     {
       if (!aRegPlanes.IsBound (aPlane))
       {
-        theDi << theArgVec[0] << ": no such plane.\n";
+        std::cout << "Error: no such plane.\n";
         return 1;
       }
-
-      if (theArgsNb < 4)
+      else if (theArgsNb < 4)
       {
-        theDi << theArgVec[0] << ": enter name for new plane. Type help for more information.\n";
+        std::cout << "Syntax error: enter name for new plane.\n";
         return 1;
       }
 
       TCollection_AsciiString aClone (theArgVec[3]);
       if (aRegPlanes.IsBound (aClone))
       {
-        theDi << theArgVec[0] << ": plane name is in use.\n";
+        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;
     }
-    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);
-
-      ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
-      for (; anIObjIt.More(); anIObjIt.Next())
+    if (toDelete)
+    {
+      if (aPlane == "ALL"
+       || aPlane == "all"
+       || aPlane == "*")
       {
-        Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
-        aPrs->RemoveClipPlane(aClipPlane);
+        for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
+        {
+          aPlane = aPlaneIter.Key();
+          removePlane (aRegPlanes, aPlane);
+          aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
+        }
       }
-
-      NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
-      for (; aViewIt.More(); aViewIt.Next())
+      else
       {
-        const Handle(V3d_View)& aView = aViewIt.Key2();
-        aView->RemoveClipPlane(aClipPlane);
+        removePlane (aRegPlanes, aPlane);
       }
-
-      ViewerTest::RedrawAllViews();
     }
 
+    if (toCreate)
+    {
+      aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
+    }
     return 0;
   }
 
   // set / unset plane command
-  if (aCommand == "set" || aCommand == "unset")
+  if (aCommand == "set"
+   || aCommand == "unset")
   {
-    if (theArgsNb < 4)
-    {
-      theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-      return 1;
-    }
-
-    Standard_Boolean toSet = (aCommand == "set");
-    TCollection_AsciiString aPlane (theArgVec [2]);
-    if (!aRegPlanes.IsBound (aPlane))
-    {
-      theDi << theArgVec[0] << ": no such plane.\n";
-      return 1;
-    }
-
-    const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
-
-    TCollection_AsciiString aTarget (theArgVec [3]);
-    if (aTarget != "object" && aTarget != "view")
+    if (theArgsNb < 5)
     {
-      theDi << theArgVec[0] << ": invalid target.\n";
+      std::cout << "Syntax error: need more arguments.\n";
       return 1;
     }
 
-    if (aTarget == "object" || aTarget == "view")
+    // 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)
     {
-      if (theArgsNb < 5)
-      {
-        theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-        return 1;
-      }
-
-      Standard_Boolean isObject = (aTarget == "object");
-
-      for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
-      {
-        TCollection_AsciiString anEntityName (theArgVec[anIt]);
-        if (isObject) // to object
-        {
-          if (!GetMapOfAIS().IsBound2 (anEntityName))
-          {
-            theDi << theArgVec[0] << ": can not find IO with name " << anEntityName << ".\n";
-            continue;
-          }
-
-          Handle(AIS_InteractiveObject) aIObj =
-            Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
-
-          if (toSet)
-            aIObj->AddClipPlane (aClipPlane);
-          else
-            aIObj->RemoveClipPlane (aClipPlane);
-        }
-        else // to view
-        {
-          if (!ViewerTest_myViews.IsBound1 (anEntityName))
-          {
-            theDi << theArgVec[0] << ": can not find View with name " << anEntityName << ".\n";
-            continue;
-          }
-
-          Handle(V3d_View) aView = ViewerTest_myViews.Find1(anEntityName);
-          if (toSet)
-            aView->AddClipPlane (aClipPlane);
-          else
-            aView->RemoveClipPlane (aClipPlane);
-        }
-      }
-
-      ViewerTest::RedrawAllViews();
+      anArgVec.SetValue (anIt, theArgVec[anIt]);
     }
 
-    return 0;
+    return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
   }
 
   // change plane command
-  if (aCommand == "change")
+  TCollection_AsciiString aPlaneName;
+  Handle(Graphic3d_ClipPlane) aClipPlane;
+  Standard_Integer anArgIter = 0;
+  if (aCommand == "-change"
+   || aCommand == "change")
   {
-    if (theArgsNb < 4)
+    // old syntax support
+    if (theArgsNb < 3)
     {
-      theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
+      std::cout << "Syntax error: need more arguments.\n";
       return 1;
     }
 
-    TCollection_AsciiString aPlane (theArgVec [2]);
-    if (!aRegPlanes.IsBound (aPlane))
+    anArgIter  = 3;
+    aPlaneName = theArgVec[2];
+    if (!aRegPlanes.Find (aPlaneName, aClipPlane))
     {
-      theDi << theArgVec[0] << ": no such plane.\n";
+      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";
+  }
 
-    const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
+  if (theArgsNb - anArgIter < 1)
+  {
+    std::cout << "Syntax error: need more arguments.\n";
+    return 1;
+  }
 
-    TCollection_AsciiString aChangeArg (theArgVec [3]);
-    if (aChangeArg != "on" && aChangeArg != "off" && aChangeArg != "capping" && aChangeArg != "equation")
-    {
-      theDi << theArgVec[0] << ": invalid arguments. Type help for more information.\n";
-      return 1;
-    }
+  for (; anArgIter < theArgsNb; ++anArgIter)
+  {
+    const char**     aChangeArgs   = theArgVec + anArgIter;
+    Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
+    TCollection_AsciiString aChangeArg (aChangeArgs[0]);
+    aChangeArg.LowerCase();
 
-    if (aChangeArg == "on" || aChangeArg == "off") // on / off
+    Standard_Boolean toEnable = Standard_True;
+    if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
     {
-      aClipPlane->SetOn (aChangeArg == "on");
+      aClipPlane->SetOn (toEnable);
     }
-    else if (aChangeArg == "equation") // change equation
+    else if (aChangeArg == "-equation"
+          || aChangeArg == "equation")
     {
-      if (theArgsNb < 8)
+      if (aNbChangeArgs < 5)
       {
-        theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
+        std::cout << "Syntax error: need more arguments.\n";
         return 1;
       }
 
-      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]);
+      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") // change capping aspects
+    else if (aChangeArg == "-capping"
+          || aChangeArg == "capping")
     {
-      if (theArgsNb < 5)
+      if (aNbChangeArgs < 2)
       {
-        theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
+        std::cout << "Syntax error: need more arguments.\n";
         return 1;
       }
 
-      TCollection_AsciiString aCappingArg (theArgVec [4]);
-      if (aCappingArg != "on" && aCappingArg != "off" &&
-          aCappingArg != "color" && aCappingArg != "texname" &&
-          aCappingArg != "texscale" && aCappingArg != "texorigin" &&
-          aCappingArg != "texrotate" && aCappingArg != "hatch")
+      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)
       {
-        theDi << theArgVec[0] << ": invalid arguments. Type help for more information.\n";
+        std::cout << "Syntax error: need more arguments.\n";
         return 1;
       }
 
-      if (aCappingArg == "on" || aCappingArg == "off") // on / off capping
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
       {
-        aClipPlane->SetCapping (aCappingArg == "on");
+        aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
+        anArgIter += 1;
       }
-      else if (aCappingArg == "color") // color aspect for capping
+    }
+    else if (aChangeArg == "-useobjecttexture"
+          || aChangeArg == "-useobjecttex"
+          || aChangeArg == "-useobjtexture"
+          || aChangeArg == "-useobjtex")
+    {
+      if (aNbChangeArgs < 2)
       {
-        if (theArgsNb < 8)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
-
-        Standard_Real aRed = Draw::Atof (theArgVec [5]);
-        Standard_Real aGrn = Draw::Atof (theArgVec [6]);
-        Standard_Real aBlu = Draw::Atof (theArgVec [7]);
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
 
-        Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
-        Quantity_Color aColor (aRed, aGrn, aBlu, Quantity_TOC_RGB);
-        aMat.SetAmbientColor (aColor);
-        aMat.SetDiffuseColor (aColor);
-        aClipPlane->SetCappingMaterial (aMat);
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
+      {
+        aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
+        anArgIter += 1;
       }
-      else if (aCappingArg == "texname") // texture name
+    }
+    else if (aChangeArg == "-useobjectshader"
+          || aChangeArg == "-useobjshader")
+    {
+      if (aNbChangeArgs < 2)
       {
-        if (theArgsNb < 6)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
-
-        TCollection_AsciiString aTextureName (theArgVec [5]);
+        std::cout << "Syntax error: need more arguments.\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);
-        }
+      if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
+      {
+        aClipPlane->SetUseObjectShader (toEnable == Standard_True);
+        anArgIter += 1;
       }
-      else if (aCappingArg == "texscale") // texture scale
+    }
+    else if (aChangeArg == "-color"
+          || aChangeArg == "color")
+    {
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
+                                                           aChangeArgs + 1,
+                                                           aColor);
+      if (aNbParsed == 0)
       {
-        if (aClipPlane->CappingTexture().IsNull())
-        {
-          theDi << theArgVec[0] << ": no texture is set.\n";
-          return 1;
-        }
-
-        if (theArgsNb < 7)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
 
-        Standard_ShortReal aSx = (Standard_ShortReal)atof (theArgVec [5]);
-        Standard_ShortReal aSy = (Standard_ShortReal)atof (theArgVec [6]);
+      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;
+      }
 
-        aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
+      TCollection_AsciiString aTextureName (aChangeArgs[1]);
+      Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
+      if (!aTexture->IsDone())
+      {
+        aClipPlane->SetCappingTexture (NULL);
       }
-      else if (aCappingArg == "texorigin") // texture origin
+      else
       {
-        if (aClipPlane->CappingTexture().IsNull())
-        {
-          theDi << theArgVec[0] << ": no texture is set.\n";
-          return 1;
-        }
-
-        if (theArgsNb < 7)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
-
-        Standard_ShortReal aTx = (Standard_ShortReal)atof (theArgVec [5]);
-        Standard_ShortReal aTy = (Standard_ShortReal)atof (theArgVec [6]);
-
-        aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
+        aTexture->EnableModulate();
+        aTexture->EnableRepeat();
+        aClipPlane->SetCappingTexture (aTexture);
       }
-      else if (aCappingArg == "texrotate") // texture rotation
+      anArgIter += 1;
+    }
+    else if (aChangeArg == "-texscale"
+          || aChangeArg == "texscale")
+    {
+      if (aClipPlane->CappingTexture().IsNull())
       {
-        if (aClipPlane->CappingTexture().IsNull())
-        {
-          theDi << theArgVec[0] << ": no texture is set.\n";
-          return 1;
-        }
-
-        if (theArgsNb < 6)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
-
-        Standard_ShortReal aRot = (Standard_ShortReal)atof (theArgVec[5]);
+        std::cout << "Error: no texture is set.\n";
+        return 1;
+      }
 
-        aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
+      if (aNbChangeArgs < 3)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
       }
-      else if (aCappingArg == "hatch") // hatch style
+
+      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())
       {
-        if (theArgsNb < 6)
-        {
-          theDi << theArgVec[0] << ": need more arguments. Type help for more information.\n";
-          return 1;
-        }
+        std::cout << "Error: no texture is set.\n";
+        return 1;
+      }
 
-        TCollection_AsciiString aHatchStr (theArgVec [5]);
-        if (aHatchStr == "on")
-        {
-          aClipPlane->SetCappingHatchOn();
-        }
-        else if (aHatchStr == "off")
-        {
-          aClipPlane->SetCappingHatchOff();
-        }
-        else
-        {
-          aClipPlane->SetCappingHatch ((Aspect_HatchStyle)atoi (theArgVec[5]));
-        }
+      if (aNbChangeArgs < 3)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
       }
-    }
 
-    ViewerTest::RedrawAllViews();
+      Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
+      Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
 
-    return 0;
-  }
+      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;
+      }
 
-  theDi << theArgVec[0] << ": invalid command. Type help for more information.\n";
-  return 1;
-}
+      if (aNbChangeArgs < 2)
+      {
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
+      }
 
-//===============================================================================================
-//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;
-  }
+      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 aViewName (theArgVec[1]);
-  if (!ViewerTest_myViews.IsBound1 (aViewName))
-  {
-    theDi << theArgVec[0] << ": view is not found.\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;
+        }
+      }
 
-  const Handle(V3d_View)& aView = ViewerTest_myViews.Find1 (aViewName);
-  switch (atoi (theArgVec[2]))
-  {
-    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";
+      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;
+    }
   }
 
-  aView->Redraw();
+  ViewerTest::RedrawAllViews();
   return 0;
 }
 
@@ -7065,7 +7862,7 @@ static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const
 
   if (theArgsNb < 2)
   {
-    theDi << "Auto z-fit mode: " << "\n"
+    theDi << "Auto z-fit mode: \n"
           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
           << "Scale: " << aScale << "\n";
     return 0;
@@ -7729,9 +8526,9 @@ static int VLight (Draw_Interpretor& theDi,
   {
     // print lights info
     Standard_Integer aLightId = 0;
-    for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightId)
+    for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
     {
-      Handle(V3d_Light) aLight = aView->ActiveLight();
+      Handle(V3d_Light) aLight = aLightIter.Value();
       const Quantity_Color aColor = aLight->Color();
       theDi << "Light" << aLightId << "\n";
       switch (aLight->Type())
@@ -7841,963 +8638,1700 @@ static int VLight (Draw_Interpretor& theDi,
       toCreate = Standard_False;
       aViewer->SetDefaultLights();
     }
-    else if (anArgCase.IsEqual ("CLR")
-          || anArgCase.IsEqual ("CLEAR"))
+    else if (anArgCase.IsEqual ("CLR")
+          || anArgCase.IsEqual ("CLEAR"))
+    {
+      toCreate = Standard_False;
+      for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
+      {
+        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;
+      }
+    }
+    else if (anArgCase.IsEqual ("DIR")
+          || anArgCase.IsEqual ("DIRECTION"))
+    {
+      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->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
+      }
+      else if (!aLightSpot.IsNull())
+      {
+        aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
+      }
+      else
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+    }
+    else if (anArgCase.IsEqual ("SM")
+          || anArgCase.IsEqual ("SMOOTHNESS"))
+    {
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
+
+      if (fabs (aSmoothness) < Precision::Confusion())
+      {
+        aLightCurr->SetIntensity (1.f);
+      }
+      else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
+      {
+        aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
+      }
+      else
+      {
+        Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
+        aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
+      }
+
+      if (!aLightPos.IsNull())
+      {
+        aLightPos->SetSmoothRadius (aSmoothness);
+      }
+      else if (!aLightDir.IsNull())
+      {
+        aLightDir->SetSmoothAngle (aSmoothness);
+      }
+    }
+    else if (anArgCase.IsEqual ("INT")
+          || anArgCase.IsEqual ("INTENSITY"))
+    {
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        return 1;
+      }
+
+      Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
+
+      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_Real anAngle = Atof (theArgVec[anArgIt]);
+
+      if (!aLightSpot.IsNull())
+      {
+        aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
+      }
+    }
+    else if (anArgCase.IsEqual ("CONSTATTEN")
+          || anArgCase.IsEqual ("CONSTATTENUATION"))
+    {
+      if (++anArgIt >= theArgsNb)
+      {
+        std::cerr << "Wrong syntax at argument '" << anArg << "'!\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;
+      }
+    }
+    else if (anArgCase.IsEqual ("LINATTEN")
+          || anArgCase.IsEqual ("LINEARATTEN")
+          || anArgCase.IsEqual ("LINEARATTENUATION"))
+    {
+      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 (anArgCase.IsEqual ("EXP")
+          || anArgCase.IsEqual ("EXPONENT")
+          || anArgCase.IsEqual ("SPOTEXP")
+          || anArgCase.IsEqual ("SPOTEXPONENT"))
+    {
+      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 (anArgCase.IsEqual ("HEAD")
+          || anArgCase.IsEqual ("HEADLIGHT"))
+    {
+      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 << "'\n";
+    }
+  }
+
+  addLight (aLightNew, isGlobal);
+  aViewer->UpdateLights();
+
+  return 0;
+}
+
+//=======================================================================
+//function : VRenderParams
+//purpose  : Enables/disables rendering features
+//=======================================================================
+
+static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
+                                       Standard_Integer  theArgNb,
+                                       const char**      theArgVec)
+{
+  Handle(V3d_View) aView = ViewerTest::CurrentView();
+  if (aView.IsNull())
+  {
+    std::cerr << "Error: no active viewer!\n";
+    return 1;
+  }
+
+  Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
+  TCollection_AsciiString aCmdName (theArgVec[0]);
+  aCmdName.LowerCase();
+  if (aCmdName == "vraytrace")
+  {
+    if (theArgNb == 1)
+    {
+      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")
+      {
+        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;
+      }
+    }
+    else
+    {
+      std::cout << "Error: wrong number of arguments\n";
+      return 1;
+    }
+  }
+
+  if (theArgNb < 2)
+  {
+    theDI << "renderMode:  ";
+    switch (aParams.Method)
+    {
+      case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
+      case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
+    }
+    theDI << "\n";
+    theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
+    theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
+    theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
+    theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
+    theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
+    theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
+    theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
+    theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
+    theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
+    theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
+    theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
+    theDI << "shadingModel: ";
+    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;
+    }
+    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))
+    {
+      continue;
+    }
+    else if (aFlag == "-echo"
+          || aFlag == "-print")
+    {
+      toPrint = Standard_True;
+      anUpdateTool.Invalidate();
+    }
+    else if (aFlag == "-mode"
+          || aFlag == "-rendermode"
+          || aFlag == "-render_mode")
+    {
+      if (toPrint)
+      {
+        switch (aParams.Method)
+        {
+          case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
+          case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
+        }
+        continue;
+      }
+      else
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\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;
+    }
+    else if (aFlag == "-rast"
+          || aFlag == "-raster"
+          || aFlag == "-rasterization")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
+        continue;
+      }
+
+      aParams.Method = Graphic3d_RM_RASTERIZATION;
+    }
+    else if (aFlag == "-msaa")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.NbMsaaSamples << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
+      if (aNbSamples < 0)
+      {
+        std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
+        return 1;
+      }
+      else
+      {
+        aParams.NbMsaaSamples = aNbSamples;
+      }
+    }
+    else if (aFlag == "-raydepth"
+          || aFlag == "-ray_depth")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.RaytracingDepth << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      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 << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
+        return 1;
+      }
+      else
+      {
+        aParams.RaytracingDepth = aDepth;
+      }
+    }
+    else if (aFlag == "-shad"
+          || aFlag == "-shadows")
     {
-      toCreate = Standard_False;
-      aView->InitActiveLights();
-      while (aView->MoreActiveLights())
+      if (toPrint)
+      {
+        theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        aViewer->DelLight (aView->ActiveLight());
-        aView->InitActiveLights();
+        --anArgIter;
       }
+      aParams.IsShadowEnabled = toEnable;
     }
-    else if (anArgCase.IsEqual ("AMB")
-          || anArgCase.IsEqual ("AMBIENT")
-          || anArgCase.IsEqual ("AMBLIGHT"))
+    else if (aFlag == "-refl"
+          || aFlag == "-reflections")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
+        continue;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_AmbientLight (aViewer);
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.IsReflectionEnabled = toEnable;
     }
-    else if (anArgCase.IsEqual ("DIRECTIONAL")
-          || anArgCase.IsEqual ("DIRLIGHT"))
+    else if (aFlag == "-fsaa")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
+        continue;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_DirectionalLight (aViewer);
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.IsAntialiasingEnabled = toEnable;
     }
-    else if (anArgCase.IsEqual ("SPOT")
-          || anArgCase.IsEqual ("SPOTLIGHT"))
+    else if (aFlag == "-gleam")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
+        continue;
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.IsTransparentShadowEnabled = toEnable;
     }
-    else if (anArgCase.IsEqual ("POSLIGHT")
-          || anArgCase.IsEqual ("POSITIONAL"))
+    else if (aFlag == "-gi")
     {
-      addLight (aLightNew, isGlobal);
-      if (!toCreate)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.IsGlobalIlluminationEnabled = toEnable;
+      if (!toEnable)
+      {
+        aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
       }
-      toCreate  = Standard_False;
-      aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
     }
-    else if (anArgCase.IsEqual ("CHANGE"))
+    else if (aFlag == "-blockedrng"
+          || aFlag == "-brng")
     {
-      addLight (aLightNew, isGlobal);
-      aLightNew.Nullify();
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
+        continue;
       }
 
-      const Standard_Integer aLightId = 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))
       {
-        if (aLightIt == aLightId)
-        {
-          aLightOld = aView->ActiveLight();
-          break;
-        }
+        --anArgIter;
+      }
+      aParams.CoherentPathTracingMode = toEnable;
+    }
+    else if (aFlag == "-iss")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
+        continue;
       }
 
-      if (aLightOld.IsNull())
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
-        return 1;
+        --anArgIter;
       }
+      aParams.AdaptiveScreenSampling = toEnable;
     }
-    else if (anArgCase.IsEqual ("DEL")
-          || anArgCase.IsEqual ("DELETE"))
+    else if (aFlag == "-issd")
     {
-      Handle(V3d_Light) aLightDel;
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.ShowSamplingTiles ? "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.ShowSamplingTiles = toEnable;
+    }
+    else if (aFlag == "-env")
+    {
+      if (toPrint)
       {
-        aViewer->DelLight (aLightDel);
+        theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
       }
+      aParams.UseEnvironmentMapBackground = toEnable;
     }
-    else if (anArgCase.IsEqual ("COLOR")
-          || anArgCase.IsEqual ("COLOUR"))
+    else if (aFlag == "-twoside")
     {
-      if (++anArgIt >= theArgsNb)
+      if (toPrint)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
+        theDI << (aParams.TwoSidedBsdfModels ? "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.TwoSidedBsdfModels = toEnable;
     }
-    else if (anArgCase.IsEqual ("POS")
-          || anArgCase.IsEqual ("POSITION"))
+    else if (aFlag == "-shademodel"
+          || aFlag == "-shadingmodel"
+          || aFlag == "-shading")
     {
-      if ((anArgIt + 3) >= 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;
       }
 
-      anXYZ[0] = Atof (theArgVec[++anArgIt]);
-      anXYZ[1] = Atof (theArgVec[++anArgIt]);
-      anXYZ[2] = Atof (theArgVec[++anArgIt]);
-      if (!aLightDir.IsNull())
+      if (++anArgIter >= theArgNb)
       {
-        aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
       }
-      else if (!aLightPos.IsNull())
+
+      TCollection_AsciiString aMode (theArgVec[anArgIter]);
+      aMode.LowerCase();
+      if (aMode == "color"
+       || aMode == "none")
       {
-        aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+        aView->SetShadingModel (V3d_COLOR);
       }
-      else if (!aLightSpot.IsNull())
+      else if (aMode == "flat"
+            || aMode == "facet")
       {
-        aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
+        aView->SetShadingModel (V3d_FLAT);
+      }
+      else if (aMode == "gouraud"
+            || aMode == "vertex"
+            || aMode == "vert")
+      {
+        aView->SetShadingModel (V3d_GOURAUD);
+      }
+      else if (aMode == "phong"
+            || aMode == "fragment"
+            || aMode == "frag"
+            || aMode == "pixel")
+      {
+        aView->SetShadingModel (V3d_PHONG);
       }
       else
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        std::cout << "Error: unknown shading model '" << aMode << "'\n";
         return 1;
       }
     }
-    else if (anArgCase.IsEqual ("DIR")
-          || anArgCase.IsEqual ("DIRECTION"))
+    else if (aFlag == "-resolution")
     {
-      if ((anArgIt + 3) >= theArgsNb)
+      if (++anArgIter >= theArgNb)
       {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
+        std::cerr << "Error: 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->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
-      }
-      else if (!aLightSpot.IsNull())
+      TCollection_AsciiString aResolution (theArgVec[anArgIter]);
+      if (aResolution.IsIntegerValue())
       {
-        aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
+        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 ("SM")
-          || anArgCase.IsEqual ("SMOOTHNESS"))
+    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;
       }
 
-      Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
-
-      if (fabs (aSmoothness) < Precision::Confusion())
-      {
-        aLightCurr->SetIntensity (1.f);
-      }
-      else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
-      {
-        aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
-      }
-      else
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+          && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
       {
-        Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
-        aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
+        --anArgIter;
       }
+      aParams.RebuildRayTracingShaders = toEnable;
+    }
+    else
+    {
+      std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
+      return 1;
+    }
+  }
 
-      if (!aLightPos.IsNull())
-      {
-        aLightPos->SetSmoothRadius (aSmoothness);
-      }
-      else if (!aLightDir.IsNull())
+  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))
       {
-        aLightDir->SetSmoothAngle (aSmoothness);
+        toExit = Standard_True;
       }
+
+      TranslateMessage (&aMsg);
+      DispatchMessageW (&aMsg);
     }
-    else if (anArgCase.IsEqual ("INT")
-          || anArgCase.IsEqual ("INTENSITY"))
+
+    if (toExit)
     {
-      if (++anArgIt >= theArgsNb)
-      {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
-      }
+      break;
+    }
+  }
+
+  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());
 
-      Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
+    aContext->SetLocation (anIObj, aTransform);
+    aContext->UpdateCurrentViewer();
+  }
 
-      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;
-      }
+  return 0;
+}
 
-      Standard_Real anAngle = Atof (theArgVec[anArgIt]);
+//===============================================================================================
+//class   : ViewerTest_AISManipulator
+//purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
+//===============================================================================================
+DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
 
-      if (!aLightSpot.IsNull())
-      {
-        aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
-      }
-    }
-    else if (anArgCase.IsEqual ("CONSTATTEN")
-          || anArgCase.IsEqual ("CONSTATTENUATION"))
-    {
-      if (++anArgIt >= theArgsNb)
-      {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
-      }
+class ViewerTest_AISManipulator : public AIS_Manipulator
+{
+public:
 
-      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;
-      }
-    }
-    else if (anArgCase.IsEqual ("LINATTEN")
-          || anArgCase.IsEqual ("LINEARATTEN")
-          || anArgCase.IsEqual ("LINEARATTENUATION"))
-    {
-      if (++anArgIt >= theArgsNb)
-      {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
-      }
+  ViewerTest_AISManipulator() : AIS_Manipulator()
+  {
+    GetMapOfAISManipulators().Add (this);
+  }
 
-      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 (anArgCase.IsEqual ("EXP")
-          || anArgCase.IsEqual ("EXPONENT")
-          || anArgCase.IsEqual ("SPOTEXP")
-          || anArgCase.IsEqual ("SPOTEXPONENT"))
-    {
-      if (++anArgIt >= theArgsNb)
-      {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
-      }
+  virtual ~ViewerTest_AISManipulator()
+  {
+    GetMapOfAISManipulators().Remove (this);
+  }
 
-      if (!aLightSpot.IsNull())
-      {
-        aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
-      }
-      else
-      {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
-      }
-    }
-    else if (anArgCase.IsEqual ("HEAD")
-          || anArgCase.IsEqual ("HEADLIGHT"))
-    {
-      if (++anArgIt >= theArgsNb)
-      {
-        std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
-        return 1;
-      }
+  DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
+};
 
-      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 << "'\n";
-    }
+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;
   }
 
-  addLight (aLightNew, isGlobal);
-  aViewer->UpdateLights();
+  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)
-    {
-      theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
-      return 0;
-    }
-    else if (theArgNb == 2)
+    if (!aMapAIS.IsBound2 (aName))
     {
-      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: could not find \"" << aName << "\" AIS object.\n";
+      return 1;
     }
-    else
+
+    Handle(AIS_Manipulator) 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;
     }
+
+    aManipulator->Detach();
+    aMapAIS.UnBind2 (aName);
+    ViewerTest::GetAISContext()->Remove (aManipulator);
+
+    return 0;
   }
 
-  if (theArgNb < 2)
+  // -----------------------------------------------
+  // find or create manipulator if it does not exist
+  // -----------------------------------------------
+
+  Handle(AIS_Manipulator) aManipulator;
+  if (!aMapAIS.IsBound2 (aName))
   {
-    theDI << "renderMode:  ";
-    switch (aParams.Method)
+    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())
     {
-      case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
-      case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
+      std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
+      return 1;
     }
-    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 << "shadingModel: ";
-    switch (aView->ShadingModel())
+  }
+
+  // -----------------------------------------
+  // change properties of manipulator instance
+  // -----------------------------------------
+
+  if (aCmd.HasOption ("autoActivate", 1, Standard_True))
+  {
+    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 V3d_COLOR:   theDI << "color";   break;
-      case V3d_FLAT:    theDI << "flat";    break;
-      case V3d_GOURAUD: theDI << "gouraud"; break;
-      case V3d_PHONG:   theDI << "phong";   break;
+      std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
+      return 1;
     }
-    theDI << "\n";
-    return 0;
+
+    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();
 
-  Standard_Boolean toPrint = Standard_False;
-  ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
-  for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+    aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
+  }
+  if (aCmd.HasOption ("size", 1, Standard_True))
   {
-    Standard_CString        anArg (theArgVec[anArgIter]);
-    TCollection_AsciiString aFlag (anArg);
-    aFlag.LowerCase();
-    if (anUpdateTool.parseRedrawMode (aFlag))
+    aManipulator->SetSize (aCmd.ArgFloat ("size"));
+  }
+  if (aCmd.HasOption ("zoomable", 1, Standard_True))
+  {
+    aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
+
+    if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
+    {
+      ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
+      ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
+    }
+  }
+
+  // ---------------------------------------------------
+  // attach, detach or access manipulator from an object
+  // ---------------------------------------------------
+
+  if (aCmd.HasOption ("attach"))
+  {
+    // 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)
+      if (anIt.Value()->IsAttached()
+       && anIt.Value()->Object() == anObject)
       {
-        switch (aParams.Method)
-        {
-          case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
-          case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
-        }
-        continue;
-      }
-      else
-      {
-        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;
-    }
-    else if (aFlag == "-rast"
-          || aFlag == "-raster"
-          || aFlag == "-rasterization")
+    AIS_Manipulator::OptionsForAttach anOptions;
+    if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
     {
-      if (toPrint)
-      {
-        theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
-        continue;
-      }
-
-      aParams.Method = Graphic3d_RM_RASTERIZATION;
+      anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
     }
-    else if (aFlag == "-msaa")
+    if (aCmd.HasOption ("adjustSize", 1, Standard_True))
     {
-      if (toPrint)
-      {
-        theDI << aParams.NbMsaaSamples << " ";
-        continue;
-      }
-      else if (++anArgIter >= theArgNb)
-      {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
-        return 1;
-      }
-
-      const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
-      if (aNbSamples < 0)
-      {
-        std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
-        return 1;
-      }
-      else
-      {
-        aParams.NbMsaaSamples = aNbSamples;
-      }
+      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]);
+    aManipulator->Attach (anObject, anOptions);
+  }
 
-      // We allow RaytracingDepth be more than 10 in case of GI enabled
-      if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
-      {
-        std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
-        return 1;
-      }
-      else
-      {
-        aParams.RaytracingDepth = aDepth;
-      }
+  // --------------------------------------
+  // 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")
     {
-      if (toPrint)
-      {
-        theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
-        continue;
-      }
-
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.IsShadowEnabled = toEnable;
+      aType = Prs3d_TypeOfHighlight_LocalDynamic;
     }
-    else if (aFlag == "-refl"
-          || aFlag == "-reflections")
+    else if (anArgFirst == "selhighlight"
+          || anArgFirst == "selhilight"
+          || anArgFirst == "selectedhighlight"
+          || anArgFirst == "selectedhilight")
     {
-      if (toPrint)
-      {
-        theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
-        continue;
-      }
-
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.IsReflectionEnabled = toEnable;
+      aType = Prs3d_TypeOfHighlight_Selected;
     }
-    else if (aFlag == "-fsaa")
+    else if (anArgFirst == "localselhighlight"
+          || anArgFirst == "localselhilight"
+          || anArgFirst == "localselectedhighlight"
+          || anArgFirst == "localselectedhilight")
     {
-      if (toPrint)
-      {
-        theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
-        continue;
-      }
-
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.IsAntialiasingEnabled = toEnable;
+      aType = Prs3d_TypeOfHighlight_LocalSelected;
     }
-    else if (aFlag == "-gleam")
+    else
     {
-      if (toPrint)
-      {
-        theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
-        continue;
-      }
-
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.IsTransparentShadowEnabled = toEnable;
+      --anArgIter;
     }
-    else if (aFlag == "-gi")
+  }
+  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.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
-        continue;
-      }
-
       Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.IsGlobalIlluminationEnabled = toEnable;
-      if (!toEnable)
+      if (anArgIter + 1 < theArgsNb
+       && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
       {
-        aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
+        ++anArgIter;
       }
+      aCtx->SetAutoActivateSelection (toEnable);
     }
-    else if (aFlag == "-blockedrng"
-          || aFlag == "-brng")
+    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.CoherentPathTracingMode ? "on" : "off") << " ";
-        continue;
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
 
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-        && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
-      {
-        --anArgIter;
-      }
-      aParams.CoherentPathTracingMode = 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 == "-env")
+    else if (anArg == "-layer"
+          && anArgIter + 1 < theArgsNb)
     {
-      if (toPrint)
+      if (aType == Prs3d_TypeOfHighlight_None)
       {
-        theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
-        continue;
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
 
-      Standard_Boolean toEnable = Standard_True;
-      if (++anArgIter < theArgNb
-        && !ViewerTest::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.UseEnvironmentMapBackground = toEnable;
+
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetZLayer (aNewLayer);
+      toRedraw = Standard_True;
     }
-    else if (aFlag == "-shademodel"
-          || aFlag == "-shadingmodel"
-          || aFlag == "-shading")
+    else if (anArg == "-hicolor"
+          || anArg == "-selcolor"
+          || anArg == "-color")
     {
-      if (toPrint)
-      {
-        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 (anArg.StartsWith ("-hi"))
+      {
+        aType = Prs3d_TypeOfHighlight_Dynamic;
       }
-
-      if (++anArgIter >= theArgNb)
+      else if (anArg.StartsWith ("-sel"))
       {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        aType = Prs3d_TypeOfHighlight_Selected;
       }
-
-      TCollection_AsciiString aMode (theArgVec[anArgIter]);
-      aMode.LowerCase();
-      if (aMode == "color"
-       || aMode == "none")
+      else if (aType == Prs3d_TypeOfHighlight_None)
       {
-        aView->SetShadingModel (V3d_COLOR);
+        std::cout << "Syntax error: type of highlighting is undefined\n";
+        return 1;
       }
-      else if (aMode == "flat"
-            || aMode == "facet")
+
+      Quantity_Color aColor;
+      Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
+                                                           theArgVec + anArgIter + 1,
+                                                           aColor);
+      if (aNbParsed == 0)
       {
-        aView->SetShadingModel (V3d_FLAT);
+        std::cout << "Syntax error: need more arguments.\n";
+        return 1;
       }
-      else if (aMode == "gouraud"
-            || aMode == "vertex"
-            || aMode == "vert")
+      anArgIter += aNbParsed;
+
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetColor (aColor);
+      toRedraw = Standard_True;
+    }
+    else if ((anArg == "-transp"
+           || anArg == "-transparency"
+           || anArg == "-hitransp"
+           || anArg == "-seltransp"
+           || anArg == "-hitransplocal"
+           || anArg == "-seltransplocal")
+          && anArgIter + 1 < theArgsNb)
+    {
+      if (anArg.StartsWith ("-hi"))
       {
-        aView->SetShadingModel (V3d_GOURAUD);
+        aType = Prs3d_TypeOfHighlight_Dynamic;
       }
-      else if (aMode == "phong"
-            || aMode == "fragment"
-            || aMode == "frag"
-            || aMode == "pixel")
+      else if (anArg.StartsWith ("-sel"))
       {
-        aView->SetShadingModel (V3d_PHONG);
+        aType = Prs3d_TypeOfHighlight_Selected;
       }
-      else
+      else if (aType == Prs3d_TypeOfHighlight_None)
       {
-        std::cout << "Error: unknown shading model '" << aMode << "'\n";
+        std::cout << "Syntax error: type of highlighting is undefined\n";
         return 1;
       }
+
+      const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      aStyle->SetTransparency ((Standard_ShortReal )aTransp);
+      toRedraw = Standard_True;
     }
-    else if (aFlag == "-resolution")
+    else if ((anArg == "-mat"
+           || anArg == "-material")
+          && anArgIter + 1 < theArgsNb)
     {
-      if (++anArgIter >= theArgNb)
+      if (aType == Prs3d_TypeOfHighlight_None)
       {
-        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        std::cout << "Syntax error: type of highlighting is undefined\n";
         return 1;
       }
 
-      TCollection_AsciiString aResolution (theArgVec[anArgIter]);
-      if (aResolution.IsIntegerValue())
+      const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
+      Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
+      if (aMatName != Graphic3d_NOM_DEFAULT)
       {
-        aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
+        ++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: wrong syntax at argument'" << anArg << "'.\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 : 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())
+  if (toPrint)
   {
-    std::cerr << "Error: no active viewer!\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";
   }
 
-  std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
-
-  for (;;)
+  if (aCtx->NbSelected() != 0 && toRedraw)
   {
-    aView->Redraw();
-
-    Standard_Boolean toExit = Standard_False;
-
-    MSG aMsg;
-    while (PeekMessage (&aMsg, NULL, NULL, NULL, PM_REMOVE))
-    {
-      if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
-      {
-        toExit = Standard_True;
-      }
-
-      TranslateMessage (&aMsg);
-      DispatchMessage  (&aMsg);
-    }
-
-    if (toExit)
-    {
-      break;
-    }
+    aCtx->HilightSelected (Standard_True);
   }
 
   return 0;
 }
-#endif
 
-//=======================================================================
-//function : VFrustumCulling
-//purpose  : enables/disables view volume's culling.
-//=======================================================================
-static int VFrustumCulling (Draw_Interpretor& theDI,
-                            Standard_Integer  theArgNb,
-                            const char**      theArgVec)
+//===============================================================================================
+//function : VDumpSelectionImage
+//purpose  :
+//===============================================================================================
+static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
+                                Standard_Integer  theArgsNb,
+                                const char**      theArgVec)
 {
-  Handle(V3d_View) aView = ViewerTest::CurrentView();
-  if (aView.IsNull())
+  if (theArgsNb < 2)
   {
-    std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
+    std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
     return 1;
   }
 
-  if (theArgNb < 2)
-  {
-    theDI << (aView->IsCullingEnabled() ? "on" : "off");
-    return 0;
-  }
-  else if (theArgNb != 2)
+  const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
+  if (aContext.IsNull())
   {
-    std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
+    std::cout << "Error: no active view.\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())
+  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)
   {
-    std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
-    return 1;
-  }
+    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;
+      }
 
-  const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+      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;
+      }
 
-  if (theArgNb < 2)
-  {
-    theDI << (aContext->ToHilightSelected() ? "on" : "off");
-    return 0;
+      aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
+    }
+    else if (aFile.IsEmpty())
+    {
+      aFile = theArgVec[anArgIter];
+    }
+    else
+    {
+      std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
+      return 1;
+    }
   }
-
-  if (theArgNb != 2)
+  if (aFile.IsEmpty())
   {
-    std::cout  << theArgVec[0] << " error : wrong number of parameters."
-          << "Type 'help" << theArgVec[0] << "' for more information.";
+    std::cout << "Syntax error: image file name is missing.\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())
-  {
-    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;
-}
+  const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+  Standard_Integer aWidth = 0, aHeight = 0;
+  aView->Window()->Size (aWidth, aHeight);
 
-//=======================================================================
-//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)
+  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;
 }
 
@@ -8874,8 +10408,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add("vpick" ,
     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
     VPick,group);
-  theCommands.Add("vfit"    ,
-    "vfit or <F> [-selected]"
+  theCommands.Add("vfit",
+    "vfit or <F> [-selected] [-noupdate]"
     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
     __FILE__,VFit,group);
   theCommands.Add ("vfitarea",
@@ -8945,22 +10479,35 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " : notice that EMF format requires patched gl2ps",
     __FILE__,VExport,group);
   theCommands.Add("vcolorscale",
-    "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
-    "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
-    "-demo/-demoversion draw a demoversion of color scale.\n"
-    "-show/display display color scale.\n"
-    "-hide/erase erase color scale.\n"
-    "Please note that -show/-hide option must be the first argument!\n"
-    "-color Index R G B: set color for indexed interval\n"
-    "-color Index ColorName: set color for indexed interval\n"
-    "-colors R G B R G B ...: set colors for all intervals\n"
-    "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
-    "-colors supports both color names and rgb values in one call\n"
-    "-label Index Text: set label for indexed interval\n"
-    "-labels Text Text Text ...: set labels for all intervals\n"
-    "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
-    "Available text positions: left, right, center, none;\n",
-    __FILE__,VColorScale,group);
+    "vcolorscale name [-noupdate|-update] [-demo]"
+    "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
+    "\n\t\t:       [-font HeightFont=20]"
+    "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
+    "\n\t\t:       [-smoothTransition {on|off}=off]"
+    "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
+    "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
+    "\n\t\t:       [-textpos {left|right|center|none}=right]"
+    "\n\t\t:       [-labelAtBorder {on|off}=on]"
+    "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
+    "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
+    "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
+    "\n\t\t:       [-xy Left=0 Bottom=0]"
+    "\n\t\t:  -demo     - displays a color scale with demonstratio values"
+    "\n\t\t:  -colors   - set colors for all intervals"
+    "\n\t\t:  -color    - set color for specific interval"
+    "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
+    "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
+    "\n\t\t:              at border means the value inbetween neighbor intervals,"
+    "\n\t\t:              at center means the center value within current interval"
+    "\n\t\t:  -labels   - set labels for all intervals"
+    "\n\t\t:  -freeLabels - same as -labels but does not require"
+    "\n\t\t:              matching the number of intervals"
+    "\n\t\t:  -label    - set label for specific interval"
+    "\n\t\t:  -title    - set title"
+    "\n\t\t:  -reversed - setup smooth color transition between intervals"
+    "\n\t\t:  -smoothTransition - swap colorscale direction"
+    "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
+    __FILE__, VColorScale, group);
   theCommands.Add("vgraduatedtrihedron",
     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
     "\t[-namefont Name] [-valuesfont Name]\n"
@@ -8985,24 +10532,26 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     " - 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("vlayerline",
     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
@@ -9123,31 +10672,77 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "vmoveto x y"
     "- emulates cursor movement to pixel postion (x,y)",
     __FILE__, VMoveTo, group);
-  theCommands.Add ("vviewparams", "vviewparams usage:\n"
-    "- vviewparams\n"
-    "- vviewparams [-scale [s]] [-eye [x y z]] [-at [x y z]] [-up [x y z]]\n"
-    "              [-proj [x y z]] [-center x y] [-size sx]\n"
-    "-   Gets or sets current view parameters.\n"
-    "-   If called without arguments, all view parameters are printed.\n"
-    "-   The options are:\n"
-    "      -scale [s]    : prints or sets viewport relative scale.\n"
-    "      -eye [x y z]  : prints or sets eye location.\n"
-    "      -at [x y z]   : prints or sets center of look.\n"
-    "      -up [x y z]   : prints or sets direction of up vector.\n"
-    "      -proj [x y z] : prints or sets direction of look.\n"
-    "      -center x y   : sets location of center of the screen in pixels.\n"
-    "      -size [sx]    : prints viewport projection width and height sizes\n"
-    "                    : or changes the size of its maximum dimension.\n",
+  theCommands.Add ("vviewparams",
+              "vviewparams [-args] [-scale [s]]"
+      "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
+      "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
+      "\n\t\t: Manage current view parameters or prints all"
+      "\n\t\t: current values when called without argument."
+      "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
+      "\n\t\t:   -eye  [x y z] prints or sets eye location"
+      "\n\t\t:   -at   [x y z] prints or sets center of look"
+      "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
+      "\n\t\t:   -proj [x y z] prints or sets direction of look"
+      "\n\t\t:   -center x y   sets location of center of the screen in pixels"
+      "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
+      "\n\t\t:                 or changes the size of its maximum dimension"
+      "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
     __FILE__, VViewParams, group);
+
+  theCommands.Add("vanimation", "Alias for vanim",
+    __FILE__, VAnimation, group);
+
+  theCommands.Add("vanim",
+            "List existing animations:"
+    "\n\t\t:  vanim"
+    "\n\t\t: Animation playback:"
+    "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
+    "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
+    "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
+    "\n\t\t:   -freeLook skip camera animations"
+    "\n\t\t:   -lockLoop disable any interactions"
+    "\n\t\t:"
+    "\n\t\t: Animation definition:"
+    "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
+    "\n\t\t:        [start TimeSec] [duration TimeSec]"
+    "\n\t\t:"
+    "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
+    "\n\t\t: specifies nested animations."
+    "\n\t\t: There is no syntax to explicitly add new animation,"
+    "\n\t\t: and all non-existing animations within the name will be"
+    "\n\t\t: implicitly created on first use (including parents)."
+    "\n\t\t:"
+    "\n\t\t: Each animation might define the SINGLE action (see below),"
+    "\n\t\t: like camera transition, object transformation or custom callback."
+    "\n\t\t: Child animations can be used for defining concurrent actions."
+    "\n\t\t:"
+    "\n\t\t: Camera animation:"
+    "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
+    "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
+    "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
+    "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
+    "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
+    "\n\t\t:   -atX    camera Center positions pair"
+    "\n\t\t:   -upX    camera Up directions pair"
+    "\n\t\t:   -scaleX camera Scale factors pair"
+    "\n\t\t: Object animation:"
+    "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
+    "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
+    "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
+    "\n\t\t:   -locX   object Location points pair (translation)"
+    "\n\t\t:   -rotX   object Orientations pair (quaternions)"
+    "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
+    "\n\t\t: Custom callback:"
+    "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
+    "\n\t\t:   %Pts        overall animation presentation timestamp"
+    "\n\t\t:   %LocalPts   local animation timestamp"
+    "\n\t\t:   %Normalized local animation normalized value in range 0..1"
+    __FILE__, VAnimation, group);
+
   theCommands.Add("vchangeselected",
     "vchangeselected shape"
     "- adds to shape to selection or remove one from it",
                __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"
     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
@@ -9185,10 +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"
-    "\n\t\t: Switches altialiasing on or off",
-    __FILE__,VAntialiasing,group);
   theCommands.Add ("vpurgedisplay",
     "vpurgedisplay"
     "- removes structures which don't belong to objects displayed in neutral point",
@@ -9233,31 +10824,37 @@ 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]"
        "\n\t\t:           [-devCoeff value]"
@@ -9306,6 +10903,10 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\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"
@@ -9328,6 +10929,55 @@ 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",