0028405: Visualization, V3d_Viewer - changes to Grid immediately updates view
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <DBRep.hxx>
30 #include <Graphic3d_ArrayOfPolylines.hxx>
31 #include <Graphic3d_AspectMarker3d.hxx>
32 #include <Graphic3d_ExportFormat.hxx>
33 #include <Graphic3d_NameOfTextureEnv.hxx>
34 #include <Graphic3d_GraduatedTrihedron.hxx>
35 #include <Graphic3d_TextureEnv.hxx>
36 #include <Graphic3d_TextureParams.hxx>
37 #include <Graphic3d_TypeOfTextureFilter.hxx>
38 #include <Graphic3d_AspectFillArea3d.hxx>
39 #include <ViewerTest.hxx>
40 #include <ViewerTest_AutoUpdater.hxx>
41 #include <ViewerTest_EventManager.hxx>
42 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
43 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_CmdParser.hxx>
45 #include <V3d_AmbientLight.hxx>
46 #include <V3d_DirectionalLight.hxx>
47 #include <V3d_PositionalLight.hxx>
48 #include <V3d_SpotLight.hxx>
49 #include <NCollection_DoubleMap.hxx>
50 #include <NCollection_List.hxx>
51 #include <NCollection_Vector.hxx>
52 #include <AIS_InteractiveContext.hxx>
53 #include <Draw_Interpretor.hxx>
54 #include <Draw.hxx>
55 #include <Draw_Appli.hxx>
56 #include <Image_AlienPixMap.hxx>
57 #include <OpenGl_GraphicDriver.hxx>
58 #include <OSD_Timer.hxx>
59 #include <TColStd_HSequenceOfAsciiString.hxx>
60 #include <TColStd_SequenceOfInteger.hxx>
61 #include <TColStd_HSequenceOfReal.hxx>
62 #include <TColgp_Array1OfPnt2d.hxx>
63 #include <TColStd_MapOfAsciiString.hxx>
64 #include <Aspect_TypeOfLine.hxx>
65 #include <Image_Diff.hxx>
66 #include <Aspect_DisplayConnection.hxx>
67 #include <gp_Pnt.hxx>
68 #include <gp_Dir.hxx>
69 #include <gp_Pln.hxx>
70 #include <PrsMgr_PresentableObject.hxx>
71 #include <Graphic3d_ClipPlane.hxx>
72 #include <NCollection_DataMap.hxx>
73 #include <Graphic3d_Texture2Dmanual.hxx>
74 #include <Prs3d_ShadingAspect.hxx>
75 #include <Prs3d_Drawer.hxx>
76 #include <Prs3d_LineAspect.hxx>
77 #include <Prs3d_Root.hxx>
78
79 #ifdef _WIN32
80 #undef DrawText
81 #endif
82
83 #include <cstdlib>
84
85 #if defined(_WIN32)
86   #include <WNT_WClass.hxx>
87   #include <WNT_Window.hxx>
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 // Auxiliary definitions
98 static const char THE_KEY_DELETE = 127;
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 extern int VErase (Draw_Interpretor& theDI,
111                    Standard_Integer  theArgNb,
112                    const char**      theArgVec);
113
114 #if defined(_WIN32)
115 static Handle(WNT_Window)& VT_GetWindow() {
116   static Handle(WNT_Window) WNTWin;
117   return WNTWin;
118 }
119 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
120 static Handle(Cocoa_Window)& VT_GetWindow()
121 {
122   static Handle(Cocoa_Window) aWindow;
123   return aWindow;
124 }
125 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
126 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
127 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
128
129 #else
130 static Handle(Xw_Window)& VT_GetWindow(){
131   static Handle(Xw_Window) XWWin;
132   return XWWin;
133 }
134
135 static void VProcessEvents(ClientData,int);
136 #endif
137
138 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
139 {
140   static Handle(Aspect_DisplayConnection) aDisplayConnection;
141   return aDisplayConnection;
142 }
143
144 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
145 {
146   GetDisplayConnection() = theDisplayConnection;
147 }
148
149 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
150 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
151 {
152   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
153 #if defined(_WIN32)
154   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156     return aWindow->HWindow();
157 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
159   if (!aWindow.IsNull())
160   return aWindow->XWindow();
161 #endif
162   return aWindowHandle;
163 }
164 #endif
165
166 static Standard_Boolean MyHLRIsOn = Standard_False;
167
168 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
169 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
170 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
171 static OpenGl_Caps ViewerTest_myDefaultCaps;
172
173 static void OSWindowSetup();
174
175 static struct
176 {
177   Quantity_Color FlatColor;
178   Quantity_Color GradientColor1;
179   Quantity_Color GradientColor2;
180   Aspect_GradientFillMethod FillMethod;
181 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
182
183 //==============================================================================
184 //  EVENT GLOBAL VARIABLES
185 //==============================================================================
186
187 static int Start_Rot = 0;
188 int X_Motion = 0; // Current cursor position
189 int Y_Motion = 0;
190 int X_ButtonPress = 0; // Last ButtonPress position
191 int Y_ButtonPress = 0;
192 Standard_Boolean IsDragged = Standard_False;
193 Standard_Boolean DragFirst = Standard_False;
194 Standard_Boolean TheIsAnimating = Standard_False;
195
196
197 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
198 {
199   static Handle(AIS_RubberBand) aBand;
200   if (aBand.IsNull())
201   {
202     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
203     aBand->SetDisplayMode (0);
204   }
205   return aBand;
206 }
207
208 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
209
210 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
211 {
212   static ViewerTest_MapOfAISManipulators aMap;
213   return aMap;
214 }
215
216 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
217 {
218   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
219   for (; anIt.More(); anIt.Next())
220   {
221     if (anIt.Value()->HasActiveMode())
222     {
223       return anIt.Value();
224     }
225   }
226   return NULL;
227 }
228
229 //==============================================================================
230
231 #ifdef _WIN32
232 static LRESULT WINAPI ViewerWindowProc(
233                                        HWND hwnd,
234                                        UINT uMsg,
235                                        WPARAM wParam,
236                                        LPARAM lParam );
237 static LRESULT WINAPI AdvViewerWindowProc(
238   HWND hwnd,
239   UINT uMsg,
240   WPARAM wParam,
241   LPARAM lParam );
242 #endif
243
244
245 //==============================================================================
246 //function : WClass
247 //purpose  :
248 //==============================================================================
249
250 const Handle(Standard_Transient)& ViewerTest::WClass()
251 {
252   static Handle(Standard_Transient) theWClass;
253 #if defined(_WIN32)
254   if (theWClass.IsNull())
255   {
256     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
257                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
258                                 ::LoadCursorW (NULL, IDC_ARROW));
259   }
260 #endif
261   return theWClass;
262 }
263
264 //==============================================================================
265 //function : CreateName
266 //purpose  : Create numerical name for new object in theMap
267 //==============================================================================
268 template <typename ObjectType>
269 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
270                                     const TCollection_AsciiString& theDefaultString)
271 {
272   if (theObjectMap.IsEmpty())
273     return theDefaultString + TCollection_AsciiString(1);
274
275   Standard_Integer aNextKey = 1;
276   Standard_Boolean isFound = Standard_False;
277   while (!isFound)
278   {
279     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
280     // Look for objects with default names
281     if (theObjectMap.IsBound1(aStringKey))
282     {
283       aNextKey++;
284     }
285     else
286       isFound = Standard_True;
287   }
288
289   return theDefaultString + TCollection_AsciiString(aNextKey);
290 }
291
292 //==============================================================================
293 //structure : ViewerTest_Names
294 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
295 //==============================================================================
296 struct ViewerTest_Names
297 {
298 private:
299   TCollection_AsciiString myDriverName;
300   TCollection_AsciiString myViewerName;
301   TCollection_AsciiString myViewName;
302
303 public:
304
305   const TCollection_AsciiString& GetDriverName () const
306   {
307     return myDriverName;
308   }
309   void SetDriverName (const TCollection_AsciiString& theDriverName)
310   {
311     myDriverName = theDriverName;
312   }
313   const TCollection_AsciiString& GetViewerName () const
314   {
315     return myViewerName;
316   }
317   void SetViewerName (const TCollection_AsciiString& theViewerName)
318   {
319     myViewerName = theViewerName;
320   }
321   const TCollection_AsciiString& GetViewName () const
322   {
323     return myViewName;
324   }
325   void SetViewName (const TCollection_AsciiString& theViewName)
326   {
327     myViewName = theViewName;
328   }
329
330   //===========================================================================
331   //function : Constructor for ViewerTest_Names
332   //purpose  : Get view, viewer, driver names from custom string
333   //===========================================================================
334
335   ViewerTest_Names (const TCollection_AsciiString& theInputString)
336   {
337     TCollection_AsciiString aName(theInputString);
338     if (theInputString.IsEmpty())
339     {
340       // Get current configuration
341       if (ViewerTest_myDrivers.IsEmpty())
342         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
343           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
344       else
345         myDriverName = ViewerTest_myDrivers.Find2
346         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
347
348       if(ViewerTest_myContexts.IsEmpty())
349       {
350         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
351           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
352       }
353       else
354         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
355
356         myViewName = CreateName <Handle(V3d_View)>
357           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
358     }
359     else
360     {
361       // There is at least view name
362       Standard_Integer aParserNumber = 0;
363       for (Standard_Integer i = 0; i < 3; ++i)
364       {
365         Standard_Integer aParserPos = aName.SearchFromEnd("/");
366         if(aParserPos != -1)
367         {
368           aParserNumber++;
369           aName.Split(aParserPos-1);
370         }
371         else
372           break;
373       }
374       if (aParserNumber == 0)
375       {
376         // Only view name
377         if (!ViewerTest::GetAISContext().IsNull())
378         {
379           myDriverName = ViewerTest_myDrivers.Find2
380           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
381           myViewerName = ViewerTest_myContexts.Find2
382           (ViewerTest::GetAISContext());
383         }
384         else
385         {
386           // There is no opened contexts here, need to create names for viewer and driver
387           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
388             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
389
390           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
391             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
392         }
393         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
394       }
395       else if (aParserNumber == 1)
396       {
397         // Here is viewerName/viewName
398         if (!ViewerTest::GetAISContext().IsNull())
399           myDriverName = ViewerTest_myDrivers.Find2
400           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
401         else
402         {
403           // There is no opened contexts here, need to create name for driver
404           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
405             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
406         }
407         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
408
409         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
410       }
411       else
412       {
413         //Here is driverName/viewerName/viewName
414         myDriverName = TCollection_AsciiString(aName);
415
416         TCollection_AsciiString aViewerName(theInputString);
417         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
418         myViewerName = TCollection_AsciiString(aViewerName);
419
420         myViewName = TCollection_AsciiString(theInputString);
421       }
422     }
423   }
424 };
425
426 //==============================================================================
427 //function : FindContextByView
428 //purpose  : Find AIS_InteractiveContext by View
429 //==============================================================================
430
431 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
432 {
433   Handle(AIS_InteractiveContext) anAISContext;
434
435   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
436        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
437   {
438     if (anIter.Value()->CurrentViewer() == theView->Viewer())
439        return anIter.Key2();
440   }
441   return anAISContext;
442 }
443
444
445 //==============================================================================
446 //function : SetWindowTitle
447 //purpose  : Set window title
448 //==============================================================================
449
450 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
451                      Standard_CString theTitle)
452 {
453 #if defined(_WIN32)
454   const TCollection_ExtendedString theTitleW (theTitle);
455   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
456 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
457   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
458 #else
459   if(GetDisplayConnection()->GetDisplay())
460   {
461     Window aWindow =
462       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
463     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
464   }
465 #endif
466 }
467
468 //==============================================================================
469 //function : IsWindowOverlapped
470 //purpose  : Check if theWindow overlapp another view
471 //==============================================================================
472
473 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
474                                      const Standard_Integer thePxTop,
475                                      const Standard_Integer thePxRight,
476                                      const Standard_Integer thePxBottom,
477                                      TCollection_AsciiString& theViewId)
478 {
479   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
480       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
481   {
482     Standard_Integer aTop = 0,
483       aLeft = 0,
484       aRight = 0,
485       aBottom = 0;
486     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
487     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
488         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
489         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
490         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
491     {
492       theViewId = anIter.Key1();
493       return Standard_True;
494     }
495   }
496   return Standard_False;
497 }
498
499 // Workaround: to create and delete non-orthographic views outside ViewerTest
500 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
501 {
502   ViewerTest_myViews.UnBind1 (theName);
503 }
504
505 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
506                                const Handle(V3d_View)& theView)
507 {
508   ViewerTest_myViews.Bind (theName, theView);
509 }
510
511 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
512 {
513   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
514 }
515 //==============================================================================
516 //function : ViewerInit
517 //purpose  : Create the window viewer and initialize all the global variable
518 //==============================================================================
519
520 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
521                                                 const Standard_Integer thePxTop,
522                                                 const Standard_Integer thePxWidth,
523                                                 const Standard_Integer thePxHeight,
524                                                 Standard_CString theViewName,
525                                                 Standard_CString theDisplayName)
526 {
527   // Default position and dimension of the viewer window.
528   // Note that left top corner is set to be sufficiently small to have
529   // window fit in the small screens (actual for remote desktops, see #23003).
530   // The position corresponds to the window's client area, thus some
531   // gap is added for window frame to be visible.
532   Standard_Integer aPxLeft   = 20;
533   Standard_Integer aPxTop    = 40;
534   Standard_Integer aPxWidth  = 409;
535   Standard_Integer aPxHeight = 409;
536   Standard_Boolean toCreateViewer = Standard_False;
537
538   Handle(OpenGl_GraphicDriver) aGraphicDriver;
539   ViewerTest_Names aViewNames(theViewName);
540   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
541     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
542
543   if (thePxLeft != 0)
544     aPxLeft = thePxLeft;
545   if (thePxTop != 0)
546     aPxTop = thePxTop;
547   if (thePxWidth != 0)
548     aPxWidth = thePxWidth;
549   if (thePxHeight != 0)
550     aPxHeight = thePxHeight;
551
552   // Get graphic driver (create it or get from another view)
553   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
554   {
555     // Get connection string
556   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
557     TCollection_AsciiString aDisplayName(theDisplayName);
558     if (!aDisplayName.IsEmpty())
559       SetDisplayConnection (new Aspect_DisplayConnection ());
560     else
561       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
562   #else
563     (void)theDisplayName; // avoid warning on unused argument
564     SetDisplayConnection (new Aspect_DisplayConnection ());
565   #endif
566
567     if (Draw_VirtualWindows)
568     {
569       // don't waste the time waiting for VSync when window is not displayed on the screen
570       ViewerTest_myDefaultCaps.swapInterval = 0;
571       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
572       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
573     }
574     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
575     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
576
577     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
578     toCreateViewer = Standard_True;
579   }
580   else
581   {
582     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
583   }
584
585   //Dispose the window if input parameters are default
586   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
587   {
588     Standard_Integer aTop = 0,
589                      aLeft = 0,
590                      aRight = 0,
591                      aBottom = 0,
592                      aScreenWidth = 0,
593                      aScreenHeight = 0;
594
595     // Get screen resolution
596 #if defined(_WIN32) || defined(__WIN32__)
597     RECT aWindowSize;
598     GetClientRect(GetDesktopWindow(), &aWindowSize);
599     aScreenHeight = aWindowSize.bottom;
600     aScreenWidth = aWindowSize.right;
601 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
602     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
603 #else
604     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
605     aScreenWidth = WidthOfScreen(aScreen);
606     aScreenHeight = HeightOfScreen(aScreen);
607 #endif
608
609     TCollection_AsciiString anOverlappedViewId("");
610
611     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
612     {
613       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
614
615       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
616         && aRight + 2*aPxWidth + 40 > aScreenWidth)
617       {
618         if (aBottom + aPxHeight + 40 > aScreenHeight)
619         {
620           aPxLeft = 20;
621           aPxTop = 40;
622           break;
623         }
624         aPxLeft = 20;
625         aPxTop = aBottom + 40;
626       }
627       else
628         aPxLeft = aRight + 20;
629     }
630   }
631
632   // Get viewer name
633   TCollection_AsciiString aTitle("3D View - ");
634   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
635
636   // Change name of current active window
637   if (!ViewerTest::CurrentView().IsNull())
638   {
639     TCollection_AsciiString anActiveWindowTitle("3D View - ");
640     anActiveWindowTitle = anActiveWindowTitle
641       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
642     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
643   }
644
645   // Create viewer
646   Handle(V3d_Viewer) a3DViewer;
647   // If it's the single view, we first look for empty context
648   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
649   {
650     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
651       anIter(ViewerTest_myContexts);
652     if (anIter.More())
653       ViewerTest::SetAISContext (anIter.Value());
654     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
655   }
656   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
657   {
658     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
659     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
660   }
661   else if (a3DViewer.IsNull())
662   {
663     toCreateViewer = Standard_True;
664     a3DViewer = new V3d_Viewer(aGraphicDriver);
665     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
666     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
667                                            ViewerTest_DefaultBackground.GradientColor2,
668                                            ViewerTest_DefaultBackground.FillMethod);
669   }
670
671   // AIS context setup
672   if (ViewerTest::GetAISContext().IsNull() ||
673       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
674   {
675     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
676     ViewerTest::SetAISContext (aContext);
677     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
678   }
679   else
680   {
681     ViewerTest::ResetEventManager();
682   }
683
684   // Create window
685 #if defined(_WIN32)
686   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
687                                     Handle(WNT_WClass)::DownCast (WClass()),
688                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
689                                     aPxLeft, aPxTop,
690                                     aPxWidth, aPxHeight,
691                                     Quantity_NOC_BLACK);
692 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
693   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
694                                      aPxLeft, aPxTop,
695                                      aPxWidth, aPxHeight);
696   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
697 #else
698   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
699                                   aTitle.ToCString(),
700                                   aPxLeft, aPxTop,
701                                   aPxWidth, aPxHeight);
702 #endif
703   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
704
705   // View setup
706   Handle(V3d_View) aView = a3DViewer->CreateView();
707   aView->SetWindow (VT_GetWindow());
708   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
709
710   ViewerTest::CurrentView(aView);
711   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
712
713   // Setup for X11 or NT
714   OSWindowSetup();
715
716   // Set parameters for V3d_View and V3d_Viewer
717   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
718   aV3dView->SetComputedMode(Standard_False);
719   MyHLRIsOn = aV3dView->ComputedMode();
720
721   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
722   if (toCreateViewer)
723   {
724     a3DViewer->SetDefaultLights();
725     a3DViewer->SetLightOn();
726   }
727
728   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
729   #if TCL_MAJOR_VERSION  < 8
730   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
731       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
732   #else
733   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
734       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
735   #endif
736   #endif
737
738   VT_GetWindow()->Map();
739
740   // Set the handle of created view in the event manager
741   ViewerTest::ResetEventManager();
742
743   ViewerTest::CurrentView()->Redraw();
744
745   aView.Nullify();
746   a3DViewer.Nullify();
747
748   return aViewNames.GetViewName();
749 }
750
751 //==============================================================================
752 //function : RedrawAllViews
753 //purpose  : Redraw all created views
754 //==============================================================================
755 void ViewerTest::RedrawAllViews()
756 {
757   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
758   for (; aViewIt.More(); aViewIt.Next())
759   {
760     const Handle(V3d_View)& aView = aViewIt.Key2();
761     aView->Redraw();
762   }
763 }
764
765 //==============================================================================
766 //function : Vinit
767 //purpose  : Create the window viewer and initialize all the global variable
768 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
769 //==============================================================================
770
771 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
772 {
773   if (theArgsNb > 9)
774   {
775     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
776               << "Type help for more information.\n";
777     return 1;
778   }
779
780   TCollection_AsciiString aViewName, aDisplayName;
781   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
782   TCollection_AsciiString aName, aValue;
783   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
784   {
785     const TCollection_AsciiString anArg = theArgVec[anArgIt];
786     TCollection_AsciiString anArgCase = anArg;
787     anArgCase.UpperCase();
788     if (ViewerTest::SplitParameter (anArg, aName, aValue))
789     {
790       aName.UpperCase();
791       if (aName.IsEqual ("NAME"))
792       {
793         aViewName = aValue;
794       }
795       else if (aName.IsEqual ("L")
796             || aName.IsEqual ("LEFT"))
797       {
798         aPxLeft = aValue.IntegerValue();
799       }
800       else if (aName.IsEqual ("T")
801             || aName.IsEqual ("TOP"))
802       {
803         aPxTop = aValue.IntegerValue();
804       }
805     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
806       else if (aName.IsEqual ("DISP")
807             || aName.IsEqual ("DISPLAY"))
808       {
809         aDisplayName = aValue;
810       }
811     #endif
812       else if (aName.IsEqual ("W")
813             || aName.IsEqual ("WIDTH"))
814       {
815         aPxWidth = aValue.IntegerValue();
816       }
817       else if (aName.IsEqual ("H")
818             || aName.IsEqual ("HEIGHT"))
819       {
820         aPxHeight = aValue.IntegerValue();
821       }
822       else
823       {
824         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
825       }
826     }
827     else if (aViewName.IsEmpty())
828     {
829       aViewName = anArg;
830     }
831     else
832     {
833       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
834     }
835   }
836
837   ViewerTest_Names aViewNames (aViewName);
838   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
839   {
840     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
841     theDi.Eval (aCommand.ToCString());
842     return 0;
843   }
844
845   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
846                                                             aViewName.ToCString(),
847                                                             aDisplayName.ToCString());
848   theDi << aViewId;
849   return 0;
850 }
851
852 //==============================================================================
853 //function : VHLR
854 //purpose  : hidden lines removal algorithm
855 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
856 //==============================================================================
857
858 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
859 {
860   if (ViewerTest::CurrentView().IsNull())
861   {
862     di << argv[0] << ": Call vinit before this command, please.\n";
863     return 1;
864   }
865
866   if (argc < 2)
867   {
868     di << argv[0] << ": Wrong number of command arguments.\n"
869       << "Type help " << argv[0] << " for more information.\n";
870     return 1;
871   }
872
873   // Enable or disable HLR mode.
874   Standard_Boolean isHLROn =
875     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
876
877   if (isHLROn != MyHLRIsOn)
878   {
879     MyHLRIsOn = isHLROn;
880     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
881   }
882
883   // Show or hide hidden lines in HLR mode.
884   Standard_Boolean isCurrentShowHidden
885     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
886
887   Standard_Boolean isShowHidden =
888     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
889                 : isCurrentShowHidden;
890
891
892   if (isShowHidden != isCurrentShowHidden)
893   {
894     if (isShowHidden)
895     {
896       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
897     }
898     else
899     {
900       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
901     }
902
903     // Redisplay shapes.
904     if (MyHLRIsOn)
905     {
906       AIS_ListOfInteractive aListOfShapes;
907       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
908
909       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
910       {
911         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
912         if (aShape.IsNull())
913         {
914           continue;
915         }
916         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
917       }
918     }
919   }
920
921   ViewerTest::CurrentView()->Update();
922   return 0;
923 }
924
925 //==============================================================================
926 //function : VHLRType
927 //purpose  : change type of using HLR algorithm
928 //==============================================================================
929
930 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
931 {
932   if (ViewerTest::CurrentView().IsNull())
933   {
934     di << argv[0] << ": Call vinit before this command, please.\n";
935     return 1;
936   }
937
938   if (argc < 2)
939   {
940     di << argv[0] << ": Wrong number of command arguments.\n"
941       << "Type help " << argv[0] << " for more information.\n";
942     return 1;
943   }
944
945   Prs3d_TypeOfHLR aTypeOfHLR =
946     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
947
948   if (argc == 2)
949   {
950     AIS_ListOfInteractive aListOfShapes;
951     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
952     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
953     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
954       anIter.More(); anIter.Next())
955     {
956       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
957       if (aShape.IsNull())
958         continue;
959       if (aShape->TypeOfHLR() != aTypeOfHLR)
960         aShape->SetTypeOfHLR (aTypeOfHLR);
961       if (MyHLRIsOn)
962         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
963     }
964     ViewerTest::CurrentView()->Update();
965     return 0;
966   }
967   else
968   {
969     for (Standard_Integer i = 2; i < argc; ++i)
970     {
971       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
972       TCollection_AsciiString aName (argv[i]);
973
974       if (!aMap.IsBound2 (aName))
975       {
976         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
977         continue;
978       }
979       Handle(AIS_Shape) anAISObject =
980         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
981       if (anAISObject.IsNull())
982         continue;
983       anAISObject->SetTypeOfHLR (aTypeOfHLR);
984       if (MyHLRIsOn)
985         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
986     }
987     ViewerTest::CurrentView()->Update();
988   }
989
990   return 0;
991 }
992
993 //==============================================================================
994 //function : FindViewIdByWindowHandle
995 //purpose  : Find theView Id in the map of views by window handle
996 //==============================================================================
997 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
998 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
999 {
1000   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1001        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1002   {
1003     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1004     if (aWindowHandle == theWindowHandle)
1005       return anIter.Key1();
1006   }
1007   return TCollection_AsciiString("");
1008 }
1009 #endif
1010
1011 //==============================================================================
1012 //function : ActivateView
1013 //purpose  : Make the view active
1014 //==============================================================================
1015
1016 void ActivateView (const TCollection_AsciiString& theViewName)
1017 {
1018   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1019   if (!aView.IsNull())
1020   {
1021     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1022     if (!anAISContext.IsNull())
1023     {
1024       if (!ViewerTest::CurrentView().IsNull())
1025       {
1026         TCollection_AsciiString aTitle("3D View - ");
1027         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1028         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1029       }
1030
1031       ViewerTest::CurrentView (aView);
1032       // Update degenerate mode
1033       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1034       ViewerTest::SetAISContext (anAISContext);
1035       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1036       aTitle = aTitle + theViewName + "(*)";
1037       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1038 #if defined(_WIN32) || defined(__WIN32__)
1039       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1040 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1041       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1042 #else
1043       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1044 #endif
1045       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1046       ViewerTest::CurrentView()->Redraw();
1047     }
1048   }
1049 }
1050
1051 //==============================================================================
1052 //function : RemoveView
1053 //purpose  :
1054 //==============================================================================
1055 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1056                              const Standard_Boolean  theToRemoveContext)
1057 {
1058   if (!ViewerTest_myViews.IsBound2 (theView))
1059   {
1060     return;
1061   }
1062
1063   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1064   RemoveView (aViewName, theToRemoveContext);
1065 }
1066
1067 //==============================================================================
1068 //function : RemoveView
1069 //purpose  : Close and remove view from display, clear maps if neccessary
1070 //==============================================================================
1071 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1072 {
1073   if (!ViewerTest_myViews.IsBound1(theViewName))
1074   {
1075     cout << "Wrong view name\n";
1076     return;
1077   }
1078
1079   // Activate another view if it's active now
1080   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1081   {
1082     if (ViewerTest_myViews.Extent() > 1)
1083     {
1084       TCollection_AsciiString aNewViewName;
1085       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1086            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1087         if (anIter.Key1() != theViewName)
1088         {
1089           aNewViewName = anIter.Key1();
1090           break;
1091         }
1092         ActivateView (aNewViewName);
1093     }
1094     else
1095     {
1096       Handle(V3d_View) anEmptyView;
1097 #if defined(_WIN32) || defined(__WIN32__)
1098       Handle(WNT_Window) anEmptyWindow;
1099 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1100       Handle(Cocoa_Window) anEmptyWindow;
1101 #else
1102       Handle(Xw_Window) anEmptyWindow;
1103 #endif
1104       VT_GetWindow() = anEmptyWindow;
1105       ViewerTest::CurrentView (anEmptyView);
1106       if (isContextRemoved)
1107       {
1108         Handle(AIS_InteractiveContext) anEmptyContext;
1109         ViewerTest::SetAISContext(anEmptyContext);
1110       }
1111     }
1112   }
1113
1114   // Delete view
1115   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1116   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1117
1118   // Remove view resources
1119   ViewerTest_myViews.UnBind1(theViewName);
1120   aView->Remove();
1121
1122 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1123   XFlush (GetDisplayConnection()->GetDisplay());
1124 #endif
1125
1126   // Keep context opened only if the closed view is last to avoid
1127   // unused empty contexts
1128   if (!aCurrentContext.IsNull())
1129   {
1130     // Check if there are more difined views in the viewer
1131     aCurrentContext->CurrentViewer()->InitDefinedViews();
1132     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1133     {
1134       // Remove driver if there is no viewers that use it
1135       Standard_Boolean isRemoveDriver = Standard_True;
1136       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1137           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1138       {
1139         if (aCurrentContext != anIter.Key2() &&
1140           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1141         {
1142           isRemoveDriver = Standard_False;
1143           break;
1144         }
1145       }
1146
1147       aCurrentContext->RemoveAll (Standard_False);
1148       if(isRemoveDriver)
1149       {
1150         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1151       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1152         #if TCL_MAJOR_VERSION  < 8
1153         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1154         #else
1155         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1156         #endif
1157       #endif
1158       }
1159
1160       ViewerTest_myContexts.UnBind2(aCurrentContext);
1161     }
1162   }
1163   cout << "3D View - " << theViewName << " was deleted.\n";
1164
1165 }
1166
1167 //==============================================================================
1168 //function : VClose
1169 //purpose  : Remove the view defined by its name
1170 //==============================================================================
1171
1172 static int VClose (Draw_Interpretor& /*theDi*/,
1173                    Standard_Integer  theArgsNb,
1174                    const char**      theArgVec)
1175 {
1176   NCollection_List<TCollection_AsciiString> aViewList;
1177   if (theArgsNb > 1)
1178   {
1179     TCollection_AsciiString anArg (theArgVec[1]);
1180     anArg.UpperCase();
1181     if (anArg.IsEqual ("ALL")
1182      || anArg.IsEqual ("*"))
1183     {
1184       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1185            anIter.More(); anIter.Next())
1186       {
1187         aViewList.Append (anIter.Key1());
1188       }
1189       if (aViewList.IsEmpty())
1190       {
1191         std::cout << "No view to close\n";
1192         return 0;
1193       }
1194     }
1195     else
1196     {
1197       ViewerTest_Names aViewName (theArgVec[1]);
1198       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1199       {
1200         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1201         return 1;
1202       }
1203       aViewList.Append (aViewName.GetViewName());
1204     }
1205   }
1206   else
1207   {
1208     // close active view
1209     if (ViewerTest::CurrentView().IsNull())
1210     {
1211       std::cerr << "No active view!\n";
1212       return 1;
1213     }
1214     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1215   }
1216
1217   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1218   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1219        anIter.More(); anIter.Next())
1220   {
1221     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1222   }
1223
1224   return 0;
1225 }
1226
1227 //==============================================================================
1228 //function : VActivate
1229 //purpose  : Activate the view defined by its ID
1230 //==============================================================================
1231
1232 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1233 {
1234   if (theArgsNb > 2)
1235   {
1236     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1237     << "Usage: " << theArgVec[0] << " ViewID\n";
1238     return 1;
1239   }
1240   if(theArgsNb == 1)
1241   {
1242     theDi.Eval("vviewlist");
1243     return 0;
1244   }
1245
1246   TCollection_AsciiString aNameString(theArgVec[1]);
1247   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1248   {
1249     TCollection_AsciiString aTitle("3D View - ");
1250     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1251     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1252     Handle(V3d_View) anEmptyView;
1253 #if defined(_WIN32) || defined(__WIN32__)
1254     Handle(WNT_Window) anEmptyWindow;
1255 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1256     Handle(Cocoa_Window) anEmptyWindow;
1257 #else
1258     Handle(Xw_Window) anEmptyWindow;
1259 #endif
1260     VT_GetWindow() = anEmptyWindow;
1261     ViewerTest::CurrentView (anEmptyView);
1262     ViewerTest::ResetEventManager();
1263     theDi << theArgVec[0] << ": all views are inactive\n";
1264     return 0;
1265   }
1266
1267   ViewerTest_Names aViewNames(aNameString);
1268
1269   // Check if this view exists in the viewer with the driver
1270   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1271   {
1272     theDi << "Wrong view name\n";
1273     return 1;
1274   }
1275
1276   // Check if it is active already
1277   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1278   {
1279     theDi << theArgVec[0] << ": the view is active already\n";
1280     return 0;
1281   }
1282
1283   ActivateView (aViewNames.GetViewName());
1284   return 0;
1285 }
1286
1287 //==============================================================================
1288 //function : VViewList
1289 //purpose  : Print current list of views per viewer and graphic driver ID
1290 //           shared between viewers
1291 //==============================================================================
1292
1293 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1294 {
1295   if (theArgsNb > 2)
1296   {
1297     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1298           << "Usage: " << theArgVec[0] << " name";
1299     return 1;
1300   }
1301   if (ViewerTest_myContexts.Size() < 1)
1302     return 0;
1303
1304   Standard_Boolean isTreeView =
1305     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1306
1307   if (isTreeView)
1308     theDi << theArgVec[0] <<":\n";
1309
1310     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1311       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1312     {
1313       if (isTreeView)
1314         theDi << aDriverIter.Key1() << ":\n";
1315
1316       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1317         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1318       {
1319         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1320         {
1321           if (isTreeView)
1322           {
1323             TCollection_AsciiString aContextName(aContextIter.Key1());
1324             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1325           }
1326
1327           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1328             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1329           {
1330             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1331             {
1332               TCollection_AsciiString aViewName(aViewIter.Key1());
1333               if (isTreeView)
1334               {
1335                 if (aViewIter.Value() == ViewerTest::CurrentView())
1336                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1337                 else
1338                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1339               }
1340               else
1341               {
1342                 theDi << aViewName << " ";
1343               }
1344             }
1345           }
1346         }
1347       }
1348     }
1349   return 0;
1350 }
1351
1352 //==============================================================================
1353 //function : VT_ProcessKeyPress
1354 //purpose  : Handle KeyPress event from a CString
1355 //==============================================================================
1356 void VT_ProcessKeyPress (const char* buf_ret)
1357 {
1358   //cout << "KeyPress" << endl;
1359   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1360   // Letter in alphabetic order
1361
1362   if (!strcasecmp (buf_ret, "A"))
1363   {
1364     // AXO
1365     aView->SetProj(V3d_XposYnegZpos);
1366   }
1367   else if (!strcasecmp (buf_ret, "D"))
1368   {
1369     // Reset
1370     aView->Reset();
1371   }
1372   else if (!strcasecmp (buf_ret, "F"))
1373   {
1374     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1375     {
1376       ViewerTest::GetAISContext()->FitSelected (aView);
1377     }
1378     else
1379     {
1380       // FitAll
1381       aView->FitAll();
1382     }
1383   }
1384   else if (!strcasecmp (buf_ret, "H"))
1385   {
1386     // HLR
1387     cout << "HLR" << endl;
1388     aView->SetComputedMode (!aView->ComputedMode());
1389     MyHLRIsOn = aView->ComputedMode();
1390   }
1391   else if (!strcasecmp (buf_ret, "P"))
1392   {
1393     // Type of HLR
1394     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1395     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1396       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1397     else
1398       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1399     if (aContext->NbSelected()==0)
1400     {
1401       AIS_ListOfInteractive aListOfShapes;
1402       aContext->DisplayedObjects(aListOfShapes);
1403       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1404         anIter.More(); anIter.Next())
1405       {
1406         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1407         if (aShape.IsNull())
1408           continue;
1409         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1410           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1411         else
1412           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1413         aContext->Redisplay (aShape, Standard_False);
1414       }
1415     }
1416     else
1417     {
1418       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1419       {
1420         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1421         if (aShape.IsNull())
1422           continue;
1423         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1424           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1425         else
1426           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1427         aContext->Redisplay (aShape, Standard_False);
1428       }
1429     }
1430
1431     aContext->UpdateCurrentViewer();
1432
1433   }
1434   else if (!strcasecmp (buf_ret, "S"))
1435   {
1436     std::cout << "setup Shaded display mode" << std::endl;
1437
1438     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1439     if(Ctx->NbSelected()==0)
1440       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1441     else{
1442       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1443         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1444       Ctx->UpdateCurrentViewer();
1445     }
1446   }
1447   else if (!strcasecmp (buf_ret, "U"))
1448   {
1449     // Unset display mode
1450     std::cout << "reset display mode to defaults" << std::endl;
1451
1452     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1453     if(Ctx->NbSelected()==0)
1454       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1455     else{
1456       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1457         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1458       Ctx->UpdateCurrentViewer();
1459     }
1460
1461   }
1462   else if (!strcasecmp (buf_ret, "T"))
1463   {
1464     // Top
1465     aView->SetProj(V3d_Zpos);
1466   }
1467   else if (!strcasecmp (buf_ret, "B"))
1468   {
1469     // Bottom
1470     aView->SetProj(V3d_Zneg);
1471   }
1472   else if (!strcasecmp (buf_ret, "L"))
1473   {
1474     // Left
1475     aView->SetProj(V3d_Xneg);
1476   }
1477   else if (!strcasecmp (buf_ret, "R"))
1478   {
1479     // Right
1480     aView->SetProj(V3d_Xpos);
1481   }
1482   else if (!strcasecmp (buf_ret, "W"))
1483   {
1484     std::cout << "setup WireFrame display mode" << std::endl;
1485     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1486     if(Ctx->NbSelected()==0)
1487       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1488     else{
1489       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1490         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1491       Ctx->UpdateCurrentViewer();
1492     }
1493   }
1494   else if (!strcasecmp (buf_ret, ","))
1495   {
1496     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1497   }
1498   else if (!strcasecmp (buf_ret, "."))
1499   {
1500     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1501   }
1502   else if (!strcasecmp (buf_ret, "/"))
1503   {
1504     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1505     if (aCamera->IsStereo())
1506     {
1507       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1508       aView->Redraw();
1509     }
1510   }
1511   else if (!strcasecmp (buf_ret, "*"))
1512   {
1513     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1514     if (aCamera->IsStereo())
1515     {
1516       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1517       aView->Redraw();
1518     }
1519   }
1520   else if (*buf_ret == THE_KEY_DELETE)
1521   {
1522     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1523     if (!aCtx.IsNull()
1524      && aCtx->NbSelected() > 0)
1525     {
1526       Draw_Interprete ("verase");
1527     }
1528   }
1529   else
1530   {
1531     // Number
1532     Standard_Integer Num = Draw::Atoi(buf_ret);
1533     if(Num>=0 && Num<=7)
1534       ViewerTest::StandardModeActivation(Num);
1535   }
1536 }
1537
1538 //==============================================================================
1539 //function : VT_ProcessExpose
1540 //purpose  : Redraw the View on an Expose Event
1541 //==============================================================================
1542 void VT_ProcessExpose()
1543 {
1544   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1545   if (!aView3d.IsNull())
1546   {
1547     aView3d->Redraw();
1548   }
1549 }
1550
1551 //==============================================================================
1552 //function : VT_ProcessConfigure
1553 //purpose  : Resize the View on an Configure Event
1554 //==============================================================================
1555 void VT_ProcessConfigure()
1556 {
1557   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1558   if (aView3d.IsNull())
1559   {
1560     return;
1561   }
1562
1563   aView3d->MustBeResized();
1564   aView3d->Update();
1565   aView3d->Redraw();
1566 }
1567
1568 //==============================================================================
1569 //function : VT_ProcessButton1Press
1570 //purpose  : Picking
1571 //==============================================================================
1572 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1573                                          const char**     theArgVec,
1574                                          Standard_Boolean theToPick,
1575                                          Standard_Boolean theIsShift)
1576 {
1577   if (TheIsAnimating)
1578   {
1579     TheIsAnimating = Standard_False;
1580     return Standard_False;
1581   }
1582
1583   if (theToPick)
1584   {
1585     Standard_Real X, Y, Z;
1586     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1587
1588     Draw::Set (theArgVec[1], X);
1589     Draw::Set (theArgVec[2], Y);
1590     Draw::Set (theArgVec[3], Z);
1591   }
1592
1593   if (theIsShift)
1594   {
1595     ViewerTest::CurrentEventManager()->ShiftSelect();
1596   }
1597   else
1598   {
1599     ViewerTest::CurrentEventManager()->Select();
1600   }
1601
1602   return Standard_False;
1603 }
1604
1605 //==============================================================================
1606 //function : VT_ProcessButton1Release
1607 //purpose  : End selecting
1608 //==============================================================================
1609 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1610 {
1611   if (IsDragged)
1612   {
1613     IsDragged = Standard_False;
1614     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1615     if (theIsShift)
1616     {
1617       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1618                        X_Motion, Y_Motion);
1619     }
1620     else
1621     {
1622       EM->Select (X_ButtonPress, Y_ButtonPress,
1623                   X_Motion, Y_Motion);
1624     }
1625   }
1626 }
1627
1628 //==============================================================================
1629 //function : VT_ProcessButton3Press
1630 //purpose  : Start Rotation
1631 //==============================================================================
1632 void VT_ProcessButton3Press()
1633 {
1634   Start_Rot = 1;
1635   if (MyHLRIsOn)
1636   {
1637     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1638   }
1639   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1640 }
1641
1642 //==============================================================================
1643 //function : VT_ProcessButton3Release
1644 //purpose  : End rotation
1645 //==============================================================================
1646 void VT_ProcessButton3Release()
1647 {
1648   if (Start_Rot)
1649   {
1650     Start_Rot = 0;
1651     if (MyHLRIsOn)
1652     {
1653       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1654     }
1655   }
1656 }
1657
1658 //==============================================================================
1659 //function : ProcessControlButton1Motion
1660 //purpose  : Zoom
1661 //==============================================================================
1662
1663 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1664 static void ProcessControlButton1Motion()
1665 {
1666   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1667
1668   X_ButtonPress = X_Motion;
1669   Y_ButtonPress = Y_Motion;
1670 }
1671 #endif
1672
1673 //==============================================================================
1674 //function : VT_ProcessControlButton2Motion
1675 //purpose  : Panning
1676 //==============================================================================
1677 void VT_ProcessControlButton2Motion()
1678 {
1679   Standard_Integer aDx = X_Motion - X_ButtonPress;
1680   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1681
1682   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1683
1684   ViewerTest::CurrentView()->Pan (aDx, aDy);
1685
1686   X_ButtonPress = X_Motion;
1687   Y_ButtonPress = Y_Motion;
1688 }
1689
1690 //==============================================================================
1691 //function : VT_ProcessControlButton3Motion
1692 //purpose  : Rotation
1693 //==============================================================================
1694 void VT_ProcessControlButton3Motion()
1695 {
1696   if (Start_Rot)
1697   {
1698     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1699   }
1700 }
1701
1702 //==============================================================================
1703 //function : VT_ProcessMotion
1704 //purpose  :
1705 //==============================================================================
1706 void VT_ProcessMotion()
1707 {
1708   //pre-hilights detected objects at mouse position
1709
1710   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1711   EM->MoveTo(X_Motion, Y_Motion);
1712 }
1713
1714
1715 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1716 {
1717   Xpix = X_Motion;Ypix=Y_Motion;
1718 }
1719
1720 //==============================================================================
1721 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1722 //purpose  : Switches to an axonometric, top, left and other views
1723 //==============================================================================
1724
1725 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1726 {
1727   if ( ViewerTest::CurrentView().IsNull() )
1728   {
1729     di<<"Call vinit before this command, please\n";
1730     return 1;
1731   }
1732
1733   ViewerTest::CurrentView()->SetProj(ori);
1734   return 0;
1735 }
1736
1737 //==============================================================================
1738 //function : VAxo
1739 //purpose  : Switch to an Axonometric view
1740 //Draw arg : No args
1741 //==============================================================================
1742
1743 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1744 {
1745   return ViewProject(di, V3d_XposYnegZpos);
1746 }
1747
1748 //==============================================================================
1749 //function : VTop
1750 //purpose  : Switch to a Top View
1751 //Draw arg : No args
1752 //==============================================================================
1753
1754 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1755 {
1756   return ViewProject(di, V3d_Zpos);
1757 }
1758
1759 //==============================================================================
1760 //function : VBottom
1761 //purpose  : Switch to a Bottom View
1762 //Draw arg : No args
1763 //==============================================================================
1764
1765 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1766 {
1767   return ViewProject(di, V3d_Zneg);
1768 }
1769
1770 //==============================================================================
1771 //function : VLeft
1772 //purpose  : Switch to a Left View
1773 //Draw arg : No args
1774 //==============================================================================
1775
1776 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1777 {
1778   return ViewProject(di, V3d_Xneg);
1779 }
1780
1781 //==============================================================================
1782 //function : VRight
1783 //purpose  : Switch to a Right View
1784 //Draw arg : No args
1785 //==============================================================================
1786
1787 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1788 {
1789   return ViewProject(di, V3d_Xpos);
1790 }
1791
1792 //==============================================================================
1793 //function : VFront
1794 //purpose  : Switch to a Front View
1795 //Draw arg : No args
1796 //==============================================================================
1797
1798 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1799 {
1800   return ViewProject(di, V3d_Yneg);
1801 }
1802
1803 //==============================================================================
1804 //function : VBack
1805 //purpose  : Switch to a Back View
1806 //Draw arg : No args
1807 //==============================================================================
1808
1809 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1810 {
1811   return ViewProject(di, V3d_Ypos);
1812 }
1813
1814 //==============================================================================
1815 //function : VHelp
1816 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1817 //Draw arg : No args
1818 //==============================================================================
1819
1820 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1821 {
1822
1823   di << "Q : Quit the application\n";
1824
1825   di << "=========================\n";
1826   di << "F : FitAll\n";
1827   di << "T : TopView\n";
1828   di << "B : BottomView\n";
1829   di << "R : RightView\n";
1830   di << "L : LeftView\n";
1831   di << "A : AxonometricView\n";
1832   di << "D : ResetView\n";
1833
1834   di << "=========================\n";
1835   di << "S : Shading\n";
1836   di << "W : Wireframe\n";
1837   di << "H : HidelLineRemoval\n";
1838   di << "U : Unset display mode\n";
1839   di << "Delete : Remove selection from viewer\n";
1840
1841   di << "=========================\n";
1842   di << "Selection mode \n";
1843   di << "0 : Shape\n";
1844   di << "1 : Vertex\n";
1845   di << "2 : Edge\n";
1846   di << "3 : Wire\n";
1847   di << "4 : Face\n";
1848   di << "5 : Shell\n";
1849   di << "6 : Solid\n";
1850   di << "7 : Compound\n";
1851
1852   di << "=========================\n";
1853   di << "Z : Switch Z clipping On/Off\n";
1854   di << ", : Hilight next detected\n";
1855   di << ". : Hilight previous detected\n";
1856
1857   return 0;
1858 }
1859
1860 #ifdef _WIN32
1861
1862 static Standard_Boolean Ppick = 0;
1863 static Standard_Integer Pargc = 0;
1864 static const char**           Pargv = NULL;
1865
1866
1867 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1868                                           UINT Msg,
1869                                           WPARAM wParam,
1870                                           LPARAM lParam )
1871 {
1872   if (!ViewerTest_myViews.IsEmpty()) {
1873
1874     WPARAM fwKeys = wParam;
1875
1876     switch( Msg ) {
1877     case WM_CLOSE:
1878        {
1879          // Delete view from map of views
1880          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1881          return 0;
1882        }
1883        break;
1884     case WM_ACTIVATE:
1885       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1886         || ViewerTest::CurrentView().IsNull())
1887       {
1888         // Activate inactive window
1889         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1890         {
1891           ActivateView (FindViewIdByWindowHandle(hwnd));
1892         }
1893       }
1894       break;
1895
1896     case WM_LBUTTONUP:
1897       if (IsDragged && !DragFirst)
1898       {
1899         if (!GetActiveAISManipulator().IsNull())
1900         {
1901           GetActiveAISManipulator()->StopTransform();
1902           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1903         }
1904
1905         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1906         {
1907           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1908           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1909         }
1910
1911         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1912       }
1913       IsDragged = Standard_False;
1914       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1915
1916     case WM_RBUTTONUP:
1917       if (IsDragged && !DragFirst)
1918       {
1919         if (!GetActiveAISManipulator().IsNull())
1920         {
1921           GetActiveAISManipulator()->StopTransform (Standard_False);
1922           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1923         }
1924         IsDragged = Standard_False;
1925       }
1926       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1927
1928     case WM_LBUTTONDOWN:
1929       if (!GetActiveAISManipulator().IsNull())
1930       {
1931         IsDragged = ( fwKeys == MK_LBUTTON );
1932       }
1933       else
1934       {
1935         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1936       }
1937
1938       if (IsDragged)
1939       {
1940         DragFirst = Standard_True;
1941         X_ButtonPress = LOWORD(lParam);
1942         Y_ButtonPress = HIWORD(lParam);
1943       }
1944       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1945
1946     case WM_MOUSEMOVE:
1947       if (IsDragged)
1948       {
1949         X_Motion = LOWORD (lParam);
1950         Y_Motion = HIWORD (lParam);
1951         if (!GetActiveAISManipulator().IsNull())
1952         {
1953           if (DragFirst)
1954           {
1955             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1956           }
1957           else
1958           {
1959             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1960             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1961           }
1962         }
1963         else
1964         {
1965           bool toRedraw = false;
1966           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1967           {
1968             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1969             toRedraw = true;
1970           }
1971
1972           RECT aRect;
1973           if (GetClientRect (hwnd, &aRect))
1974           {
1975             int aHeight = aRect.bottom - aRect.top;
1976             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1977             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1978             toRedraw = true;
1979           }
1980           if (toRedraw)
1981           {
1982             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1983           }
1984         }
1985
1986         DragFirst = Standard_False;
1987       }
1988       else
1989         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1990       break;
1991
1992     default:
1993       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1994     }
1995     return 0;
1996   }
1997   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1998 }
1999
2000
2001 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2002                                        UINT Msg,
2003                                        WPARAM wParam,
2004                                        LPARAM lParam )
2005 {
2006   static int Up = 1;
2007   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2008   if (aView.IsNull())
2009   {
2010     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2011   }
2012
2013     PAINTSTRUCT    ps;
2014
2015     switch( Msg ) {
2016     case WM_PAINT:
2017       BeginPaint(hwnd, &ps);
2018       EndPaint(hwnd, &ps);
2019       VT_ProcessExpose();
2020       break;
2021
2022     case WM_SIZE:
2023       VT_ProcessConfigure();
2024       break;
2025     case WM_MOVE:
2026     case WM_MOVING:
2027     case WM_SIZING:
2028       switch (aView->RenderingParams().StereoMode)
2029       {
2030         case Graphic3d_StereoMode_RowInterlaced:
2031         case Graphic3d_StereoMode_ColumnInterlaced:
2032         case Graphic3d_StereoMode_ChessBoard:
2033           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2034           break;
2035         default:
2036           break;
2037       }
2038       break;
2039
2040     case WM_KEYDOWN:
2041       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2042       {
2043         char c[2];
2044         c[0] = (char) wParam;
2045         c[1] = '\0';
2046         if (wParam == VK_DELETE)
2047         {
2048           c[0] = THE_KEY_DELETE;
2049         }
2050         // comma
2051         else if (wParam == VK_OEM_COMMA)
2052         {
2053           c[0] = ',';
2054         }
2055         // dot
2056         else if (wParam == VK_OEM_PERIOD)
2057         {
2058           c[0] = '.';
2059         }
2060         else if (wParam == VK_DIVIDE)
2061         {
2062           c[0] = '/';
2063         }
2064         // dot
2065         else if (wParam == VK_MULTIPLY)
2066         {
2067           c[0] = '*';
2068         }
2069         VT_ProcessKeyPress (c);
2070       }
2071       break;
2072
2073     case WM_LBUTTONUP:
2074     case WM_MBUTTONUP:
2075     case WM_RBUTTONUP:
2076       Up = 1;
2077       VT_ProcessButton3Release();
2078       break;
2079
2080     case WM_LBUTTONDOWN:
2081     case WM_MBUTTONDOWN:
2082     case WM_RBUTTONDOWN:
2083       {
2084         WPARAM fwKeys = wParam;
2085
2086         Up = 0;
2087
2088         X_ButtonPress = LOWORD(lParam);
2089         Y_ButtonPress = HIWORD(lParam);
2090
2091         if (Msg == WM_LBUTTONDOWN)
2092         {
2093           if ((fwKeys & MK_CONTROL) != 0)
2094           {
2095             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2096           }
2097           else
2098           {
2099             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2100           }
2101         }
2102         else if (Msg == WM_RBUTTONDOWN)
2103         {
2104           // Start rotation
2105           VT_ProcessButton3Press();
2106         }
2107       }
2108       break;
2109
2110     case WM_MOUSEWHEEL:
2111     {
2112       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2113       if (wParam & MK_CONTROL)
2114       {
2115         if (aView->Camera()->IsStereo())
2116         {
2117           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2118           if (aFocus > 0.2
2119            && aFocus < 2.0)
2120           {
2121             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2122             aView->Redraw();
2123           }
2124         }
2125       }
2126       else
2127       {
2128         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2129       }
2130       break;
2131     }
2132
2133     case WM_MOUSEMOVE:
2134       {
2135         //cout << "\t WM_MOUSEMOVE" << endl;
2136         WPARAM fwKeys = wParam;
2137         X_Motion = LOWORD(lParam);
2138         Y_Motion = HIWORD(lParam);
2139
2140         if ( Up &&
2141           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2142           {
2143             Up = 0;
2144             X_ButtonPress = LOWORD(lParam);
2145             Y_ButtonPress = HIWORD(lParam);
2146
2147             if ((fwKeys & MK_RBUTTON) != 0) {
2148               // Start rotation
2149               VT_ProcessButton3Press();
2150             }
2151           }
2152
2153           if ((fwKeys & MK_CONTROL) != 0)
2154           {
2155             if ((fwKeys & MK_LBUTTON) != 0)
2156             {
2157               ProcessControlButton1Motion();
2158             }
2159             else if ((fwKeys & MK_MBUTTON) != 0
2160                  || ((fwKeys & MK_LBUTTON) != 0
2161                   && (fwKeys & MK_RBUTTON) != 0))
2162             {
2163               VT_ProcessControlButton2Motion();
2164             }
2165             else if ((fwKeys & MK_RBUTTON) != 0)
2166             {
2167               VT_ProcessControlButton3Motion();
2168             }
2169           }
2170           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2171           {
2172             VT_ProcessMotion();
2173           }
2174       }
2175       break;
2176
2177     default:
2178       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2179     }
2180     return 0L;
2181 }
2182
2183 //==============================================================================
2184 //function : ViewerMainLoop
2185 //purpose  : Get a Event on the view and dispatch it
2186 //==============================================================================
2187
2188
2189 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2190 {
2191   Ppick = (argc > 0)? 1 : 0;
2192   Pargc = argc;
2193   Pargv = argv;
2194
2195   if ( Ppick ) {
2196     MSG msg;
2197     msg.wParam = 1;
2198
2199     cout << "Start picking" << endl;
2200
2201     while ( Ppick == 1 ) {
2202       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2203       if (GetMessageW (&msg, NULL, 0, 0))
2204       {
2205         TranslateMessage (&msg);
2206         DispatchMessageW (&msg);
2207       }
2208     }
2209
2210     cout << "Picking done" << endl;
2211   }
2212
2213   return Ppick;
2214 }
2215
2216 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2217
2218 int min( int a, int b )
2219 {
2220   if( a<b )
2221     return a;
2222   else
2223     return b;
2224 }
2225
2226 int max( int a, int b )
2227 {
2228   if( a>b )
2229     return a;
2230   else
2231     return b;
2232 }
2233
2234 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2235
2236 {
2237   static XEvent aReport;
2238   Standard_Boolean pick = argc > 0;
2239   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2240   XNextEvent (aDisplay, &aReport);
2241
2242   // Handle event for the chosen display connection
2243   switch (aReport.type) {
2244       case ClientMessage:
2245         {
2246           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2247           {
2248             // Close the window
2249             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2250           }
2251         }
2252         return 0;
2253      case FocusIn:
2254       {
2255          // Activate inactive view
2256          Window aWindow = GetWindowHandle(VT_GetWindow());
2257          if(aWindow != aReport.xfocus.window)
2258          {
2259            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2260          }
2261       }
2262       break;
2263       case Expose:
2264         {
2265           VT_ProcessExpose();
2266         }
2267         break;
2268       case ConfigureNotify:
2269         {
2270           VT_ProcessConfigure();
2271         }
2272         break;
2273       case KeyPress:
2274         {
2275
2276           KeySym ks_ret ;
2277           char buf_ret[11] ;
2278           int ret_len ;
2279           XComposeStatus status_in_out;
2280
2281           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2282             (char *) buf_ret , 10 ,
2283             &ks_ret , &status_in_out ) ;
2284
2285
2286           buf_ret[ret_len] = '\0' ;
2287
2288           if (ret_len)
2289           {
2290             VT_ProcessKeyPress (buf_ret);
2291           }
2292         }
2293         break;
2294       case ButtonPress:
2295         {
2296           X_ButtonPress = aReport.xbutton.x;
2297           Y_ButtonPress = aReport.xbutton.y;
2298
2299           if (aReport.xbutton.button == Button1)
2300           {
2301             if (aReport.xbutton.state & ControlMask)
2302             {
2303               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2304             }
2305             else
2306             {
2307               IsDragged = Standard_True;
2308               DragFirst = Standard_True;
2309             }
2310           }
2311           else if (aReport.xbutton.button == Button3)
2312           {
2313             // Start rotation
2314             VT_ProcessButton3Press();
2315           }
2316         }
2317         break;
2318       case ButtonRelease:
2319         {
2320           if( IsDragged )
2321           {
2322             if( !DragFirst )
2323             {
2324               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2325               {
2326                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2327                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2328               }
2329             }
2330
2331             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2332             if( aContext.IsNull() )
2333             {
2334               cout << "The context is null. Please use vinit before createmesh" << endl;
2335               return 0;
2336             }
2337
2338             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2339             if( aReport.xbutton.button==1 )
2340               if( DragFirst )
2341                 if( ShiftPressed )
2342                 {
2343                   aContext->ShiftSelect (Standard_True);
2344                 }
2345                 else
2346                 {
2347                   aContext->Select (Standard_True);
2348                 }
2349               else
2350                 if( ShiftPressed )
2351                 {
2352                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2353                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2354                                         ViewerTest::CurrentView(), Standard_True);
2355                 }
2356                 else
2357                 {
2358                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2359                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2360                                    ViewerTest::CurrentView(), Standard_True);
2361                 }
2362             else
2363               VT_ProcessButton3Release();
2364
2365             IsDragged = Standard_False;
2366           }
2367           else
2368             VT_ProcessButton3Release();
2369         }
2370         break;
2371       case MotionNotify:
2372         {
2373           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2374           {
2375             break;
2376           }
2377           if( IsDragged )
2378           {
2379             if( !DragFirst )
2380             {
2381               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2382               {
2383                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2384               }
2385             }
2386
2387             X_Motion = aReport.xmotion.x;
2388             Y_Motion = aReport.xmotion.y;
2389             DragFirst = Standard_False;
2390
2391             Window aWindow = GetWindowHandle(VT_GetWindow());
2392             Window aRoot;
2393             int anX, anY;
2394             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2395             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2396             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2397             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2398             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2399           }
2400           else
2401           {
2402             X_Motion = aReport.xmotion.x;
2403             Y_Motion = aReport.xmotion.y;
2404
2405             // remove all the ButtonMotionMaskr
2406             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2407
2408             if ( aReport.xmotion.state & ControlMask ) {
2409               if ( aReport.xmotion.state & Button1Mask ) {
2410                 ProcessControlButton1Motion();
2411               }
2412               else if ( aReport.xmotion.state & Button2Mask ) {
2413                 VT_ProcessControlButton2Motion();
2414               }
2415               else if ( aReport.xmotion.state & Button3Mask ) {
2416                 VT_ProcessControlButton3Motion();
2417               }
2418             }
2419             else
2420             {
2421               VT_ProcessMotion();
2422             }
2423           }
2424         }
2425         break;
2426 }
2427 return pick;
2428 }
2429
2430 //==============================================================================
2431 //function : VProcessEvents
2432 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2433 //       event in the Viewer window
2434 //==============================================================================
2435
2436 static void VProcessEvents(ClientData,int)
2437 {
2438   NCollection_Vector<int> anEventNumbers;
2439   // Get number of messages from every display
2440   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2441        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2442   {
2443     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2444   }
2445     // Handle events for every display
2446   int anEventIter = 0;
2447   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2448        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2449   {
2450     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2451          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2452     {
2453       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2454       int anEventResult = ViewerMainLoop( 0, NULL);
2455       // If window is closed or context was not found finish current event processing loop
2456       if (!anEventResult)
2457         return;
2458     }
2459   }
2460
2461   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2462
2463 }
2464 #endif
2465
2466 //==============================================================================
2467 //function : OSWindowSetup
2468 //purpose  : Setup for the X11 window to be able to cath the event
2469 //==============================================================================
2470
2471
2472 static void OSWindowSetup()
2473 {
2474 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2475   // X11
2476
2477   Window  window   = VT_GetWindow()->XWindow();
2478   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2479   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2480   XSynchronize(aDisplay, 1);
2481
2482   // X11 : For keyboard on SUN
2483   XWMHints wmhints;
2484   wmhints.flags = InputHint;
2485   wmhints.input = 1;
2486
2487   XSetWMHints( aDisplay, window, &wmhints);
2488
2489   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2490     ButtonPressMask | ButtonReleaseMask |
2491     StructureNotifyMask |
2492     PointerMotionMask |
2493     Button1MotionMask | Button2MotionMask |
2494     Button3MotionMask | FocusChangeMask
2495     );
2496   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2497   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2498
2499   XSynchronize(aDisplay, 0);
2500
2501 #else
2502   // _WIN32
2503 #endif
2504
2505 }
2506
2507 //==============================================================================
2508 //function : VFit
2509 //purpose  :
2510 //==============================================================================
2511
2512 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2513 {
2514   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2515   if (aView.IsNull())
2516   {
2517     std::cout << "Error: no active viewer!\n";
2518     return 1;
2519   }
2520
2521   Standard_Boolean toFit = Standard_True;
2522   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2523   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2524   {
2525     TCollection_AsciiString anArg (theArgv[anArgIter]);
2526     anArg.LowerCase();
2527     if (anUpdateTool.parseRedrawMode (anArg))
2528     {
2529       continue;
2530     }
2531     else if (anArg == "-selected")
2532     {
2533       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2534       toFit = Standard_False;
2535     }
2536     else
2537     {
2538       std::cout << "Syntax error at '" << anArg << "'\n";
2539     }
2540   }
2541
2542   if (toFit)
2543   {
2544     aView->FitAll (0.01, Standard_False);
2545   }
2546   return 0;
2547 }
2548
2549 //=======================================================================
2550 //function : VFitArea
2551 //purpose  : Fit view to show area located between two points
2552 //         : given in world 2D or 3D coordinates.
2553 //=======================================================================
2554 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2555 {
2556   Handle(V3d_View) aView = ViewerTest::CurrentView();
2557   if (aView.IsNull())
2558   {
2559     std::cerr << theArgVec[0] << "Error: No active view.\n";
2560     return 1;
2561   }
2562
2563   // Parse arguments.
2564   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2565   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2566
2567   if (theArgNb == 5)
2568   {
2569     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2570     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2571     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2572     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2573   }
2574   else if (theArgNb == 7)
2575   {
2576     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2577     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2578     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2579     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2580     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2581     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2582   }
2583   else
2584   {
2585     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2586     theDI.PrintHelp(theArgVec[0]);
2587     return 1;
2588   }
2589
2590   // Convert model coordinates to view space
2591   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2592   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2593   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2594
2595   // Determine fit area
2596   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2597   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2598
2599   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2600
2601   if (aDiagonal < Precision::Confusion())
2602   {
2603     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2604     return 1;
2605   }
2606
2607   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2608   return 0;
2609 }
2610
2611 //==============================================================================
2612 //function : VZFit
2613 //purpose  : ZFitall, no DRAW arguments
2614 //Draw arg : No args
2615 //==============================================================================
2616 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2617 {
2618   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2619
2620   if (aCurrentView.IsNull())
2621   {
2622     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2623     return 1;
2624   }
2625
2626   if (theArgsNb == 1)
2627   {
2628     aCurrentView->ZFitAll();
2629     aCurrentView->Redraw();
2630     return 0;
2631   }
2632
2633   Standard_Real aScale = 1.0;
2634
2635   if (theArgsNb >= 2)
2636   {
2637     aScale = Draw::Atoi (theArgVec[1]);
2638   }
2639
2640   aCurrentView->ZFitAll (aScale);
2641   aCurrentView->Redraw();
2642
2643   return 0;
2644 }
2645
2646 //==============================================================================
2647 //function : VRepaint
2648 //purpose  :
2649 //==============================================================================
2650 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2651 {
2652   Handle(V3d_View) V = ViewerTest::CurrentView();
2653   if ( !V.IsNull() ) V->Redraw(); return 0;
2654 }
2655
2656 //==============================================================================
2657 //function : VClear
2658 //purpose  : Remove all the object from the viewer
2659 //Draw arg : No args
2660 //==============================================================================
2661
2662 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2663 {
2664   Handle(V3d_View) V = ViewerTest::CurrentView();
2665   if(!V.IsNull())
2666     ViewerTest::Clear();
2667   return 0;
2668 }
2669
2670 //==============================================================================
2671 //function : VPick
2672 //purpose  :
2673 //==============================================================================
2674
2675 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2676 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2677
2678 if ( argc < 4 ) {
2679   di << argv[0] << "Invalid number of arguments\n";
2680   return 1;
2681 }
2682
2683 while (ViewerMainLoop( argc, argv)) {
2684 }
2685
2686 return 0;
2687 }
2688
2689 //==============================================================================
2690 //function : VSetBg
2691 //purpose  : Load image as background
2692 //==============================================================================
2693
2694 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2695 {
2696   if (argc < 2 || argc > 3)
2697   {
2698     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2699     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2700     return 1;
2701   }
2702
2703   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2704   if(AISContext.IsNull())
2705   {
2706     di << "use 'vinit' command before " << argv[0] << "\n";
2707     return 1;
2708   }
2709
2710   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2711   if (argc == 3)
2712   {
2713     const char* szType = argv[2];
2714     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2715     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2716     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2717     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2718     else
2719     {
2720       di << "Wrong fill type : " << szType << "\n";
2721       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2722       return 1;
2723     }
2724   }
2725
2726   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2727   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2728
2729   return 0;
2730 }
2731
2732 //==============================================================================
2733 //function : VSetBgMode
2734 //purpose  : Change background image fill type
2735 //==============================================================================
2736
2737 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2738 {
2739   if (argc != 2)
2740   {
2741     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2742     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2743     return 1;
2744   }
2745
2746   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2747   if(AISContext.IsNull())
2748   {
2749     di << "use 'vinit' command before " << argv[0] << "\n";
2750     return 1;
2751   }
2752   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2753   const char* szType = argv[1];
2754   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2755   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2756   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2757   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2758   else
2759   {
2760     di << "Wrong fill type : " << szType << "\n";
2761     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2762     return 1;
2763   }
2764   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2765   V3dView->SetBgImageStyle(aFillType, Standard_True);
2766   return 0;
2767 }
2768
2769 //==============================================================================
2770 //function : VSetGradientBg
2771 //purpose  : Mount gradient background
2772 //==============================================================================
2773 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2774 {
2775   if (argc != 8 )
2776   {
2777     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2778     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2779     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2780     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2781     return 1;
2782   }
2783
2784   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2785   if(AISContext.IsNull())
2786   {
2787     di << "use 'vinit' command before " << argv[0] << "\n";
2788     return 1;
2789   }
2790   if (argc == 8)
2791   {
2792
2793     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2794     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2795     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2796     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2797
2798     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2799     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2800     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2801
2802     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2803     int aType = Draw::Atoi(argv[7]);
2804     if( aType < 0 || aType > 8 )
2805     {
2806       di << "Wrong fill type \n";
2807       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2808       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2809       return 1;
2810     }
2811
2812     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2813
2814     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2815     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2816   }
2817
2818   return 0;
2819 }
2820
2821 //==============================================================================
2822 //function : VSetGradientBgMode
2823 //purpose  : Change gradient background fill style
2824 //==============================================================================
2825 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2826 {
2827   if (argc != 2 )
2828   {
2829     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2830     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2831     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2832     return 1;
2833   }
2834
2835   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2836   if(AISContext.IsNull())
2837   {
2838     di << "use 'vinit' command before " << argv[0] << "\n";
2839     return 1;
2840   }
2841   if (argc == 2)
2842   {
2843     int aType = Draw::Atoi(argv[1]);
2844     if( aType < 0 || aType > 8 )
2845     {
2846       di << "Wrong fill type \n";
2847       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2848       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2849       return 1;
2850     }
2851
2852     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2853
2854     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2855     V3dView->SetBgGradientStyle( aMethod, 1 );
2856   }
2857
2858   return 0;
2859 }
2860
2861 //==============================================================================
2862 //function : VSetColorBg
2863 //purpose  : Set color background
2864 //==============================================================================
2865 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2866 {
2867   if (argc != 4 )
2868   {
2869     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2870     di << "R,G,B = [0..255]\n";
2871     return 1;
2872   }
2873
2874   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2875   if(AISContext.IsNull())
2876   {
2877     di << "use 'vinit' command before " << argv[0] << "\n";
2878     return 1;
2879   }
2880   if (argc == 4)
2881   {
2882
2883     Standard_Real R = Draw::Atof(argv[1])/255.;
2884     Standard_Real G = Draw::Atof(argv[2])/255.;
2885     Standard_Real B = Draw::Atof(argv[3])/255.;
2886     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2887
2888     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2889     V3dView->SetBackgroundColor( aColor );
2890     V3dView->Update();
2891   }
2892
2893   return 0;
2894 }
2895
2896 //==============================================================================
2897 //function : VSetDefaultBg
2898 //purpose  : Set default viewer background fill color
2899 //==============================================================================
2900 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2901 {
2902   if (theArgNb != 4
2903    && theArgNb != 8)
2904   {
2905     std::cout << "Error: wrong syntax! See usage:\n";
2906     theDI.PrintHelp (theArgVec[0]);
2907     return 1;
2908   }
2909
2910   ViewerTest_DefaultBackground.FillMethod =
2911     theArgNb == 4 ? Aspect_GFM_NONE
2912                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2913
2914   if (theArgNb == 4)
2915   {
2916     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2917     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2918     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2919     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2920   }
2921   else
2922   {
2923     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2924     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2925     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2926     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2927
2928     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2929     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2930     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2931     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2932   }
2933
2934   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2935        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2936   {
2937     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2938     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2939     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2940                                          ViewerTest_DefaultBackground.GradientColor2,
2941                                          ViewerTest_DefaultBackground.FillMethod);
2942   }
2943
2944   return 0;
2945 }
2946
2947 //==============================================================================
2948 //function : VScale
2949 //purpose  : View Scaling
2950 //==============================================================================
2951
2952 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2953 {
2954   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2955   if ( V3dView.IsNull() ) return 1;
2956
2957   if ( argc != 4 ) {
2958     di << argv[0] << "Invalid number of arguments\n";
2959     return 1;
2960   }
2961   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2962   return 0;
2963 }
2964 //==============================================================================
2965 //function : VZBuffTrihedron
2966 //purpose  :
2967 //==============================================================================
2968
2969 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2970                             Standard_Integer  theArgNb,
2971                             const char**      theArgVec)
2972 {
2973   Handle(V3d_View) aView = ViewerTest::CurrentView();
2974   if (aView.IsNull())
2975   {
2976     std::cout << "Error: no active viewer!\n";
2977     return 1;
2978   }
2979
2980   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2981
2982   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2983   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2984   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2985   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2986   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2987   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2988   Standard_Real                 aScale        = 0.1;
2989   Standard_Real                 aSizeRatio    = 0.8;
2990   Standard_Real                 anArrowDiam   = 0.05;
2991   Standard_Integer              aNbFacets     = 12;
2992   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2993   {
2994     Standard_CString        anArg = theArgVec[anArgIter];
2995     TCollection_AsciiString aFlag (anArg);
2996     aFlag.LowerCase();
2997     if (anUpdateTool.parseRedrawMode (aFlag))
2998     {
2999       continue;
3000     }
3001     else if (aFlag == "-on")
3002     {
3003       continue;
3004     }
3005     else if (aFlag == "-off")
3006     {
3007       aView->TriedronErase();
3008       return 0;
3009     }
3010     else if (aFlag == "-pos"
3011           || aFlag == "-position"
3012           || aFlag == "-corner")
3013     {
3014       if (++anArgIter >= theArgNb)
3015       {
3016         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3017         return 1;
3018       }
3019
3020       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3021       aPosName.LowerCase();
3022       if (aPosName == "center")
3023       {
3024         aPosition = Aspect_TOTP_CENTER;
3025       }
3026       else if (aPosName == "left_lower"
3027             || aPosName == "lower_left"
3028             || aPosName == "leftlower"
3029             || aPosName == "lowerleft")
3030       {
3031         aPosition = Aspect_TOTP_LEFT_LOWER;
3032       }
3033       else if (aPosName == "left_upper"
3034             || aPosName == "upper_left"
3035             || aPosName == "leftupper"
3036             || aPosName == "upperleft")
3037       {
3038         aPosition = Aspect_TOTP_LEFT_UPPER;
3039       }
3040       else if (aPosName == "right_lower"
3041             || aPosName == "lower_right"
3042             || aPosName == "rightlower"
3043             || aPosName == "lowerright")
3044       {
3045         aPosition = Aspect_TOTP_RIGHT_LOWER;
3046       }
3047       else if (aPosName == "right_upper"
3048             || aPosName == "upper_right"
3049             || aPosName == "rightupper"
3050             || aPosName == "upperright")
3051       {
3052         aPosition = Aspect_TOTP_RIGHT_UPPER;
3053       }
3054       else
3055       {
3056         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3057         return 1;
3058       }
3059     }
3060     else if (aFlag == "-type")
3061     {
3062       if (++anArgIter >= theArgNb)
3063       {
3064         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3065         return 1;
3066       }
3067
3068       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3069       aTypeName.LowerCase();
3070       if (aTypeName == "wireframe"
3071        || aTypeName == "wire")
3072       {
3073         aVisType = V3d_WIREFRAME;
3074       }
3075       else if (aTypeName == "zbuffer"
3076             || aTypeName == "shaded")
3077       {
3078         aVisType = V3d_ZBUFFER;
3079       }
3080       else
3081       {
3082         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3083       }
3084     }
3085     else if (aFlag == "-scale")
3086     {
3087       if (++anArgIter >= theArgNb)
3088       {
3089         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3090         return 1;
3091       }
3092
3093       aScale = Draw::Atof (theArgVec[anArgIter]);
3094     }
3095     else if (aFlag == "-size"
3096           || aFlag == "-sizeratio")
3097     {
3098       if (++anArgIter >= theArgNb)
3099       {
3100         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3101         return 1;
3102       }
3103
3104       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3105     }
3106     else if (aFlag == "-arrowdiam"
3107           || aFlag == "-arrowdiameter")
3108     {
3109       if (++anArgIter >= theArgNb)
3110       {
3111         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3112         return 1;
3113       }
3114
3115       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3116     }
3117     else if (aFlag == "-nbfacets")
3118     {
3119       if (++anArgIter >= theArgNb)
3120       {
3121         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3122         return 1;
3123       }
3124
3125       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3126     }
3127     else if (aFlag == "-colorlabel"
3128           || aFlag == "-colorlabels")
3129     {
3130       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3131                                                            theArgVec + anArgIter + 1,
3132                                                            aLabelsColor);
3133       if (aNbParsed == 0)
3134       {
3135         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3136         return 1;
3137       }
3138       anArgIter += aNbParsed;
3139     }
3140     else if (aFlag == "-colorarrowx")
3141     {
3142       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3143                                                            theArgVec + anArgIter + 1,
3144                                                            anArrowColorX);
3145       if (aNbParsed == 0)
3146       {
3147         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3148         return 1;
3149       }
3150       anArgIter += aNbParsed;
3151     }
3152     else if (aFlag == "-colorarrowy")
3153     {
3154       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3155                                                            theArgVec + anArgIter + 1,
3156                                                            anArrowColorY);
3157       if (aNbParsed == 0)
3158       {
3159         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3160         return 1;
3161       }
3162       anArgIter += aNbParsed;
3163     }
3164     else if (aFlag == "-colorarrowz")
3165     {
3166       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3167                                                            theArgVec + anArgIter + 1,
3168                                                            anArrowColorZ);
3169       if (aNbParsed == 0)
3170       {
3171         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3172         return 1;
3173       }
3174       anArgIter += aNbParsed;
3175     }
3176     else
3177     {
3178       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3179       return 1;
3180     }
3181   }
3182
3183   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3184                                aSizeRatio, anArrowDiam, aNbFacets);
3185   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3186   aView->ZFitAll();
3187   return 0;
3188 }
3189
3190 //==============================================================================
3191 //function : VRotate
3192 //purpose  : Camera Rotating
3193 //==============================================================================
3194
3195 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3196 {
3197   Handle(V3d_View) aView = ViewerTest::CurrentView();
3198   if (aView.IsNull())
3199   {
3200     std::cout << "No active view!\n";
3201     return 1;
3202   }
3203
3204   Standard_Boolean hasFlags = Standard_False;
3205   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3206   {
3207     Standard_CString        anArg (theArgVec[anArgIter]);
3208     TCollection_AsciiString aFlag (anArg);
3209     aFlag.LowerCase();
3210     if (aFlag == "-mousestart"
3211      || aFlag == "-mousefrom")
3212     {
3213       hasFlags = Standard_True;
3214       if (anArgIter + 2 >= theArgNb)
3215       {
3216         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3217         return 1;
3218       }
3219
3220       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3221       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3222       aView->StartRotation (anX, anY);
3223     }
3224     else if (aFlag == "-mousemove")
3225     {
3226       hasFlags = Standard_True;
3227       if (anArgIter + 2 >= theArgNb)
3228       {
3229         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3230         return 1;
3231       }
3232
3233       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3234       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3235       aView->Rotation (anX, anY);
3236     }
3237     else if (theArgNb != 4
3238           && theArgNb != 7)
3239     {
3240       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3241       return 1;
3242     }
3243   }
3244
3245   if (hasFlags)
3246   {
3247     return 0;
3248   }
3249   else if (theArgNb == 4)
3250   {
3251     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3252     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3253     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3254     aView->Rotate (anAX, anAY, anAZ);
3255     return 0;
3256   }
3257   else if (theArgNb == 7)
3258   {
3259     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3260     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3261     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3262
3263     Standard_Real anX = Draw::Atof (theArgVec[4]);
3264     Standard_Real anY = Draw::Atof (theArgVec[5]);
3265     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3266
3267     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3268     return 0;
3269   }
3270
3271   std::cout << "Error: Invalid number of arguments\n";
3272   return 1;
3273 }
3274
3275 //==============================================================================
3276 //function : VZoom
3277 //purpose  : View zoom in / out (relative to current zoom)
3278 //==============================================================================
3279
3280 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3281   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3282   if ( V3dView.IsNull() ) {
3283     return 1;
3284   }
3285
3286   if ( argc == 2 ) {
3287     Standard_Real coef = Draw::Atof(argv[1]);
3288     if ( coef <= 0.0 ) {
3289       di << argv[1] << "Invalid value\n";
3290       return 1;
3291     }
3292     V3dView->SetZoom( Draw::Atof(argv[1]) );
3293     return 0;
3294   } else {
3295     di << argv[0] << " Invalid number of arguments\n";
3296     return 1;
3297   }
3298 }
3299
3300 //==============================================================================
3301 //function : VPan
3302 //purpose  : View panning (in pixels)
3303 //==============================================================================
3304
3305 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3306   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3307   if ( V3dView.IsNull() ) return 1;
3308
3309   if ( argc == 3 ) {
3310     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3311     return 0;
3312   } else {
3313     di << argv[0] << " Invalid number of arguments\n";
3314     return 1;
3315   }
3316 }
3317
3318 //==============================================================================
3319 //function : VPlace
3320 //purpose  : Place the point (in pixels) at the center of the window
3321 //==============================================================================
3322 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3323 {
3324   Handle(V3d_View) aView = ViewerTest::CurrentView();
3325   if (aView.IsNull())
3326   {
3327     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3328     return 1;
3329   }
3330
3331   if (theArgNb != 3)
3332   {
3333     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3334     return 1;
3335   }
3336
3337   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3338
3339   return 0;
3340 }
3341
3342 //==============================================================================
3343 //function : VExport
3344 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3345 //==============================================================================
3346
3347 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3348 {
3349   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3350   if (V3dView.IsNull())
3351     return 1;
3352
3353   if (argc == 1)
3354   {
3355     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3356     return 1;
3357   }
3358
3359   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3360   TCollection_AsciiString aFormatStr;
3361
3362   TCollection_AsciiString aFileName (argv[1]);
3363   Standard_Integer aLen = aFileName.Length();
3364
3365   if (argc > 2)
3366   {
3367     aFormatStr = TCollection_AsciiString (argv[2]);
3368   }
3369   else if (aLen >= 4)
3370   {
3371     if (aFileName.Value (aLen - 2) == '.')
3372     {
3373       aFormatStr = aFileName.ToCString() + aLen - 2;
3374     }
3375     else if (aFileName.Value (aLen - 3) == '.')
3376     {
3377       aFormatStr = aFileName.ToCString() + aLen - 3;
3378     }
3379     else
3380     {
3381       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3382       return 1;
3383     }
3384   }
3385   else
3386   {
3387     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3388     return 1;
3389   }
3390
3391   aFormatStr.UpperCase();
3392   if (aFormatStr == "PS")
3393     anExpFormat = Graphic3d_EF_PostScript;
3394   else if (aFormatStr == "EPS")
3395     anExpFormat = Graphic3d_EF_EnhPostScript;
3396   else if (aFormatStr == "TEX")
3397     anExpFormat = Graphic3d_EF_TEX;
3398   else if (aFormatStr == "PDF")
3399     anExpFormat = Graphic3d_EF_PDF;
3400   else if (aFormatStr == "SVG")
3401     anExpFormat = Graphic3d_EF_SVG;
3402   else if (aFormatStr == "PGF")
3403     anExpFormat = Graphic3d_EF_PGF;
3404   else if (aFormatStr == "EMF")
3405     anExpFormat = Graphic3d_EF_EMF;
3406   else
3407   {
3408     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3409     return 1;
3410   }
3411
3412   Standard_DISABLE_DEPRECATION_WARNINGS
3413   try
3414   {
3415     if (!V3dView->Export (argv[1], anExpFormat))
3416     {
3417       di << "Error: export of image to " << aFormatStr << " failed!\n";
3418     }
3419   }
3420   catch (Standard_Failure const& anException)
3421   {
3422     di << "Error: export of image to " << aFormatStr << " failed";
3423     di << " (exception: " << anException.GetMessageString() << ")";
3424   }
3425   Standard_ENABLE_DEPRECATION_WARNINGS
3426   return 0;
3427 }
3428
3429 static int VColorScale (Draw_Interpretor& theDI,
3430                         Standard_Integer  theArgNb,
3431                         const char**      theArgVec)
3432 {
3433   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3434   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3435   if (aContext.IsNull())
3436   {
3437     std::cout << "Error: no active view!\n";
3438     return 1;
3439   }
3440   if (theArgNb <= 1)
3441   {
3442     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3443     return 1;
3444   }
3445
3446   Handle(AIS_ColorScale) aColorScale;
3447   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3448   {
3449     // find existing object
3450     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3451     if (aColorScale.IsNull())
3452     {
3453       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3454       return 1;
3455     }
3456   }
3457
3458   if (theArgNb <= 2)
3459   {
3460     if (aColorScale.IsNull())
3461     {
3462       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3463       return 1;
3464     }
3465
3466     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3467           << "Min range: "            << aColorScale->GetMin() << "\n"
3468           << "Max range: "            << aColorScale->GetMax() << "\n"
3469           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3470           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3471           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3472           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3473           << "Label position: ";
3474     switch (aColorScale->GetLabelPosition())
3475     {
3476       case Aspect_TOCSP_NONE:
3477         theDI << "None\n";
3478         break;
3479       case Aspect_TOCSP_LEFT:
3480         theDI << "Left\n";
3481         break;
3482       case Aspect_TOCSP_RIGHT:
3483         theDI << "Right\n";
3484         break;
3485       case Aspect_TOCSP_CENTER:
3486         theDI << "Center\n";
3487         break;
3488     }
3489     return 0;
3490   }
3491
3492   if (aColorScale.IsNull())
3493   {
3494     aColorScale = new AIS_ColorScale();
3495     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3496     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3497   }
3498
3499   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3500   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3501   {
3502     Standard_CString        anArg = theArgVec[anArgIter];
3503     TCollection_AsciiString aFlag (anArg);
3504     aFlag.LowerCase();
3505     if (anUpdateTool.parseRedrawMode (aFlag))
3506     {
3507       continue;
3508     }
3509     else if (aFlag == "-range")
3510     {
3511       if (anArgIter + 3 >= theArgNb)
3512       {
3513         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3514         return 1;
3515       }
3516
3517       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3518       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3519       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3520       if (!aRangeMin.IsRealValue()
3521        || !aRangeMax.IsRealValue())
3522       {
3523         std::cout << "Error: the range values should be real!\n";
3524         return 1;
3525       }
3526       else if (!aNbIntervals.IsIntegerValue())
3527       {
3528         std::cout << "Error: the number of intervals should be integer!\n";
3529         return 1;
3530       }
3531
3532       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3533       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3534     }
3535     else if (aFlag == "-font")
3536     {
3537       if (anArgIter + 1 >= theArgNb)
3538       {
3539         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3540         return 1;
3541       }
3542       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3543       if (!aFontArg.IsIntegerValue())
3544       {
3545         std::cout << "Error: HeightFont value should be integer!\n";
3546         return 1;
3547       }
3548
3549       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3550       anArgIter += 1;
3551     }
3552     else if (aFlag == "-textpos")
3553     {
3554       if (anArgIter + 1 >= theArgNb)
3555       {
3556         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3557         return 1;
3558       }
3559
3560       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3561       aTextPosArg.LowerCase();
3562       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3563       if (aTextPosArg == "none")
3564       {
3565         aLabPosition = Aspect_TOCSP_NONE;
3566       }
3567       else if (aTextPosArg == "left")
3568       {
3569         aLabPosition = Aspect_TOCSP_LEFT;
3570       }
3571       else if (aTextPosArg == "right")
3572       {
3573         aLabPosition = Aspect_TOCSP_RIGHT;
3574       }
3575       else if (aTextPosArg == "center")
3576       {
3577         aLabPosition = Aspect_TOCSP_CENTER;
3578       }
3579       else
3580       {
3581         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3582         return 1;
3583       }
3584       aColorScale->SetLabelPosition (aLabPosition);
3585     }
3586     else if (aFlag == "-logarithmic"
3587           || aFlag == "-log")
3588     {
3589       if (anArgIter + 1 >= theArgNb)
3590       {
3591         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3592         return 1;
3593       }
3594
3595       Standard_Boolean IsLog;
3596       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3597       {
3598         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3599         return 1;
3600       }
3601       aColorScale->SetLogarithmic (IsLog);
3602     }
3603     else if (aFlag == "-huerange"
3604           || aFlag == "-hue")
3605     {
3606       if (anArgIter + 2 >= theArgNb)
3607       {
3608         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3609         return 1;
3610       }
3611
3612       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3613       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3614       aColorScale->SetHueRange (aHueMin, aHueMax);
3615     }
3616     else if (aFlag == "-colorrange")
3617     {
3618       Quantity_Color aColorMin, aColorMax;
3619       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3620                                                             theArgVec + (anArgIter + 1),
3621                                                             aColorMin);
3622       anArgIter += aNbParsed1;
3623       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3624                                                             theArgVec + (anArgIter + 1),
3625                                                             aColorMax);
3626       anArgIter += aNbParsed2;
3627       if (aNbParsed1 == 0
3628        || aNbParsed2 == 0)
3629       {
3630         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3631         return 1;
3632       }
3633
3634       aColorScale->SetColorRange (aColorMin, aColorMax);
3635     }
3636     else if (aFlag == "-reversed"
3637           || aFlag == "-inverted"
3638           || aFlag == "-topdown"
3639           || aFlag == "-bottomup")
3640     {
3641       Standard_Boolean toEnable = Standard_True;
3642       if (anArgIter + 1 < theArgNb
3643        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3644       {
3645         ++anArgIter;
3646       }
3647       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3648     }
3649     else if (aFlag == "-smooth"
3650           || aFlag == "-smoothtransition")
3651     {
3652       Standard_Boolean toEnable = Standard_True;
3653       if (anArgIter + 1 < theArgNb
3654        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3655       {
3656         ++anArgIter;
3657       }
3658       aColorScale->SetSmoothTransition (toEnable);
3659     }
3660     else if (aFlag == "-xy")
3661     {
3662       if (anArgIter + 2 >= theArgNb)
3663       {
3664         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3665         return 1;
3666       }
3667
3668       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3669       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3670       if (!anX.IsIntegerValue()
3671        || !anY.IsIntegerValue())
3672       {
3673         std::cout << "Error: coordinates should be integer values!\n";
3674         return 1;
3675       }
3676
3677       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3678     }
3679     else if (aFlag == "-width"
3680           || aFlag == "-w"
3681           || aFlag == "-breadth")
3682     {
3683       if (anArgIter + 1 >= theArgNb)
3684       {
3685         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3686         return 1;
3687       }
3688
3689       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3690       if (!aBreadth.IsIntegerValue())
3691       {
3692         std::cout << "Error: a width should be an integer value!\n";
3693         return 1;
3694       }
3695       aColorScale->SetBreadth (aBreadth.IntegerValue());
3696     }
3697     else if (aFlag == "-height"
3698           || aFlag == "-h")
3699     {
3700       if (anArgIter + 1 >= theArgNb)
3701       {
3702         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3703         return 1;
3704       }
3705
3706       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3707       if (!aHeight.IsIntegerValue())
3708       {
3709         std::cout << "Error: a width should be an integer value!\n";
3710         return 1;
3711       }
3712       aColorScale->SetHeight (aHeight.IntegerValue());
3713     }
3714     else if (aFlag == "-color")
3715     {
3716       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3717       {
3718         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3719         return 1;
3720       }
3721       else if (anArgIter + 2 >= theArgNb)
3722       {
3723         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3724         return 1;
3725       }
3726
3727       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3728       if (!anInd.IsIntegerValue())
3729       {
3730         std::cout << "Error: Index value should be integer!\n";
3731         return 1;
3732       }
3733       const Standard_Integer anIndex = anInd.IntegerValue();
3734       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3735       {
3736         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3737         return 1;
3738       }
3739
3740       Quantity_Color aColor;
3741       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3742                                                            theArgVec + (anArgIter + 1),
3743                                                            aColor);
3744       if (aNbParsed == 0)
3745       {
3746         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3747         return 1;
3748       }
3749       aColorScale->SetIntervalColor (aColor, anIndex);
3750       aColorScale->SetColorType (Aspect_TOCSD_USER);
3751       anArgIter += aNbParsed;
3752     }
3753     else if (aFlag == "-label")
3754     {
3755       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3756       {
3757         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3758         return 1;
3759       }
3760       else if (anArgIter + 2 >= theArgNb)
3761       {
3762         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3763         return 1;
3764       }
3765
3766       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3767       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
3768       {
3769         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
3770         return 1;
3771       }
3772
3773       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3774       aColorScale->SetLabel     (aText, anIndex);
3775       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3776       anArgIter += 2;
3777     }
3778     else if (aFlag == "-labelat"
3779           || aFlag == "-labat"
3780           || aFlag == "-labelatborder"
3781           || aFlag == "-labatborder"
3782           || aFlag == "-labelatcenter"
3783           || aFlag == "-labatcenter")
3784     {
3785       Standard_Boolean toEnable = Standard_True;
3786       if (aFlag == "-labelat"
3787        || aFlag == "-labat")
3788       {
3789         Standard_Integer aLabAtBorder = -1;
3790         if (++anArgIter >= theArgNb)
3791         {
3792           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
3793           anAtBorder.LowerCase();
3794           if (anAtBorder == "border")
3795           {
3796             aLabAtBorder = 1;
3797           }
3798           else if (anAtBorder == "center")
3799           {
3800             aLabAtBorder = 0;
3801           }
3802         }
3803         if (aLabAtBorder == -1)
3804         {
3805           std::cout << "Syntax error at argument '" << anArg << "'!\n";
3806           return 1;
3807         }
3808         toEnable = (aLabAtBorder == 1);
3809       }
3810       else if (anArgIter + 1 < theArgNb
3811             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3812       {
3813         ++anArgIter;
3814       }
3815       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
3816                                   || aFlag == "-labatcenter"
3817                                    ? !toEnable
3818                                    :  toEnable);
3819     }
3820     else if (aFlag == "-colors")
3821     {
3822       Aspect_SequenceOfColor aSeq;
3823       for (;;)
3824       {
3825         Quantity_Color aColor;
3826         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3827                                                              theArgVec + (anArgIter + 1),
3828                                                              aColor);
3829         if (aNbParsed == 0)
3830         {
3831           break;
3832         }
3833         anArgIter += aNbParsed;
3834         aSeq.Append (aColor);
3835       }
3836       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
3837       {
3838         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3839                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
3840         return 1;
3841       }
3842
3843       aColorScale->SetColors    (aSeq);
3844       aColorScale->SetColorType (Aspect_TOCSD_USER);
3845     }
3846     else if (aFlag == "-labels"
3847           || aFlag == "-freelabels")
3848     {
3849       if (anArgIter + 1 >= theArgNb)
3850       {
3851         std::cout << "Syntax error at argument '" << anArg << "'!\n";
3852         return 1;
3853       }
3854
3855       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
3856                                  ? aColorScale->GetNumberOfIntervals() + 1
3857                                  : aColorScale->GetNumberOfIntervals();
3858       if (aFlag == "-freelabels")
3859       {
3860         ++anArgIter;
3861         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
3862       }
3863       if (anArgIter + aNbLabels >= theArgNb)
3864       {
3865         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
3866         return 1;
3867       }
3868
3869       TColStd_SequenceOfExtendedString aSeq;
3870       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
3871       {
3872         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
3873       }
3874       aColorScale->SetLabels (aSeq);
3875       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3876     }
3877     else if (aFlag == "-title")
3878     {
3879       if (anArgIter + 1 >= theArgNb)
3880       {
3881         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3882         return 1;
3883       }
3884
3885       Standard_Boolean isTwoArgs = Standard_False;
3886       if (anArgIter + 2 < theArgNb)
3887       {
3888         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3889         aSecondArg.LowerCase();
3890       Standard_DISABLE_DEPRECATION_WARNINGS
3891         if (aSecondArg == "none")
3892         {
3893           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
3894           isTwoArgs = Standard_True;
3895         }
3896         else if (aSecondArg == "left")
3897         {
3898           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
3899           isTwoArgs = Standard_True;
3900         }
3901         else if (aSecondArg == "right")
3902         {
3903           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
3904           isTwoArgs = Standard_True;
3905         }
3906         else if (aSecondArg == "center")
3907         {
3908           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
3909           isTwoArgs = Standard_True;
3910         }
3911       Standard_ENABLE_DEPRECATION_WARNINGS
3912       }
3913
3914       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
3915       if (isTwoArgs)
3916       {
3917         anArgIter += 1;
3918       }
3919       anArgIter += 1;
3920     }
3921     else if (aFlag == "-demoversion"
3922           || aFlag == "-demo")
3923     {
3924       aColorScale->SetPosition (0, 0);
3925       aColorScale->SetTextHeight (16);
3926       aColorScale->SetRange (0.0, 100.0);
3927       aColorScale->SetNumberOfIntervals (10);
3928       aColorScale->SetBreadth (0);
3929       aColorScale->SetHeight  (0);
3930       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
3931       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
3932       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
3933     }
3934     else if (aFlag == "-findcolor")
3935     {
3936       if (anArgIter + 1 >= theArgNb)
3937       {
3938         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3939         return 1;
3940       }
3941
3942       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3943
3944       if (!anArg1.IsRealValue())
3945       {
3946         std::cout << "Error: the value should be real!\n";
3947         return 1;
3948       }
3949
3950       Quantity_Color aColor;
3951       aColorScale->FindColor (anArg1.RealValue(), aColor);
3952       theDI << Quantity_Color::StringName (aColor.Name());
3953       return 0;
3954     }
3955     else
3956     {
3957       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3958       return 1;
3959     }
3960   }
3961
3962   Standard_Integer aWinWidth = 0, aWinHeight = 0;
3963   aView->Window()->Size (aWinWidth, aWinHeight);
3964   if (aColorScale->GetBreadth() == 0)
3965   {
3966     aColorScale->SetBreadth (aWinWidth);
3967   }
3968   if (aColorScale->GetHeight() == 0)
3969   {
3970     aColorScale->SetHeight (aWinHeight);
3971   }
3972   aColorScale->SetToUpdate();
3973   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
3974   return 0;
3975 }
3976
3977 //==============================================================================
3978 //function : VGraduatedTrihedron
3979 //purpose  : Displays or hides a graduated trihedron
3980 //==============================================================================
3981 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
3982                                   Quantity_Color& theColor)
3983 {
3984   Quantity_NameOfColor aColorName;
3985   TCollection_AsciiString aVal = theValue;
3986   aVal.UpperCase();
3987   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
3988   {
3989     return Standard_False;
3990   }
3991   theColor = Quantity_Color (aColorName);
3992   return Standard_True;
3993 }
3994
3995 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
3996 {
3997   if (theArgNum < 2)
3998   {
3999     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4000               << theArgs[0] <<"' for more information.\n";
4001     return 1;  //TCL_ERROR
4002   }
4003
4004   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4005   TCollection_AsciiString aParseKey;
4006   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4007   {
4008     TCollection_AsciiString anArg (theArgs [anArgIt]);
4009
4010     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4011     {
4012       aParseKey = anArg;
4013       aParseKey.Remove (1);
4014       aParseKey.LowerCase();
4015       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4016       continue;
4017     }
4018
4019     if (aParseKey.IsEmpty())
4020     {
4021       continue;
4022     }
4023
4024     aMapOfArgs(aParseKey)->Append (anArg);
4025   }
4026
4027   // Check parameters
4028   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4029        aMapIt.More(); aMapIt.Next())
4030   {
4031     const TCollection_AsciiString& aKey = aMapIt.Key();
4032     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4033
4034     // Bool key, without arguments
4035     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4036         && anArgs->IsEmpty())
4037     {
4038       continue;
4039     }
4040
4041     // One argument
4042     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4043           && anArgs->Length() == 1)
4044     {
4045       continue;
4046     }
4047
4048     // On/off arguments
4049     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4050         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4051         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4052         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4053         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4054     {
4055       continue;
4056     }
4057
4058     // One string argument
4059     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4060           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4061           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4062     {
4063       continue;
4064     }
4065
4066     // One integer argument
4067     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4068           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4069           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4070           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4071          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4072     {
4073       continue;
4074     }
4075
4076     // One real argument
4077     if ( aKey.IsEqual ("arrowlength")
4078          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4079     {
4080       continue;
4081     }
4082
4083     // Two string arguments
4084     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4085          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4086     {
4087       continue;
4088     }
4089
4090     TCollection_AsciiString aLowerKey;
4091     aLowerKey  = "-";
4092     aLowerKey += aKey;
4093     aLowerKey.LowerCase();
4094     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4095     std::cout << "Type help for more information.\n";
4096     return 1;
4097   }
4098
4099   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4100   if (anAISContext.IsNull())
4101   {
4102     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4103     return 1;
4104   }
4105
4106   Standard_Boolean toDisplay = Standard_True;
4107   Quantity_Color aColor;
4108   Graphic3d_GraduatedTrihedron aTrihedronData;
4109   // Process parameters
4110   Handle(TColStd_HSequenceOfAsciiString) aValues;
4111   if (aMapOfArgs.Find ("off", aValues))
4112   {
4113     toDisplay = Standard_False;
4114   }
4115
4116   // AXES NAMES
4117   if (aMapOfArgs.Find ("xname", aValues))
4118   {
4119     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4120   }
4121   if (aMapOfArgs.Find ("yname", aValues))
4122   {
4123     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4124   }
4125   if (aMapOfArgs.Find ("zname", aValues))
4126   {
4127     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4128   }
4129   if (aMapOfArgs.Find ("xdrawname", aValues))
4130   {
4131     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4132   }
4133   if (aMapOfArgs.Find ("ydrawname", aValues))
4134   {
4135     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4136   }
4137   if (aMapOfArgs.Find ("zdrawname", aValues))
4138   {
4139     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4140   }
4141   if (aMapOfArgs.Find ("xnameoffset", aValues))
4142   {
4143     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4144   }
4145   if (aMapOfArgs.Find ("ynameoffset", aValues))
4146   {
4147     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4148   }
4149   if (aMapOfArgs.Find ("znameoffset", aValues))
4150   {
4151     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4152   }
4153
4154   // COLORS
4155   if (aMapOfArgs.Find ("xnamecolor", aValues))
4156   {
4157     if (!GetColor (aValues->Value(1), aColor))
4158     {
4159       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4160       return 1;
4161     }
4162     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4163   }
4164   if (aMapOfArgs.Find ("ynamecolor", aValues))
4165   {
4166     if (!GetColor (aValues->Value(1), aColor))
4167     {
4168       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4169       return 1;
4170     }
4171     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4172   }
4173   if (aMapOfArgs.Find ("znamecolor", aValues))
4174   {
4175     if (!GetColor (aValues->Value(1), aColor))
4176     {
4177       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4178       return 1;
4179     }
4180     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4181   }
4182   if (aMapOfArgs.Find ("xcolor", aValues))
4183   {
4184     if (!GetColor (aValues->Value(1), aColor))
4185     {
4186       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4187       return 1;
4188     }
4189     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4190   }
4191   if (aMapOfArgs.Find ("ycolor", aValues))
4192   {
4193     if (!GetColor (aValues->Value(1), aColor))
4194     {
4195       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4196       return 1;
4197     }
4198     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4199   }
4200   if (aMapOfArgs.Find ("zcolor", aValues))
4201   {
4202     if (!GetColor (aValues->Value(1), aColor))
4203     {
4204       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4205       return 1;
4206     }
4207     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4208   }
4209
4210   // TICKMARKS
4211   if (aMapOfArgs.Find ("xticks", aValues))
4212   {
4213     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4214   }
4215   if (aMapOfArgs.Find ("yticks", aValues))
4216   {
4217     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4218   }
4219   if (aMapOfArgs.Find ("zticks", aValues))
4220   {
4221     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4222   }
4223   if (aMapOfArgs.Find ("xticklength", aValues))
4224   {
4225     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4226   }
4227   if (aMapOfArgs.Find ("yticklength", aValues))
4228   {
4229     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4230   }
4231   if (aMapOfArgs.Find ("zticklength", aValues))
4232   {
4233     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4234   }
4235   if (aMapOfArgs.Find ("xdrawticks", aValues))
4236   {
4237     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4238   }
4239   if (aMapOfArgs.Find ("ydrawticks", aValues))
4240   {
4241     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4242   }
4243   if (aMapOfArgs.Find ("zdrawticks", aValues))
4244   {
4245     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4246   }
4247
4248   // VALUES
4249   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4250   {
4251     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4252   }
4253   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4254   {
4255     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4256   }
4257   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4258   {
4259     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4260   }
4261   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4262   {
4263     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4264   }
4265   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4266   {
4267     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4268   }
4269   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4270   {
4271     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4272   }
4273
4274   // ARROWS
4275   if (aMapOfArgs.Find ("arrowlength", aValues))
4276   {
4277     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4278   }
4279
4280   // FONTS
4281   if (aMapOfArgs.Find ("namefont", aValues))
4282   {
4283     aTrihedronData.SetNamesFont (aValues->Value(1));
4284   }
4285   if (aMapOfArgs.Find ("valuesfont", aValues))
4286   {
4287     aTrihedronData.SetValuesFont (aValues->Value(1));
4288   }
4289
4290   if (aMapOfArgs.Find ("drawgrid", aValues))
4291   {
4292     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4293   }
4294   if (aMapOfArgs.Find ("drawaxes", aValues))
4295   {
4296     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4297   }
4298
4299   // The final step: display of erase trihedron
4300   if (toDisplay)
4301   {
4302     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4303   }
4304   else
4305   {
4306     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4307   }
4308
4309   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4310   ViewerTest::CurrentView()->Redraw();
4311
4312   return 0;
4313 }
4314
4315 //==============================================================================
4316 //function : VTile
4317 //purpose  :
4318 //==============================================================================
4319 static int VTile (Draw_Interpretor& theDI,
4320                   Standard_Integer  theArgNb,
4321                   const char**      theArgVec)
4322 {
4323   Handle(V3d_View) aView = ViewerTest::CurrentView();
4324   if (aView.IsNull())
4325   {
4326     std::cerr << "Error: no active viewer.\n";
4327     return 1;
4328   }
4329
4330   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4331   if (theArgNb < 2)
4332   {
4333     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4334           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4335           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4336     return 0;
4337   }
4338
4339   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4340   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4341   {
4342     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4343     anArg.LowerCase();
4344     if (anArg == "-lowerleft"
4345      || anArg == "-upperleft")
4346     {
4347       if (anArgIter + 3 < theArgNb)
4348       {
4349         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4350         return 1;
4351       }
4352       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4353       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4354       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4355     }
4356     else if (anArg == "-total"
4357           || anArg == "-totalsize"
4358           || anArg == "-viewsize")
4359     {
4360       if (anArgIter + 3 < theArgNb)
4361       {
4362         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4363         return 1;
4364       }
4365       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4366       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4367       if (aTile.TotalSize.x() < 1
4368        || aTile.TotalSize.y() < 1)
4369       {
4370         std::cerr << "Error: total size is incorrect.\n";
4371         return 1;
4372       }
4373     }
4374     else if (anArg == "-tilesize")
4375     {
4376       if (anArgIter + 3 < theArgNb)
4377       {
4378         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4379         return 1;
4380       }
4381
4382       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4383       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4384       if (aTile.TileSize.x() < 1
4385        || aTile.TileSize.y() < 1)
4386       {
4387         std::cerr << "Error: tile size is incorrect.\n";
4388         return 1;
4389       }
4390     }
4391     else if (anArg == "-unset")
4392     {
4393       aView->Camera()->SetTile (Graphic3d_CameraTile());
4394       aView->Redraw();
4395       return 0;
4396     }
4397   }
4398
4399   if (aTile.TileSize.x() < 1
4400    || aTile.TileSize.y() < 1)
4401   {
4402     std::cerr << "Error: tile size is undefined.\n";
4403     return 1;
4404   }
4405   else if (aTile.TotalSize.x() < 1
4406         || aTile.TotalSize.y() < 1)
4407   {
4408     std::cerr << "Error: total size is undefined.\n";
4409     return 1;
4410   }
4411
4412   aView->Camera()->SetTile (aTile);
4413   aView->Redraw();
4414   return 0;
4415 }
4416
4417 //! Format ZLayer ID.
4418 inline const char* formZLayerId (const Standard_Integer theLayerId)
4419 {
4420   switch (theLayerId)
4421   {
4422     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4423     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4424     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4425     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4426     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4427     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4428   }
4429   return "";
4430 }
4431
4432 //! Print the ZLayer information.
4433 inline void printZLayerInfo (Draw_Interpretor& theDI,
4434                              const Graphic3d_ZLayerSettings& theLayer)
4435 {
4436   if (!theLayer.Name().IsEmpty())
4437   {
4438     theDI << "  Name: " << theLayer.Name() << "\n";
4439   }
4440   if (theLayer.IsImmediate())
4441   {
4442     theDI << "  Immediate: TRUE\n";
4443   }
4444   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4445   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4446   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4447   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4448   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4449   {
4450     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4451   }
4452 }
4453
4454 //==============================================================================
4455 //function : VZLayer
4456 //purpose  : Test z layer operations for v3d viewer
4457 //==============================================================================
4458 static int VZLayer (Draw_Interpretor& theDI,
4459                     Standard_Integer  theArgNb,
4460                     const char**      theArgVec)
4461 {
4462   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4463   if (aContextAIS.IsNull())
4464   {
4465     std::cout << "No active viewer!\n";
4466     return 1;
4467   }
4468
4469   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4470   if (theArgNb < 2)
4471   {
4472     TColStd_SequenceOfInteger aLayers;
4473     aViewer->GetAllZLayers (aLayers);
4474     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4475     {
4476       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4477       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4478       printZLayerInfo (theDI, aSettings);
4479     }
4480     return 1;
4481   }
4482
4483   Standard_Integer anArgIter = 1;
4484   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4485   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4486   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4487   {
4488     ++anArgIter;
4489   }
4490
4491   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4492   if (aFirstArg.IsIntegerValue())
4493   {
4494     ++anArgIter;
4495     aLayerId = aFirstArg.IntegerValue();
4496   }
4497   else
4498   {
4499     aFirstArg.LowerCase();
4500     if (aFirstArg == "default"
4501      || aFirstArg == "def")
4502     {
4503       aLayerId = Graphic3d_ZLayerId_Default;
4504       ++anArgIter;
4505     }
4506     else if (aFirstArg == "top")
4507     {
4508       aLayerId = Graphic3d_ZLayerId_Top;
4509       ++anArgIter;
4510     }
4511     else if (aFirstArg == "topmost")
4512     {
4513       aLayerId = Graphic3d_ZLayerId_Topmost;
4514       ++anArgIter;
4515     }
4516     else if (aFirstArg == "overlay"
4517           || aFirstArg == "toposd")
4518     {
4519       aLayerId = Graphic3d_ZLayerId_TopOSD;
4520       ++anArgIter;
4521     }
4522     else if (aFirstArg == "underlay"
4523           || aFirstArg == "botosd")
4524     {
4525       aLayerId = Graphic3d_ZLayerId_BotOSD;
4526       ++anArgIter;
4527     }
4528     else
4529     {
4530       TColStd_SequenceOfInteger aLayers;
4531       aViewer->GetAllZLayers (aLayers);
4532       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4533       {
4534         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4535         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4536         {
4537           aLayerId = aLayeriter.Value();
4538           ++anArgIter;
4539           break;
4540         }
4541       }
4542     }
4543   }
4544
4545   for (; anArgIter < theArgNb; ++anArgIter)
4546   {
4547     // perform operation
4548     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4549     anArg.LowerCase();
4550     if (anUpdateTool.parseRedrawMode (anArg))
4551     {
4552       //
4553     }
4554     else if (anArg == "-add"
4555           || anArg == "add")
4556     {
4557       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4558       if (!aViewer->AddZLayer (aLayerId))
4559       {
4560         std::cout << "Error: can not add a new z layer!\n";
4561         return 0;
4562       }
4563
4564       theDI << aLayerId;
4565     }
4566     else if (anArg == "-del"
4567           || anArg == "-delete"
4568           || anArg == "del")
4569     {
4570       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4571       {
4572         if (++anArgIter >= theArgNb)
4573         {
4574           std::cout << "Syntax error: id of z layer to remove is missing\n";
4575           return 1;
4576         }
4577
4578         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4579       }
4580
4581       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4582        || aLayerId == Graphic3d_ZLayerId_Default
4583        || aLayerId == Graphic3d_ZLayerId_Top
4584        || aLayerId == Graphic3d_ZLayerId_Topmost
4585        || aLayerId == Graphic3d_ZLayerId_TopOSD
4586        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4587       {
4588         std::cout << "Syntax error: standard Z layer can not be removed\n";
4589         return 1;
4590       }
4591
4592       // move all object displayed in removing layer to default layer
4593       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4594            anObjIter.More(); anObjIter.Next())
4595       {
4596         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4597         if (aPrs.IsNull()
4598          || aPrs->ZLayer() != aLayerId)
4599         {
4600           continue;
4601         }
4602         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4603       }
4604
4605       if (!aViewer->RemoveZLayer (aLayerId))
4606       {
4607         std::cout << "Z layer can not be removed!\n";
4608       }
4609       else
4610       {
4611         theDI << aLayerId << " ";
4612       }
4613     }
4614     else if (anArg == "-get"
4615           || anArg == "get")
4616     {
4617       TColStd_SequenceOfInteger aLayers;
4618       aViewer->GetAllZLayers (aLayers);
4619       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4620       {
4621         theDI << aLayeriter.Value() << " ";
4622       }
4623
4624       theDI << "\n";
4625     }
4626     else if (anArg == "-name")
4627     {
4628       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4629       {
4630         std::cout << "Syntax error: id of Z layer is missing\n";
4631         return 1;
4632       }
4633
4634       if (++anArgIter >= theArgNb)
4635       {
4636         std::cout << "Syntax error: name is missing\n";
4637         return 1;
4638       }
4639
4640       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4641       aSettings.SetName (theArgVec[anArgIter]);
4642       aViewer->SetZLayerSettings (aLayerId, aSettings);
4643     }
4644     else if (anArg == "-origin")
4645     {
4646       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4647       {
4648         std::cout << "Syntax error: id of Z layer is missing\n";
4649         return 1;
4650       }
4651
4652       if (anArgIter + 2 >= theArgNb)
4653       {
4654         std::cout << "Syntax error: origin coordinates are missing\n";
4655         return 1;
4656       }
4657
4658       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4659       gp_XYZ anOrigin;
4660       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4661       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4662       anOrigin.SetZ (0.0);
4663       if (anArgIter + 3 < theArgNb)
4664       {
4665         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4666         anArgIter += 3;
4667       }
4668       else
4669       {
4670         anArgIter += 2;
4671       }
4672       aSettings.SetOrigin (anOrigin);
4673       aViewer->SetZLayerSettings (aLayerId, aSettings);
4674     }
4675     else if (anArg == "-settings"
4676           || anArg == "settings")
4677     {
4678       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4679       {
4680         if (++anArgIter >= theArgNb)
4681         {
4682           std::cout << "Syntax error: id of Z layer is missing\n";
4683           return 1;
4684         }
4685
4686         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4687       }
4688
4689       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4690       printZLayerInfo (theDI, aSettings);
4691     }
4692     else if (anArg == "-enable"
4693           || anArg == "enable"
4694           || anArg == "-disable"
4695           || anArg == "disable")
4696     {
4697       const Standard_Boolean toEnable = anArg == "-enable"
4698                                      || anArg == "enable";
4699       if (++anArgIter >= theArgNb)
4700       {
4701         std::cout << "Syntax error: option name is missing\n";
4702         return 1;
4703       }
4704
4705       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4706       aSubOp.LowerCase();
4707       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4708       {
4709         if (++anArgIter >= theArgNb)
4710         {
4711           std::cout << "Syntax error: id of Z layer is missing\n";
4712           return 1;
4713         }
4714
4715         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4716       }
4717
4718       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4719       if (aSubOp == "depthtest"
4720        || aSubOp == "test")
4721       {
4722         aSettings.SetEnableDepthTest (toEnable);
4723       }
4724       else if (aSubOp == "depthwrite"
4725             || aSubOp == "write")
4726       {
4727         aSettings.SetEnableDepthWrite (toEnable);
4728       }
4729       else if (aSubOp == "depthclear"
4730             || aSubOp == "clear")
4731       {
4732         aSettings.SetClearDepth (toEnable);
4733       }
4734       else if (aSubOp == "depthoffset"
4735             || aSubOp == "offset")
4736       {
4737         Graphic3d_PolygonOffset aParams;
4738         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4739         if (toEnable)
4740         {
4741           if (anArgIter + 2 >= theArgNb)
4742           {
4743             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4744             return 1;
4745           }
4746
4747           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4748           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4749         }
4750         aSettings.SetPolygonOffset (aParams);
4751       }
4752       else if (aSubOp == "positiveoffset"
4753             || aSubOp == "poffset")
4754       {
4755         if (toEnable)
4756         {
4757           aSettings.SetDepthOffsetPositive();
4758         }
4759         else
4760         {
4761           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4762         }
4763       }
4764       else if (aSubOp == "negativeoffset"
4765             || aSubOp == "noffset")
4766       {
4767         if (toEnable)
4768         {
4769           aSettings.SetDepthOffsetNegative();
4770         }
4771         else
4772         {
4773           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4774         }
4775       }
4776       else if (aSubOp == "textureenv")
4777       {
4778         aSettings.SetEnvironmentTexture (toEnable);
4779       }
4780
4781       aViewer->SetZLayerSettings (aLayerId, aSettings);
4782     }
4783     else
4784     {
4785       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4786       return 1;
4787     }
4788   }
4789
4790   return 0;
4791 }
4792
4793 // The interactive presentation of 2d layer item
4794 // for "vlayerline" command it provides a presentation of
4795 // line with user-defined linewidth, linetype and transparency.
4796 class V3d_LineItem : public AIS_InteractiveObject
4797 {
4798 public:
4799   // CASCADE RTTI
4800   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4801
4802   // constructor
4803   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4804                                Standard_Real X2, Standard_Real Y2,
4805                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4806                                Standard_Real theWidth    = 0.5,
4807                                Standard_Real theTransp   = 1.0);
4808
4809   private:
4810
4811   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4812                 const Handle(Prs3d_Presentation)& thePresentation,
4813                 const Standard_Integer theMode) Standard_OVERRIDE;
4814
4815   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4816                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4817   {}
4818
4819 private:
4820
4821   Standard_Real       myX1, myY1, myX2, myY2;
4822   Aspect_TypeOfLine   myType;
4823   Standard_Real       myWidth;
4824 };
4825
4826 // default constructor for line item
4827 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4828                            Standard_Real X2, Standard_Real Y2,
4829                            Aspect_TypeOfLine theType,
4830                            Standard_Real theWidth,
4831                            Standard_Real theTransp) :
4832   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4833   myType(theType), myWidth(theWidth)
4834 {
4835   SetTransparency (1-theTransp);
4836 }
4837
4838 // render line
4839 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4840                             const Handle(Prs3d_Presentation)& thePresentation,
4841                             const Standard_Integer /*theMode*/)
4842 {
4843   thePresentation->Clear();
4844   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4845   Standard_Integer aWidth, aHeight;
4846   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4847   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4848   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4849   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4850   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4851   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4852   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4853   aGroup->AddPrimitiveArray (aPrim);
4854 }
4855
4856 //=============================================================================
4857 //function : VLayerLine
4858 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4859 //         : linewidth, transparency coefficient
4860 //============================================================================
4861 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4862 {
4863   // get the active view
4864   Handle(V3d_View) aView = ViewerTest::CurrentView();
4865   if (aView.IsNull())
4866   {
4867     di << "Call vinit before!\n";
4868     return 1;
4869   }
4870   else if (argc < 5)
4871   {
4872     di << "Use: " << argv[0];
4873     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4874     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4875     di << "              0 - solid  \n";
4876     di << "              1 - dashed \n";
4877     di << "              2 - dot    \n";
4878     di << "              3 - dashdot\n";
4879     di << " transparency : { 0.0 - 1.0 } \n";
4880     di << "                  0.0 - transparent\n";
4881     di << "                  1.0 - visible    \n";
4882     return 1;
4883   }
4884
4885   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4886   // get the input params
4887   Standard_Real X1 = Draw::Atof(argv[1]);
4888   Standard_Real Y1 = Draw::Atof(argv[2]);
4889   Standard_Real X2 = Draw::Atof(argv[3]);
4890   Standard_Real Y2 = Draw::Atof(argv[4]);
4891
4892   Standard_Real aWidth = 0.5;
4893   Standard_Real aTransparency = 1.0;
4894
4895   // has width
4896   if (argc > 5)
4897     aWidth = Draw::Atof(argv[5]);
4898
4899   // select appropriate line type
4900   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
4901   if (argc > 6
4902   && !ViewerTest::ParseLineType (argv[6], aLineType))
4903   {
4904     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
4905     return 1;
4906   }
4907
4908   // has transparency
4909   if (argc > 7)
4910   {
4911     aTransparency = Draw::Atof(argv[7]);
4912     if (aTransparency < 0 || aTransparency > 1.0)
4913       aTransparency = 1.0;
4914   }
4915
4916   static Handle (V3d_LineItem) aLine;
4917   if (!aLine.IsNull())
4918   {
4919     aContext->Erase (aLine, Standard_False);
4920   }
4921   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4922                             aLineType, aWidth,
4923                             aTransparency);
4924
4925   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4926   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4927   aLine->SetToUpdate();
4928   aContext->Display (aLine, Standard_True);
4929
4930   return 0;
4931 }
4932
4933
4934 //==============================================================================
4935 //function : VGrid
4936 //purpose  :
4937 //==============================================================================
4938
4939 static int VGrid (Draw_Interpretor& /*theDI*/,
4940                   Standard_Integer  theArgNb,
4941                   const char**      theArgVec)
4942 {
4943   // get the active view
4944   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4945   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4946   if (aView.IsNull() || aViewer.IsNull())
4947   {
4948     std::cerr << "No active view. Please call vinit.\n";
4949     return 1;
4950   }
4951
4952   Aspect_GridType     aType = aViewer->GridType();
4953   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4954   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4955   Standard_Integer anIter = 1;
4956   for (; anIter < theArgNb; ++anIter)
4957   {
4958     const char* aValue = theArgVec[anIter];
4959     if (anUpdateTool.parseRedrawMode (aValue))
4960     {
4961       continue;
4962     }
4963     else if (*aValue == 'r')
4964     {
4965       aType = Aspect_GT_Rectangular;
4966     }
4967     else if (*aValue == 'c')
4968     {
4969       aType = Aspect_GT_Circular;
4970     }
4971     else if (*aValue == 'l')
4972     {
4973       aMode = Aspect_GDM_Lines;
4974     }
4975     else if (*aValue == 'p')
4976     {
4977       aMode = Aspect_GDM_Points;
4978     }
4979     else if (strcmp (aValue, "off" ) == 0)
4980     {
4981       aViewer->DeactivateGrid();
4982       return 0;
4983     }
4984     else
4985     {
4986       break;
4987     }
4988   }
4989
4990   Standard_Integer aTail = (theArgNb - anIter);
4991   if (aTail == 0)
4992   {
4993     aViewer->ActivateGrid (aType, aMode);
4994     return 0;
4995   }
4996   else if (aTail != 2 && aTail != 5)
4997   {
4998     std::cerr << "Incorrect arguments number! Usage:\n"
4999               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5000     return 1;
5001   }
5002
5003   Quantity_Length anOriginX, anOriginY;
5004   Quantity_PlaneAngle aRotAngle;
5005   if (aType == Aspect_GT_Rectangular)
5006   {
5007     Quantity_Length aRStepX, aRStepY;
5008     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5009
5010     anOriginX = Draw::Atof (theArgVec[anIter++]);
5011     anOriginY = Draw::Atof (theArgVec[anIter++]);
5012     if (aTail == 5)
5013     {
5014       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5015       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5016       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5017     }
5018     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5019     aViewer->ActivateGrid (aType, aMode);
5020   }
5021   else if (aType == Aspect_GT_Circular)
5022   {
5023     Quantity_Length aRadiusStep;
5024     Standard_Integer aDivisionNumber;
5025     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5026
5027     anOriginX = Draw::Atof (theArgVec[anIter++]);
5028     anOriginY = Draw::Atof (theArgVec[anIter++]);
5029     if (aTail == 5)
5030     {
5031       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5032       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5033       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5034     }
5035
5036     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5037     aViewer->ActivateGrid (aType, aMode);
5038   }
5039
5040   return 0;
5041 }
5042
5043 //==============================================================================
5044 //function : VPriviledgedPlane
5045 //purpose  :
5046 //==============================================================================
5047
5048 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5049                               Standard_Integer  theArgNb,
5050                               const char**      theArgVec)
5051 {
5052   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5053   {
5054     std::cerr << "Error: wrong number of arguments! See usage:\n";
5055     theDI.PrintHelp (theArgVec[0]);
5056     return 1;
5057   }
5058
5059   // get the active viewer
5060   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5061   if (aViewer.IsNull())
5062   {
5063     std::cerr << "Error: no active viewer. Please call vinit.\n";
5064     return 1;
5065   }
5066
5067   if (theArgNb == 1)
5068   {
5069     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5070     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5071     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5072     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5073     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5074           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5075           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5076     return 0;
5077   }
5078
5079   Standard_Integer anArgIdx = 1;
5080   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5081   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5082   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5083   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5084   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5085   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5086
5087   gp_Ax3 aPriviledgedPlane;
5088   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5089   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5090   if (theArgNb > 7)
5091   {
5092     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5093     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5094     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5095     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5096     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5097   }
5098   else
5099   {
5100     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5101   }
5102
5103   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5104
5105   return 0;
5106 }
5107
5108 //==============================================================================
5109 //function : VConvert
5110 //purpose  :
5111 //==============================================================================
5112
5113 static int VConvert (Draw_Interpretor& theDI,
5114                      Standard_Integer  theArgNb,
5115                      const char**      theArgVec)
5116 {
5117   // get the active view
5118   Handle(V3d_View) aView = ViewerTest::CurrentView();
5119   if (aView.IsNull())
5120   {
5121     std::cerr << "Error: no active view. Please call vinit.\n";
5122     return 1;
5123   }
5124
5125   enum { Model, Ray, View, Window, Grid } aMode = Model;
5126
5127   // access coordinate arguments
5128   TColStd_SequenceOfReal aCoord;
5129   Standard_Integer anArgIdx = 1;
5130   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5131   {
5132     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5133     if (!anArg.IsRealValue())
5134     {
5135       break;
5136     }
5137     aCoord.Append (anArg.RealValue());
5138   }
5139
5140   // non-numeric argument too early
5141   if (aCoord.IsEmpty())
5142   {
5143     std::cerr << "Error: wrong number of arguments! See usage:\n";
5144     theDI.PrintHelp (theArgVec[0]);
5145     return 1;
5146   }
5147
5148   // collect all other arguments and options
5149   for (; anArgIdx < theArgNb; ++anArgIdx)
5150   {
5151     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5152     anArg.LowerCase();
5153     if      (anArg == "window") aMode = Window;
5154     else if (anArg == "view")   aMode = View;
5155     else if (anArg == "grid")   aMode = Grid;
5156     else if (anArg == "ray")    aMode = Ray;
5157     else
5158     {
5159       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5160       theDI.PrintHelp (theArgVec[0]);
5161       return 1;
5162     }
5163   }
5164
5165   // complete input checks
5166   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5167       (aCoord.Length() == 2 && theArgNb > 4) ||
5168       (aCoord.Length() == 3 && theArgNb > 5))
5169   {
5170     std::cerr << "Error: wrong number of arguments! See usage:\n";
5171     theDI.PrintHelp (theArgVec[0]);
5172     return 1;
5173   }
5174
5175   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5176   Standard_Integer aXYp[2] = {0, 0};
5177
5178   // convert one-dimensional coordinate
5179   if (aCoord.Length() == 1)
5180   {
5181     switch (aMode)
5182     {
5183       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
5184       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
5185       default:
5186         std::cerr << "Error: wrong arguments! See usage:\n";
5187         theDI.PrintHelp (theArgVec[0]);
5188         return 1;
5189     }
5190   }
5191
5192   // convert 2D coordinates from projection or view reference space
5193   if (aCoord.Length() == 2)
5194   {
5195     switch (aMode)
5196     {
5197       case Model :
5198         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5199         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5200         return 0;
5201
5202       case View :
5203         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5204         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5205         return 0;
5206
5207       case Window :
5208         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5209         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5210         return 0;
5211
5212       case Grid :
5213         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5214         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5215         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5216         return 0;
5217
5218       case Ray :
5219         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5220                                 (Standard_Integer) aCoord (2),
5221                                 aXYZ[0], aXYZ[1], aXYZ[2],
5222                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5223         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5224         return 0;
5225
5226       default:
5227         std::cerr << "Error: wrong arguments! See usage:\n";
5228         theDI.PrintHelp (theArgVec[0]);
5229         return 1;
5230     }
5231   }
5232
5233   // convert 3D coordinates from view reference space
5234   else if (aCoord.Length() == 3)
5235   {
5236     switch (aMode)
5237     {
5238       case Window :
5239         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5240         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5241         return 0;
5242
5243       case Grid :
5244         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5245         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5246         return 0;
5247
5248       default:
5249         std::cerr << "Error: wrong arguments! See usage:\n";
5250         theDI.PrintHelp (theArgVec[0]);
5251         return 1;
5252     }
5253   }
5254
5255   return 0;
5256 }
5257
5258 //==============================================================================
5259 //function : VFps
5260 //purpose  :
5261 //==============================================================================
5262
5263 static int VFps (Draw_Interpretor& theDI,
5264                  Standard_Integer  theArgNb,
5265                  const char**      theArgVec)
5266 {
5267   // get the active view
5268   Handle(V3d_View) aView = ViewerTest::CurrentView();
5269   if (aView.IsNull())
5270   {
5271     std::cerr << "No active view. Please call vinit.\n";
5272     return 1;
5273   }
5274
5275   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5276   if (aFramesNb <= 0)
5277   {
5278     std::cerr << "Incorrect arguments!\n";
5279     return 1;
5280   }
5281
5282   // the time is meaningless for first call
5283   // due to async OpenGl rendering
5284   aView->Redraw();
5285
5286   // redraw view in loop to estimate average values
5287   OSD_Timer aTimer;
5288   aTimer.Start();
5289   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5290   {
5291     aView->Redraw();
5292   }
5293   aTimer.Stop();
5294   Standard_Real aCpu;
5295   const Standard_Real aTime = aTimer.ElapsedTime();
5296   aTimer.OSD_Chronometer::Show (aCpu);
5297
5298   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5299   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5300
5301   // return statistics
5302   theDI << "FPS: " << aFpsAver << "\n"
5303         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5304
5305   // compute additional statistics in ray-tracing mode
5306   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5307
5308   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5309   {
5310     Standard_Integer aSizeX;
5311     Standard_Integer aSizeY;
5312
5313     aView->Window()->Size (aSizeX, aSizeY);
5314
5315     // 1 shadow ray and 1 secondary ray pew each bounce
5316     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5317
5318     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5319   }
5320
5321   return 0;
5322 }
5323
5324 //==============================================================================
5325 //function : VGlDebug
5326 //purpose  :
5327 //==============================================================================
5328
5329 static int VGlDebug (Draw_Interpretor& theDI,
5330                      Standard_Integer  theArgNb,
5331                      const char**      theArgVec)
5332 {
5333   Handle(OpenGl_GraphicDriver) aDriver;
5334   Handle(V3d_View) aView = ViewerTest::CurrentView();
5335   if (!aView.IsNull())
5336   {
5337     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5338   }
5339   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5340   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5341
5342   if (theArgNb < 2)
5343   {
5344     TCollection_AsciiString aDebActive, aSyncActive;
5345     if (aCaps == NULL)
5346     {
5347       aCaps = aDefCaps;
5348     }
5349     else
5350     {
5351       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5352                                                                   "GL_ARB_debug_output");
5353       aDebActive = isActive ? " (active)" : " (inactive)";
5354       if (isActive)
5355       {
5356         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5357         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5358       }
5359     }
5360
5361     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5362           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5363           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5364           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5365     return 0;
5366   }
5367
5368   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5369   {
5370     Standard_CString        anArg     = theArgVec[anArgIter];
5371     TCollection_AsciiString anArgCase (anArg);
5372     anArgCase.LowerCase();
5373     Standard_Boolean toEnableDebug = Standard_True;
5374     if (anArgCase == "-glsl"
5375      || anArgCase == "-glslwarn"
5376      || anArgCase == "-glslwarns"
5377      || anArgCase == "-glslwarnings")
5378     {
5379       Standard_Boolean toShowWarns = Standard_True;
5380       if (++anArgIter < theArgNb
5381       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5382       {
5383         --anArgIter;
5384       }
5385       aDefCaps->glslWarnings = toShowWarns;
5386       if (aCaps != NULL)
5387       {
5388         aCaps->glslWarnings = toShowWarns;
5389       }
5390     }
5391     else if (anArgCase == "-extra"
5392           || anArgCase == "-extramsg"
5393           || anArgCase == "-extramessages")
5394     {
5395       Standard_Boolean toShow = Standard_True;
5396       if (++anArgIter < theArgNb
5397       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5398       {
5399         --anArgIter;
5400       }
5401       aDefCaps->suppressExtraMsg = !toShow;
5402       if (aCaps != NULL)
5403       {
5404         aCaps->suppressExtraMsg = !toShow;
5405       }
5406     }
5407     else if (anArgCase == "-noextra"
5408           || anArgCase == "-noextramsg"
5409           || anArgCase == "-noextramessages")
5410     {
5411       Standard_Boolean toSuppress = Standard_True;
5412       if (++anArgIter < theArgNb
5413       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5414       {
5415         --anArgIter;
5416       }
5417       aDefCaps->suppressExtraMsg = toSuppress;
5418       if (aCaps != NULL)
5419       {
5420         aCaps->suppressExtraMsg = toSuppress;
5421       }
5422     }
5423     else if (anArgCase == "-sync")
5424     {
5425       Standard_Boolean toSync = Standard_True;
5426       if (++anArgIter < theArgNb
5427       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5428       {
5429         --anArgIter;
5430       }
5431       aDefCaps->contextSyncDebug = toSync;
5432       if (toSync)
5433       {
5434         aDefCaps->contextDebug = Standard_True;
5435       }
5436     }
5437     else if (anArgCase == "-debug")
5438     {
5439       if (++anArgIter < theArgNb
5440       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5441       {
5442         --anArgIter;
5443       }
5444       aDefCaps->contextDebug = toEnableDebug;
5445     }
5446     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5447           && (anArgIter + 1 == theArgNb))
5448     {
5449       // simple alias to turn on almost everything
5450       aDefCaps->contextDebug     = toEnableDebug;
5451       aDefCaps->contextSyncDebug = toEnableDebug;
5452       aDefCaps->glslWarnings     = toEnableDebug;
5453     }
5454     else
5455     {
5456       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5457       return 1;
5458     }
5459   }
5460
5461   return 0;
5462 }
5463
5464 //==============================================================================
5465 //function : VVbo
5466 //purpose  :
5467 //==============================================================================
5468
5469 static int VVbo (Draw_Interpretor& theDI,
5470                  Standard_Integer  theArgNb,
5471                  const char**      theArgVec)
5472 {
5473   const Standard_Boolean toSet    = (theArgNb > 1);
5474   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5475   if (toSet)
5476   {
5477     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5478   }
5479
5480   // get the context
5481   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5482   if (aContextAIS.IsNull())
5483   {
5484     if (!toSet)
5485     {
5486       std::cerr << "No active view!\n";
5487     }
5488     return 1;
5489   }
5490   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5491   if (!aDriver.IsNull())
5492   {
5493     if (!toSet)
5494     {
5495       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5496     }
5497     else
5498     {
5499       aDriver->ChangeOptions().vboDisable = toUseVbo;
5500     }
5501   }
5502
5503   return 0;
5504 }
5505
5506 //==============================================================================
5507 //function : VCaps
5508 //purpose  :
5509 //==============================================================================
5510
5511 static int VCaps (Draw_Interpretor& theDI,
5512                   Standard_Integer  theArgNb,
5513                   const char**      theArgVec)
5514 {
5515   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5516   Handle(OpenGl_GraphicDriver)   aDriver;
5517   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5518   if (!aContext.IsNull())
5519   {
5520     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5521     aCaps   = &aDriver->ChangeOptions();
5522   }
5523
5524   if (theArgNb < 2)
5525   {
5526     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5527     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5528     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5529     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5530     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5531     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5532     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5533     return 0;
5534   }
5535
5536   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5537   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5538   {
5539     Standard_CString        anArg     = theArgVec[anArgIter];
5540     TCollection_AsciiString anArgCase (anArg);
5541     anArgCase.LowerCase();
5542     if (anUpdateTool.parseRedrawMode (anArg))
5543     {
5544       continue;
5545     }
5546     else if (anArgCase == "-vsync"
5547           || anArgCase == "-swapinterval")
5548     {
5549       Standard_Boolean toEnable = Standard_True;
5550       if (++anArgIter < theArgNb
5551       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5552       {
5553         --anArgIter;
5554       }
5555       aCaps->swapInterval = toEnable;
5556     }
5557     else if (anArgCase == "-ffp")
5558     {
5559       Standard_Boolean toEnable = Standard_True;
5560       if (++anArgIter < theArgNb
5561       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5562       {
5563         --anArgIter;
5564       }
5565       aCaps->ffpEnable = toEnable;
5566     }
5567     else if (anArgCase == "-vbo")
5568     {
5569       Standard_Boolean toEnable = Standard_True;
5570       if (++anArgIter < theArgNb
5571       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5572       {
5573         --anArgIter;
5574       }
5575       aCaps->vboDisable = !toEnable;
5576     }
5577     else if (anArgCase == "-sprite"
5578           || anArgCase == "-sprites")
5579     {
5580       Standard_Boolean toEnable = Standard_True;
5581       if (++anArgIter < theArgNb
5582       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5583       {
5584         --anArgIter;
5585       }
5586       aCaps->pntSpritesDisable = !toEnable;
5587     }
5588     else if (anArgCase == "-softmode")
5589     {
5590       Standard_Boolean toEnable = Standard_True;
5591       if (++anArgIter < theArgNb
5592       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5593       {
5594         --anArgIter;
5595       }
5596       aCaps->contextNoAccel = toEnable;
5597     }
5598     else if (anArgCase == "-accel"
5599           || anArgCase == "-acceleration")
5600     {
5601       Standard_Boolean toEnable = Standard_True;
5602       if (++anArgIter < theArgNb
5603       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5604       {
5605         --anArgIter;
5606       }
5607       aCaps->contextNoAccel = !toEnable;
5608     }
5609     else if (anArgCase == "-compat"
5610           || anArgCase == "-compatprofile"
5611           || anArgCase == "-compatible"
5612           || anArgCase == "-compatibleprofile")
5613     {
5614       Standard_Boolean toEnable = Standard_True;
5615       if (++anArgIter < theArgNb
5616       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5617       {
5618         --anArgIter;
5619       }
5620       aCaps->contextCompatible = toEnable;
5621       if (!aCaps->contextCompatible)
5622       {
5623         aCaps->ffpEnable = Standard_False;
5624       }
5625     }
5626     else if (anArgCase == "-core"
5627           || anArgCase == "-coreprofile")
5628     {
5629       Standard_Boolean toEnable = Standard_True;
5630       if (++anArgIter < theArgNb
5631       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5632       {
5633         --anArgIter;
5634       }
5635       aCaps->contextCompatible = !toEnable;
5636       if (!aCaps->contextCompatible)
5637       {
5638         aCaps->ffpEnable = Standard_False;
5639       }
5640     }
5641     else if (anArgCase == "-stereo"
5642           || anArgCase == "-quadbuffer")
5643     {
5644       Standard_Boolean toEnable = Standard_True;
5645       if (++anArgIter < theArgNb
5646       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5647       {
5648         --anArgIter;
5649       }
5650       aCaps->contextStereo = toEnable;
5651     }
5652     else
5653     {
5654       std::cout << "Error: unknown argument '" << anArg << "'\n";
5655       return 1;
5656     }
5657   }
5658   if (aCaps != &ViewerTest_myDefaultCaps)
5659   {
5660     ViewerTest_myDefaultCaps = *aCaps;
5661   }
5662   return 0;
5663 }
5664
5665 //==============================================================================
5666 //function : VMemGpu
5667 //purpose  :
5668 //==============================================================================
5669
5670 static int VMemGpu (Draw_Interpretor& theDI,
5671                     Standard_Integer  theArgNb,
5672                     const char**      theArgVec)
5673 {
5674   // get the context
5675   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5676   if (aContextAIS.IsNull())
5677   {
5678     std::cerr << "No active view. Please call vinit.\n";
5679     return 1;
5680   }
5681
5682   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5683   if (aDriver.IsNull())
5684   {
5685     std::cerr << "Graphic driver not available.\n";
5686     return 1;
5687   }
5688
5689   Standard_Size aFreeBytes = 0;
5690   TCollection_AsciiString anInfo;
5691   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5692   {
5693     std::cerr << "Information not available.\n";
5694     return 1;
5695   }
5696
5697   if (theArgNb > 1 && *theArgVec[1] == 'f')
5698   {
5699     theDI << Standard_Real (aFreeBytes);
5700   }
5701   else
5702   {
5703     theDI << anInfo;
5704   }
5705
5706   return 0;
5707 }
5708
5709 // ==============================================================================
5710 // function : VReadPixel
5711 // purpose  :
5712 // ==============================================================================
5713 static int VReadPixel (Draw_Interpretor& theDI,
5714                        Standard_Integer  theArgNb,
5715                        const char**      theArgVec)
5716 {
5717   // get the active view
5718   Handle(V3d_View) aView = ViewerTest::CurrentView();
5719   if (aView.IsNull())
5720   {
5721     std::cerr << "No active view. Please call vinit.\n";
5722     return 1;
5723   }
5724   else if (theArgNb < 3)
5725   {
5726     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5727     return 1;
5728   }
5729
5730   Image_PixMap::ImgFormat aFormat     = Image_PixMap::ImgRGBA;
5731   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5732
5733   Standard_Integer aWidth, aHeight;
5734   aView->Window()->Size (aWidth, aHeight);
5735   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5736   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5737   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5738   {
5739     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5740     return 1;
5741   }
5742
5743   Standard_Boolean toShowName = Standard_False;
5744   Standard_Boolean toShowHls  = Standard_False;
5745   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5746   {
5747     const char* aParam = theArgVec[anIter];
5748     if ( strcasecmp( aParam, "rgb" ) == 0 )
5749     {
5750       aFormat     = Image_PixMap::ImgRGB;
5751       aBufferType = Graphic3d_BT_RGB;
5752     }
5753     else if ( strcasecmp( aParam, "hls" ) == 0 )
5754     {
5755       aFormat     = Image_PixMap::ImgRGB;
5756       aBufferType = Graphic3d_BT_RGB;
5757       toShowHls   = Standard_True;
5758     }
5759     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5760     {
5761       aFormat     = Image_PixMap::ImgRGBF;
5762       aBufferType = Graphic3d_BT_RGB;
5763     }
5764     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5765     {
5766       aFormat     = Image_PixMap::ImgRGBA;
5767       aBufferType = Graphic3d_BT_RGBA;
5768     }
5769     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5770     {
5771       aFormat     = Image_PixMap::ImgRGBAF;
5772       aBufferType = Graphic3d_BT_RGBA;
5773     }
5774     else if ( strcasecmp( aParam, "depth" ) == 0 )
5775     {
5776       aFormat     = Image_PixMap::ImgGrayF;
5777       aBufferType = Graphic3d_BT_Depth;
5778     }
5779     else if ( strcasecmp( aParam, "name" ) == 0 )
5780     {
5781       toShowName = Standard_True;
5782     }
5783   }
5784
5785   Image_PixMap anImage;
5786   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5787   {
5788     std::cerr << "Image allocation failed\n";
5789     return 1;
5790   }
5791   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5792   {
5793     std::cerr << "Image dump failed\n";
5794     return 1;
5795   }
5796
5797   Quantity_Parameter anAlpha;
5798   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5799   if (toShowName)
5800   {
5801     if (aBufferType == Graphic3d_BT_RGBA)
5802     {
5803       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5804     }
5805     else
5806     {
5807       theDI << Quantity_Color::StringName (aColor.Name());
5808     }
5809   }
5810   else
5811   {
5812     switch (aBufferType)
5813     {
5814       default:
5815       case Graphic3d_BT_RGB:
5816       {
5817         if (toShowHls)
5818         {
5819           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5820         }
5821         else
5822         {
5823           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5824         }
5825         break;
5826       }
5827       case Graphic3d_BT_RGBA:
5828       {
5829         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5830         break;
5831       }
5832       case Graphic3d_BT_Depth:
5833       {
5834         theDI << aColor.Red();
5835         break;
5836       }
5837     }
5838   }
5839
5840   return 0;
5841 }
5842
5843 //==============================================================================
5844 //function : VDiffImage
5845 //purpose  : The draw-command compares two images.
5846 //==============================================================================
5847
5848 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5849 {
5850   if (theArgNb < 6)
5851   {
5852     theDI << "Not enough arguments.\n";
5853     return 1;
5854   }
5855
5856   // image file names
5857   const char* anImgPathRef = theArgVec[1];
5858   const char* anImgPathNew = theArgVec[2];
5859
5860   // get string tolerance and check its validity
5861   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5862   if (aTolColor < 0.0)
5863     aTolColor = 0.0;
5864   if (aTolColor > 1.0)
5865     aTolColor = 1.0;
5866
5867   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5868   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5869
5870   // image file of difference
5871   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5872
5873   // compare the images
5874   Image_Diff aComparer;
5875   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5876   {
5877     return 1;
5878   }
5879
5880   aComparer.SetColorTolerance (aTolColor);
5881   aComparer.SetBorderFilterOn (isBorderFilterOn);
5882   Standard_Integer aDiffColorsNb = aComparer.Compare();
5883   theDI << aDiffColorsNb << "\n";
5884
5885   // save image of difference
5886   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5887   {
5888     aComparer.SaveDiffImage (aDiffImagePath);
5889   }
5890
5891   return 0;
5892 }
5893
5894 //=======================================================================
5895 //function : VSelect
5896 //purpose  : Emulates different types of selection by mouse:
5897 //           1) single click selection
5898 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5899 //           3) selection with polygon having corners at
5900 //           pixel positions (x1,y1),...,(xn,yn)
5901 //           4) any of these selections with shift button pressed
5902 //=======================================================================
5903 static Standard_Integer VSelect (Draw_Interpretor& di,
5904                                  Standard_Integer argc,
5905                                  const char ** argv)
5906 {
5907   if(argc < 3)
5908   {
5909     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5910     return 1;
5911   }
5912
5913   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5914   if(myAIScontext.IsNull())
5915   {
5916     di << "use 'vinit' command before " << argv[0] << "\n";
5917     return 1;
5918   }
5919
5920   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5921   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5922   TCollection_AsciiString anArg;
5923   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5924   anArg.LowerCase();
5925   if (anArg == "-allowoverlap")
5926   {
5927     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5928       : argc == 7;
5929     if (!isValidated)
5930     {
5931       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5932       return 1;
5933     }
5934
5935     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5936     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5937     aCoordsNb -= 2;
5938   }
5939
5940   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5941   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5942   if(aCoordsNb == 2)
5943   {
5944     if(isShiftSelection)
5945       aCurrentEventManager->ShiftSelect();
5946     else
5947       aCurrentEventManager->Select();
5948   }
5949   else if(aCoordsNb == 4)
5950   {
5951     if(isShiftSelection)
5952       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5953     else
5954       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5955   }
5956   else
5957   {
5958     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5959
5960     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5961       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5962
5963     if(isShiftSelection)
5964       aCurrentEventManager->ShiftSelect(aPolyline);
5965     else
5966       aCurrentEventManager->Select(aPolyline);
5967   }
5968   return 0;
5969 }
5970
5971 //=======================================================================
5972 //function : VMoveTo
5973 //purpose  : Emulates cursor movement to defined pixel position
5974 //=======================================================================
5975 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5976                                 Standard_Integer argc,
5977                                 const char ** argv)
5978 {
5979   if(argc != 3)
5980   {
5981     di << "Usage : " << argv[0] << " x y\n";
5982     return 1;
5983   }
5984
5985   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5986   if(aContext.IsNull())
5987   {
5988     di << "use 'vinit' command before " << argv[0] << "\n";
5989     return 1;
5990   }
5991   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
5992   return 0;
5993 }
5994
5995 namespace
5996 {
5997   //! Global map storing all animations registered in ViewerTest.
5998   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
5999
6000   //! The animation calling the Draw Harness command.
6001   class ViewerTest_AnimationProc : public AIS_Animation
6002   {
6003   public:
6004
6005     //! Main constructor.
6006     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6007                               Draw_Interpretor* theDI,
6008                               const TCollection_AsciiString& theCommand)
6009     : AIS_Animation (theAnimationName),
6010       myDrawInter(theDI),
6011       myCommand  (theCommand)
6012     {
6013       //
6014     }
6015
6016   protected:
6017
6018     //! Evaluate the command.
6019     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6020     {
6021       TCollection_AsciiString aCmd = myCommand;
6022       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6023       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6024       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6025       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6026       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6027       myDrawInter->Eval (aCmd.ToCString());
6028     }
6029
6030     //! Find the keyword in the command and replace it with value.
6031     //! @return the position of the keyword to pass value
6032     void replace (TCollection_AsciiString&       theCmd,
6033                   const TCollection_AsciiString& theKey,
6034                   const TCollection_AsciiString& theVal)
6035     {
6036       TCollection_AsciiString aCmd (theCmd);
6037       aCmd.LowerCase();
6038       const Standard_Integer aPos = aCmd.Search (theKey);
6039       if (aPos == -1)
6040       {
6041         return;
6042       }
6043
6044       TCollection_AsciiString aPart1, aPart2;
6045       Standard_Integer aPart1To = aPos - 1;
6046       if (aPart1To >= 1
6047        && aPart1To <= theCmd.Length())
6048       {
6049         aPart1 = theCmd.SubString (1, aPart1To);
6050       }
6051
6052       Standard_Integer aPart2From = aPos + theKey.Length();
6053       if (aPart2From >= 1
6054        && aPart2From <= theCmd.Length())
6055       {
6056         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6057       }
6058
6059       theCmd = aPart1 + theVal + aPart2;
6060     }
6061
6062   protected:
6063
6064     Draw_Interpretor*       myDrawInter;
6065     TCollection_AsciiString myCommand;
6066
6067   };
6068
6069   //! Replace the animation with the new one.
6070   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6071                                 Handle(AIS_Animation)&       theAnimation,
6072                                 const Handle(AIS_Animation)& theAnimationNew)
6073   {
6074     theAnimationNew->CopyFrom (theAnimation);
6075     if (!theParentAnimation.IsNull())
6076     {
6077       theParentAnimation->Replace (theAnimation, theAnimationNew);
6078     }
6079     else
6080     {
6081       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6082       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6083     }
6084     theAnimation = theAnimationNew;
6085   }
6086
6087   //! Parse the point.
6088   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6089   {
6090     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6091     if (!anXYZ[0].IsRealValue()
6092      || !anXYZ[1].IsRealValue()
6093      || !anXYZ[2].IsRealValue())
6094     {
6095       return Standard_False;
6096     }
6097
6098     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6099     return Standard_True;
6100   }
6101
6102   //! Parse the quaternion.
6103   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6104   {
6105     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6106     if (!anXYZW[0].IsRealValue()
6107      || !anXYZW[1].IsRealValue()
6108      || !anXYZW[2].IsRealValue()
6109      || !anXYZW[3].IsRealValue())
6110     {
6111       return Standard_False;
6112     }
6113
6114     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6115     return Standard_True;
6116   }
6117
6118 }
6119
6120 //=================================================================================================
6121 //function : VViewParams
6122 //purpose  : Gets or sets AIS View characteristics
6123 //=================================================================================================
6124 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6125 {
6126   Handle(V3d_View) aView = ViewerTest::CurrentView();
6127   if (aView.IsNull())
6128   {
6129     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6130     return 1;
6131   }
6132
6133   Standard_Boolean toSetProj     = Standard_False;
6134   Standard_Boolean toSetUp       = Standard_False;
6135   Standard_Boolean toSetAt       = Standard_False;
6136   Standard_Boolean toSetEye      = Standard_False;
6137   Standard_Boolean toSetScale    = Standard_False;
6138   Standard_Boolean toSetSize     = Standard_False;
6139   Standard_Boolean toSetCenter2d = Standard_False;
6140   Quantity_Factor  aViewScale = aView->Scale();
6141   Quantity_Length  aViewSize  = 1.0;
6142   Graphic3d_Vec2i  aCenter2d;
6143   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6144   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6145   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6146   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6147   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6148   if (theArgsNb == 1)
6149   {
6150     // print all of the available view parameters
6151     char aText[4096];
6152     Sprintf (aText,
6153              "Scale: %g\n"
6154              "Proj:  %12g %12g %12g\n"
6155              "Up:    %12g %12g %12g\n"
6156              "At:    %12g %12g %12g\n"
6157              "Eye:   %12g %12g %12g\n",
6158               aViewScale,
6159               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6160               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6161               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6162               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6163     theDi << aText;
6164     return 0;
6165   }
6166
6167   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6168   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6169   {
6170     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6171     anArg.LowerCase();
6172     if (anUpdateTool.parseRedrawMode (anArg))
6173     {
6174       continue;
6175     }
6176     else if (anArg == "-cmd"
6177           || anArg == "-command"
6178           || anArg == "-args")
6179     {
6180       char aText[4096];
6181       Sprintf (aText,
6182                "-scale %g "
6183                "-proj %g %g %g "
6184                "-up %g %g %g "
6185                "-at %g %g %g\n",
6186                 aViewScale,
6187                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6188                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6189                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6190       theDi << aText;
6191     }
6192     else if (anArg == "-scale"
6193           || anArg == "-size")
6194     {
6195       if (anArgIter + 1 < theArgsNb
6196        && *theArgVec[anArgIter + 1] != '-')
6197       {
6198         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6199         if (aValueArg.IsRealValue())
6200         {
6201           ++anArgIter;
6202           if (anArg == "-scale")
6203           {
6204             toSetScale = Standard_True;
6205             aViewScale = aValueArg.RealValue();
6206           }
6207           else if (anArg == "-size")
6208           {
6209             toSetSize = Standard_True;
6210             aViewSize = aValueArg.RealValue();
6211           }
6212           continue;
6213         }
6214       }
6215       if (anArg == "-scale")
6216       {
6217         theDi << "Scale: " << aView->Scale() << "\n";
6218       }
6219       else if (anArg == "-size")
6220       {
6221         Graphic3d_Vec2d aSizeXY;
6222         aView->Size (aSizeXY.x(), aSizeXY.y());
6223         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6224       }
6225     }
6226     else if (anArg == "-eye"
6227           || anArg == "-at"
6228           || anArg == "-up"
6229           || anArg == "-proj")
6230     {
6231       if (anArgIter + 3 < theArgsNb)
6232       {
6233         gp_XYZ anXYZ;
6234         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6235         {
6236           anArgIter += 3;
6237           if (anArg == "-eye")
6238           {
6239             toSetEye = Standard_True;
6240             aViewEye = anXYZ;
6241           }
6242           else if (anArg == "-at")
6243           {
6244             toSetAt = Standard_True;
6245             aViewAt = anXYZ;
6246           }
6247           else if (anArg == "-up")
6248           {
6249             toSetUp = Standard_True;
6250             aViewUp = anXYZ;
6251           }
6252           else if (anArg == "-proj")
6253           {
6254             toSetProj = Standard_True;
6255             aViewProj = anXYZ;
6256           }
6257           continue;
6258         }
6259       }
6260
6261       if (anArg == "-eye")
6262       {
6263         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6264       }
6265       else if (anArg == "-at")
6266       {
6267         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6268       }
6269       else if (anArg == "-up")
6270       {
6271         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6272       }
6273       else if (anArg == "-proj")
6274       {
6275         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6276       }
6277     }
6278     else if (anArg == "-center")
6279     {
6280       if (anArgIter + 2 < theArgsNb)
6281       {
6282         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6283         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6284         if (anX.IsIntegerValue()
6285          && anY.IsIntegerValue())
6286         {
6287           toSetCenter2d = Standard_True;
6288           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6289         }
6290       }
6291     }
6292     else
6293     {
6294       std::cout << "Syntax error at '" << anArg << "'\n";
6295       return 1;
6296     }
6297   }
6298
6299   // change view parameters in proper order
6300   if (toSetScale)
6301   {
6302     aView->SetScale (aViewScale);
6303   }
6304   if (toSetSize)
6305   {
6306     aView->SetSize (aViewSize);
6307   }
6308   if (toSetEye)
6309   {
6310     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6311   }
6312   if (toSetAt)
6313   {
6314     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6315   }
6316   if (toSetProj)
6317   {
6318     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6319   }
6320   if (toSetUp)
6321   {
6322     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6323   }
6324   if (toSetCenter2d)
6325   {
6326     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6327   }
6328
6329   return 0;
6330 }
6331
6332 //==============================================================================
6333 //function : VAnimation
6334 //purpose  :
6335 //==============================================================================
6336 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6337                                     Standard_Integer  theArgNb,
6338                                     const char**      theArgVec)
6339 {
6340   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6341   if (theArgNb < 2)
6342   {
6343     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6344          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6345     {
6346       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6347     }
6348     return 0;
6349   }
6350   if (aCtx.IsNull())
6351   {
6352     std::cout << "Error: no active view\n";
6353     return 1;
6354   }
6355
6356   Standard_Integer anArgIter = 1;
6357   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6358   if (aNameArg.IsEmpty())
6359   {
6360     std::cout << "Syntax error: animation name is not defined.\n";
6361     return 1;
6362   }
6363
6364   TCollection_AsciiString aNameArgLower = aNameArg;
6365   aNameArgLower.LowerCase();
6366   if (aNameArgLower == "-reset"
6367    || aNameArgLower == "-clear")
6368   {
6369     ViewerTest_AnimationTimelineMap.Clear();
6370     return 0;
6371   }
6372   else if (aNameArg.Value (1) == '-')
6373   {
6374     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6375     return 1;
6376   }
6377
6378   const char* aNameSplitter = "/";
6379   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6380   if (aSplitPos == -1)
6381   {
6382     aNameSplitter = ".";
6383     aSplitPos = aNameArg.Search (aNameSplitter);
6384   }
6385
6386   // find existing or create a new animation by specified name within syntax "parent.child".
6387   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6388   for (; !aNameArg.IsEmpty();)
6389   {
6390     TCollection_AsciiString aNameParent;
6391     if (aSplitPos != -1)
6392     {
6393       if (aSplitPos == aNameArg.Length())
6394       {
6395         std::cout << "Syntax error: animation name is not defined.\n";
6396         return 1;
6397       }
6398
6399       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6400       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6401
6402       aSplitPos = aNameArg.Search (aNameSplitter);
6403     }
6404     else
6405     {
6406       aNameParent = aNameArg;
6407       aNameArg.Clear();
6408     }
6409
6410     if (anAnimation.IsNull())
6411     {
6412       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6413       {
6414         anAnimation = new AIS_Animation (aNameParent);
6415         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6416       }
6417       aRootAnimation = anAnimation;
6418     }
6419     else
6420     {
6421       aParentAnimation = anAnimation;
6422       anAnimation = aParentAnimation->Find (aNameParent);
6423       if (anAnimation.IsNull())
6424       {
6425         anAnimation = new AIS_Animation (aNameParent);
6426         aParentAnimation->Add (anAnimation);
6427       }
6428     }
6429   }
6430
6431   if (anArgIter >= theArgNb)
6432   {
6433     // just print the list of children
6434     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
6435     {
6436       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
6437     }
6438     return 0;
6439   }
6440
6441   // animation parameters
6442   Standard_Boolean toPlay = Standard_False;
6443   Standard_Real aPlaySpeed     = 1.0;
6444   Standard_Real aPlayStartTime = anAnimation->StartPts();
6445   Standard_Real aPlayDuration  = anAnimation->Duration();
6446   Standard_Integer aFpsNum     = 0;
6447   Standard_Integer aFpsDen     = 1;
6448   Standard_Boolean isFreeCamera = Standard_False;
6449   Standard_Boolean isLockLoop   = Standard_False;
6450   Handle(V3d_View) aView = ViewerTest::CurrentView();
6451   for (; anArgIter < theArgNb; ++anArgIter)
6452   {
6453     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6454     anArg.LowerCase();
6455     // general options
6456     if (anArg == "-reset"
6457      || anArg == "-clear")
6458     {
6459       anAnimation->Clear();
6460     }
6461     else if (anArg == "-remove"
6462           || anArg == "-del"
6463           || anArg == "-delete")
6464     {
6465       if (!aParentAnimation.IsNull())
6466       {
6467         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
6468       }
6469       else
6470       {
6471         aParentAnimation->Remove (anAnimation);
6472       }
6473     }
6474     // playback options
6475     else if (anArg == "-play")
6476     {
6477       toPlay = Standard_True;
6478       if (++anArgIter < theArgNb)
6479       {
6480         if (*theArgVec[anArgIter] == '-')
6481         {
6482           --anArgIter;
6483           continue;
6484         }
6485         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
6486
6487         if (++anArgIter < theArgNb)
6488         {
6489           if (*theArgVec[anArgIter] == '-')
6490           {
6491             --anArgIter;
6492             continue;
6493           }
6494           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6495         }
6496       }
6497     }
6498     else if (anArg == "-resume")
6499     {
6500       toPlay = Standard_True;
6501       aPlayStartTime = anAnimation->ElapsedTime();
6502       if (++anArgIter < theArgNb)
6503       {
6504         if (*theArgVec[anArgIter] == '-')
6505         {
6506           --anArgIter;
6507           continue;
6508         }
6509
6510         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6511       }
6512     }
6513     else if (anArg == "-playspeed"
6514           || anArg == "-speed")
6515     {
6516       if (++anArgIter >= theArgNb)
6517       {
6518         std::cout << "Syntax error at " << anArg << ".\n";
6519         return 1;
6520       }
6521       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
6522     }
6523     else if (anArg == "-lock"
6524           || anArg == "-lockloop"
6525           || anArg == "-playlockloop")
6526     {
6527       isLockLoop = Standard_True;
6528     }
6529     else if (anArg == "-freecamera"
6530           || anArg == "-playfreecamera"
6531           || anArg == "-freelook")
6532     {
6533       isFreeCamera = Standard_True;
6534     }
6535     else if (anArg == "-fps")
6536     {
6537       if (++anArgIter >= theArgNb)
6538       {
6539         std::cout << "Syntax error at " << anArg << ".\n";
6540         return 1;
6541       }
6542
6543       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
6544       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
6545       if (aSplitIndex == 0)
6546       {
6547         aFpsNum = aFpsArg.IntegerValue();
6548       }
6549       else
6550       {
6551         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
6552         aFpsArg.Split (aFpsArg.Length() - 1);
6553         const TCollection_AsciiString aNumStr = aFpsArg;
6554         aFpsNum = aNumStr.IntegerValue();
6555         aFpsDen = aDenStr.IntegerValue();
6556         if (aFpsDen < 1)
6557         {
6558           std::cout << "Syntax error at " << anArg << ".\n";
6559           return 1;
6560         }
6561       }
6562     }
6563     // animation definition options
6564     else if (anArg == "-start"
6565           || anArg == "-starttime"
6566           || anArg == "-startpts")
6567     {
6568       if (++anArgIter >= theArgNb)
6569       {
6570         std::cout << "Syntax error at " << anArg << ".\n";
6571         return 1;
6572       }
6573
6574       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
6575       aRootAnimation->UpdateTotalDuration();
6576     }
6577     else if (anArg == "-end"
6578           || anArg == "-endtime"
6579           || anArg == "-endpts")
6580     {
6581       if (++anArgIter >= theArgNb)
6582       {
6583         std::cout << "Syntax error at " << anArg << ".\n";
6584         return 1;
6585       }
6586
6587       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
6588       aRootAnimation->UpdateTotalDuration();
6589     }
6590     else if (anArg == "-dur"
6591           || anArg == "-duration")
6592     {
6593       if (++anArgIter >= theArgNb)
6594       {
6595         std::cout << "Syntax error at " << anArg << ".\n";
6596         return 1;
6597       }
6598
6599       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
6600       aRootAnimation->UpdateTotalDuration();
6601     }
6602     else if (anArg == "-command"
6603           || anArg == "-cmd"
6604           || anArg == "-invoke"
6605           || anArg == "-eval"
6606           || anArg == "-proc")
6607     {
6608       if (++anArgIter >= theArgNb)
6609       {
6610         std::cout << "Syntax error at " << anArg << ".\n";
6611         return 1;
6612       }
6613
6614       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
6615       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
6616     }
6617     else if (anArg == "-objecttrsf"
6618           || anArg == "-objectransformation"
6619           || anArg == "-objtransformation"
6620           || anArg == "-objtrsf"
6621           || anArg == "-object"
6622           || anArg == "-obj")
6623     {
6624       if (++anArgIter >= theArgNb)
6625       {
6626         std::cout << "Syntax error at " << anArg << ".\n";
6627         return 1;
6628       }
6629
6630       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
6631       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
6632       if (!aMapOfAIS.IsBound2 (anObjName))
6633       {
6634         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
6635         return 1;
6636       }
6637
6638       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
6639       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
6640       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
6641       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
6642       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
6643       Standard_Boolean isTrsfSet = Standard_False;
6644       Standard_Integer aTrsfArgIter = anArgIter + 1;
6645       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
6646       {
6647         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
6648         aTrsfArg.LowerCase();
6649         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
6650         if (aTrsfArg.StartsWith ("-rotation")
6651          || aTrsfArg.StartsWith ("-rot"))
6652         {
6653           isTrsfSet = Standard_True;
6654           if (aTrsfArgIter + 4 >= theArgNb
6655           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
6656           {
6657             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6658             return 1;
6659           }
6660           aTrsfArgIter += 4;
6661         }
6662         else if (aTrsfArg.StartsWith ("-location")
6663               || aTrsfArg.StartsWith ("-loc"))
6664         {
6665           isTrsfSet = Standard_True;
6666           if (aTrsfArgIter + 3 >= theArgNb
6667           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
6668           {
6669             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6670             return 1;
6671           }
6672           aTrsfArgIter += 3;
6673         }
6674         else if (aTrsfArg.StartsWith ("-scale"))
6675         {
6676           isTrsfSet = Standard_True;
6677           if (++aTrsfArgIter >= theArgNb)
6678           {
6679             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6680             return 1;
6681           }
6682
6683           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
6684           if (!aScaleStr.IsRealValue())
6685           {
6686             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6687             return 1;
6688           }
6689           aScales[anIndex] = aScaleStr.RealValue();
6690         }
6691         else
6692         {
6693           anArgIter = aTrsfArgIter - 1;
6694           break;
6695         }
6696       }
6697       if (!isTrsfSet)
6698       {
6699         std::cout << "Syntax error at " << anArg << ".\n";
6700         return 1;
6701       }
6702       else if (aTrsfArgIter >= theArgNb)
6703       {
6704         anArgIter = theArgNb;
6705       }
6706
6707       aTrsfs[0].SetRotation        (aRotQuats[0]);
6708       aTrsfs[1].SetRotation        (aRotQuats[1]);
6709       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
6710       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
6711       aTrsfs[0].SetScaleFactor     (aScales[0]);
6712       aTrsfs[1].SetScaleFactor     (aScales[1]);
6713
6714       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
6715       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
6716     }
6717     else if (anArg == "-viewtrsf"
6718           || anArg == "-view")
6719     {
6720       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
6721       if (aCamAnimation.IsNull())
6722       {
6723         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
6724         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
6725       }
6726
6727       Handle(Graphic3d_Camera) aCams[2] =
6728       {
6729         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
6730         new Graphic3d_Camera (aCamAnimation->View()->Camera())
6731       };
6732
6733       Standard_Boolean isTrsfSet = Standard_False;
6734       Standard_Integer aViewArgIter = anArgIter + 1;
6735       for (; aViewArgIter < theArgNb; ++aViewArgIter)
6736       {
6737         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
6738         aViewArg.LowerCase();
6739         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
6740         if (aViewArg.StartsWith ("-scale"))
6741         {
6742           isTrsfSet = Standard_True;
6743           if (++aViewArgIter >= theArgNb)
6744           {
6745             std::cout << "Syntax error at " << anArg << ".\n";
6746             return 1;
6747           }
6748
6749           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
6750           if (!aScaleStr.IsRealValue())
6751           {
6752             std::cout << "Syntax error at " << aViewArg << ".\n";
6753             return 1;
6754           }
6755           Standard_Real aScale = aScaleStr.RealValue();
6756           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
6757           aCams[anIndex]->SetScale (aScale);
6758         }
6759         else if (aViewArg.StartsWith ("-eye")
6760               || aViewArg.StartsWith ("-center")
6761               || aViewArg.StartsWith ("-at")
6762               || aViewArg.StartsWith ("-up"))
6763         {
6764           isTrsfSet = Standard_True;
6765           gp_XYZ anXYZ;
6766           if (aViewArgIter + 3 >= theArgNb
6767           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
6768           {
6769             std::cout << "Syntax error at " << aViewArg << ".\n";
6770             return 1;
6771           }
6772           aViewArgIter += 3;
6773
6774           if (aViewArg.StartsWith ("-eye"))
6775           {
6776             aCams[anIndex]->SetEye (anXYZ);
6777           }
6778           else if (aViewArg.StartsWith ("-center")
6779                 || aViewArg.StartsWith ("-at"))
6780           {
6781             aCams[anIndex]->SetCenter (anXYZ);
6782           }
6783           else if (aViewArg.StartsWith ("-up"))
6784           {
6785             aCams[anIndex]->SetUp (anXYZ);
6786           }
6787         }
6788         else
6789         {
6790           anArgIter = aViewArgIter - 1;
6791           break;
6792         }
6793       }
6794       if (!isTrsfSet)
6795       {
6796         std::cout << "Syntax error at " << anArg << ".\n";
6797         return 1;
6798       }
6799       else if (aViewArgIter >= theArgNb)
6800       {
6801         anArgIter = theArgNb;
6802       }
6803
6804       aCamAnimation->SetCameraStart(aCams[0]);
6805       aCamAnimation->SetCameraEnd  (aCams[1]);
6806     }
6807     else
6808     {
6809       std::cout << "Syntax error at " << anArg << ".\n";
6810       return 1;
6811     }
6812   }
6813
6814   if (!toPlay)
6815   {
6816     return 0;
6817   }
6818
6819   // Start animation timeline and process frame updating.
6820   TheIsAnimating = Standard_True;
6821   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
6822   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
6823   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
6824   if (isFreeCamera)
6825   {
6826     aView->Camera()->Copy (aCameraBack);
6827   }
6828
6829   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
6830   if (aFpsNum <= 0)
6831   {
6832     while (!anAnimation->IsStopped())
6833     {
6834       aCameraBack->Copy (aView->Camera());
6835       const Standard_Real aPts = anAnimation->UpdateTimer();
6836       if (isFreeCamera)
6837       {
6838         aView->Camera()->Copy (aCameraBack);
6839       }
6840
6841       if (aPts >= anUpperPts)
6842       {
6843         anAnimation->Pause();
6844         break;
6845       }
6846
6847       if (aView->IsInvalidated())
6848       {
6849         aView->Redraw();
6850       }
6851       else
6852       {
6853         aView->RedrawImmediate();
6854       }
6855
6856       if (!isLockLoop)
6857       {
6858         // handle user events
6859         theDI.Eval ("after 1 set waiter 1");
6860         theDI.Eval ("vwait waiter");
6861       }
6862       if (!TheIsAnimating)
6863       {
6864         anAnimation->Pause();
6865         theDI << aPts;
6866         break;
6867       }
6868     }
6869
6870     if (aView->IsInvalidated())
6871     {
6872       aView->Redraw();
6873     }
6874     else
6875     {
6876       aView->RedrawImmediate();
6877     }
6878   }
6879   else
6880   {
6881     OSD_Timer aPerfTimer;
6882     aPerfTimer.Start();
6883
6884     // Manage frame-rated animation here
6885     Standard_Real aPts = aPlayStartTime;
6886     int64_t aNbFrames = 0;
6887     for (; aPts <= anUpperPts;)
6888     {
6889       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
6890       aPts = aPlayStartTime + aRecPts;
6891       ++aNbFrames;
6892       if (!anAnimation->Update (aPts))
6893       {
6894         break;
6895       }
6896
6897       aView->Redraw();
6898     }
6899
6900     aPerfTimer.Stop();
6901     anAnimation->Stop();
6902     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
6903     theDI << "Average FPS: " << aRecFps << "\n"
6904           << "Nb. Frames: "  << Standard_Real(aNbFrames);
6905
6906     aView->Redraw();
6907   }
6908
6909   aView->SetImmediateUpdate (wasImmediateUpdate);
6910   TheIsAnimating = Standard_False;
6911   return 0;
6912 }
6913
6914
6915 //=======================================================================
6916 //function : VChangeSelected
6917 //purpose  : Adds the shape to selection or remove one from it
6918 //=======================================================================
6919 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6920                                 Standard_Integer argc,
6921                                 const char ** argv)
6922 {
6923   if(argc != 2)
6924   {
6925     di<<"Usage : " << argv[0] << " shape \n";
6926     return 1;
6927   }
6928   //get AIS_Shape:
6929   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6930   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6931   TCollection_AsciiString aName(argv[1]);
6932   Handle(AIS_InteractiveObject) anAISObject;
6933
6934   if(!aMap.IsBound2(aName))
6935   {
6936     di<<"Use 'vdisplay' before";
6937     return 1;
6938   }
6939   else
6940   {
6941     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6942     if(anAISObject.IsNull()){
6943       di<<"No interactive object \n";
6944       return 1;
6945     }
6946
6947     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
6948   }
6949   return 0;
6950 }
6951
6952 //=======================================================================
6953 //function : VNbSelected
6954 //purpose  : Returns number of selected objects
6955 //=======================================================================
6956 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6957                                 Standard_Integer argc,
6958                                 const char ** argv)
6959 {
6960   if(argc != 1)
6961   {
6962     di << "Usage : " << argv[0] << "\n";
6963     return 1;
6964   }
6965   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6966   if(aContext.IsNull())
6967   {
6968     di << "use 'vinit' command before " << argv[0] << "\n";
6969     return 1;
6970   }
6971   di << aContext->NbSelected() << "\n";
6972   return 0;
6973 }
6974
6975 //=======================================================================
6976 //function : VPurgeDisplay
6977 //purpose  : Switches altialiasing on or off
6978 //=======================================================================
6979 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6980                                 Standard_Integer argc,
6981                                 const char ** argv)
6982 {
6983   if (argc > 1)
6984   {
6985     di << "Usage : " << argv[0] << "\n";
6986     return 1;
6987   }
6988   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6989   if (aContext.IsNull())
6990   {
6991     di << "use 'vinit' command before " << argv[0] << "\n";
6992     return 1;
6993   }
6994
6995   di << aContext->PurgeDisplay() << "\n";
6996   return 0;
6997 }
6998
6999 //=======================================================================
7000 //function : VSetViewSize
7001 //purpose  :
7002 //=======================================================================
7003 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7004                                 Standard_Integer argc,
7005                                 const char ** argv)
7006 {
7007   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7008   if(aContext.IsNull())
7009   {
7010     di << "use 'vinit' command before " << argv[0] << "\n";
7011     return 1;
7012   }
7013   if(argc != 2)
7014   {
7015     di<<"Usage : " << argv[0] << " Size\n";
7016     return 1;
7017   }
7018   Standard_Real aSize = Draw::Atof (argv[1]);
7019   if (aSize <= 0.)
7020   {
7021     di<<"Bad Size value  : " << aSize << "\n";
7022     return 1;
7023   }
7024
7025   Handle(V3d_View) aView = ViewerTest::CurrentView();
7026   aView->SetSize(aSize);
7027   return 0;
7028 }
7029
7030 //=======================================================================
7031 //function : VMoveView
7032 //purpose  :
7033 //=======================================================================
7034 static Standard_Integer VMoveView (Draw_Interpretor& di,
7035                                 Standard_Integer argc,
7036                                 const char ** argv)
7037 {
7038   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7039   if(aContext.IsNull())
7040   {
7041     di << "use 'vinit' command before " << argv[0] << "\n";
7042     return 1;
7043   }
7044   if(argc < 4 || argc > 5)
7045   {
7046     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7047     return 1;
7048   }
7049   Standard_Real Dx = Draw::Atof (argv[1]);
7050   Standard_Real Dy = Draw::Atof (argv[2]);
7051   Standard_Real Dz = Draw::Atof (argv[3]);
7052   Standard_Boolean aStart = Standard_True;
7053   if (argc == 5)
7054   {
7055       aStart = (Draw::Atoi (argv[4]) > 0);
7056   }
7057
7058   Handle(V3d_View) aView = ViewerTest::CurrentView();
7059   aView->Move(Dx,Dy,Dz,aStart);
7060   return 0;
7061 }
7062
7063 //=======================================================================
7064 //function : VTranslateView
7065 //purpose  :
7066 //=======================================================================
7067 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7068                                 Standard_Integer argc,
7069                                 const char ** argv)
7070 {
7071   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7072   if(aContext.IsNull())
7073   {
7074     di << "use 'vinit' command before " << argv[0] << "\n";
7075     return 1;
7076   }
7077   if(argc < 4 || argc > 5)
7078   {
7079     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7080     return 1;
7081   }
7082   Standard_Real Dx = Draw::Atof (argv[1]);
7083   Standard_Real Dy = Draw::Atof (argv[2]);
7084   Standard_Real Dz = Draw::Atof (argv[3]);
7085   Standard_Boolean aStart = Standard_True;
7086   if (argc == 5)
7087   {
7088       aStart = (Draw::Atoi (argv[4]) > 0);
7089   }
7090
7091   Handle(V3d_View) aView = ViewerTest::CurrentView();
7092   aView->Translate(Dx,Dy,Dz,aStart);
7093   return 0;
7094 }
7095
7096 //=======================================================================
7097 //function : VTurnView
7098 //purpose  :
7099 //=======================================================================
7100 static Standard_Integer VTurnView (Draw_Interpretor& di,
7101                                 Standard_Integer argc,
7102                                 const char ** argv)
7103 {
7104   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7105   if(aContext.IsNull()) {
7106     di << "use 'vinit' command before " << argv[0] << "\n";
7107     return 1;
7108   }
7109   if(argc < 4 || argc > 5){
7110     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7111     return 1;
7112   }
7113   Standard_Real Ax = Draw::Atof (argv[1]);
7114   Standard_Real Ay = Draw::Atof (argv[2]);
7115   Standard_Real Az = Draw::Atof (argv[3]);
7116   Standard_Boolean aStart = Standard_True;
7117   if (argc == 5)
7118   {
7119       aStart = (Draw::Atoi (argv[4]) > 0);
7120   }
7121
7122   Handle(V3d_View) aView = ViewerTest::CurrentView();
7123   aView->Turn(Ax,Ay,Az,aStart);
7124   return 0;
7125 }
7126
7127 //==============================================================================
7128 //function : VTextureEnv
7129 //purpose  : ENables or disables environment mapping
7130 //==============================================================================
7131 class OCC_TextureEnv : public Graphic3d_TextureEnv
7132 {
7133 public:
7134   OCC_TextureEnv(const Standard_CString FileName);
7135   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7136   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7137                             const Standard_Boolean theModulateFlag,
7138                             const Graphic3d_TypeOfTextureFilter theFilter,
7139                             const Standard_ShortReal theXScale,
7140                             const Standard_ShortReal theYScale,
7141                             const Standard_ShortReal theXShift,
7142                             const Standard_ShortReal theYShift,
7143                             const Standard_ShortReal theAngle);
7144   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7145 };
7146 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7147
7148 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7149   : Graphic3d_TextureEnv(theFileName)
7150 {
7151 }
7152
7153 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7154   : Graphic3d_TextureEnv(theTexId)
7155 {
7156 }
7157
7158 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7159                                           const Standard_Boolean theModulateFlag,
7160                                           const Graphic3d_TypeOfTextureFilter theFilter,
7161                                           const Standard_ShortReal theXScale,
7162                                           const Standard_ShortReal theYScale,
7163                                           const Standard_ShortReal theXShift,
7164                                           const Standard_ShortReal theYShift,
7165                                           const Standard_ShortReal theAngle)
7166 {
7167   myParams->SetRepeat     (theRepeatFlag);
7168   myParams->SetModulate   (theModulateFlag);
7169   myParams->SetFilter     (theFilter);
7170   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7171   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7172   myParams->SetRotation   (theAngle);
7173 }
7174
7175 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7176 {
7177   // get the active view
7178   Handle(V3d_View) aView = ViewerTest::CurrentView();
7179   if (aView.IsNull())
7180   {
7181     std::cerr << "No active view. Please call vinit.\n";
7182     return 1;
7183   }
7184
7185   // Checking the input arguments
7186   Standard_Boolean anEnableFlag = Standard_False;
7187   Standard_Boolean isOk         = theArgNb >= 2;
7188   if (isOk)
7189   {
7190     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7191     anEnableFlag = anEnableOpt.IsEqual("on");
7192     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7193   }
7194   if (anEnableFlag)
7195   {
7196     isOk = (theArgNb == 3 || theArgNb == 11);
7197     if (isOk)
7198     {
7199       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7200       isOk = (!aTextureOpt.IsIntegerValue() ||
7201              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7202
7203       if (isOk && theArgNb == 11)
7204       {
7205         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7206                                 aModulateOpt(theArgVec[4]),
7207                                 aFilterOpt  (theArgVec[5]),
7208                                 aSScaleOpt  (theArgVec[6]),
7209                                 aTScaleOpt  (theArgVec[7]),
7210                                 aSTransOpt  (theArgVec[8]),
7211                                 aTTransOpt  (theArgVec[9]),
7212                                 anAngleOpt  (theArgVec[10]);
7213         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7214                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7215                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7216                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7217                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7218                 anAngleOpt.IsRealValue());
7219       }
7220     }
7221   }
7222
7223   if (!isOk)
7224   {
7225     std::cerr << "Usage :" << std::endl;
7226     std::cerr << theArgVec[0] << " off" << std::endl;
7227     std::cerr << theArgVec[0] << " on {index_of_std_texture(0..7)|texture_file_name} [{clamp|repeat} {decal|modulate} {nearest|bilinear|trilinear} scale_s scale_t translation_s translation_t rotation_degrees]" << std::endl;
7228     return 1;
7229   }
7230
7231   if (anEnableFlag)
7232   {
7233     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7234     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7235                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7236                                      new OCC_TextureEnv(theArgVec[2]);
7237
7238     if (theArgNb == 11)
7239     {
7240       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7241       aTexEnv->SetTextureParameters(
7242         aRepeatOpt.  IsEqual("repeat"),
7243         aModulateOpt.IsEqual("modulate"),
7244         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7245                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7246                                                                            Graphic3d_TOTF_TRILINEAR,
7247         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7248         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7249         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7250         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7251         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7252         );
7253     }
7254     aView->SetTextureEnv(aTexEnv);
7255   }
7256   else // Disabling environment mapping
7257   {
7258     Handle(Graphic3d_TextureEnv) aTexture;
7259     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7260   }
7261
7262   aView->Redraw();
7263   return 0;
7264 }
7265
7266 namespace
7267 {
7268   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7269
7270   //! Remove registered clipping plane from all views and objects.
7271   static void removePlane (MapOfPlanes& theRegPlanes,
7272                            const TCollection_AsciiString& theName)
7273   {
7274     Handle(Graphic3d_ClipPlane) aClipPlane;
7275     if (!theRegPlanes.Find (theName, aClipPlane))
7276     {
7277       std::cout << "Warning: no such plane.\n";
7278       return;
7279     }
7280
7281     theRegPlanes.UnBind (theName);
7282     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7283          anIObjIt.More(); anIObjIt.Next())
7284     {
7285       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7286       aPrs->RemoveClipPlane (aClipPlane);
7287     }
7288
7289     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7290          aViewIt.More(); aViewIt.Next())
7291     {
7292       const Handle(V3d_View)& aView = aViewIt.Key2();
7293       aView->RemoveClipPlane(aClipPlane);
7294     }
7295
7296     ViewerTest::RedrawAllViews();
7297   }
7298 }
7299
7300 //===============================================================================================
7301 //function : VClipPlane
7302 //purpose  :
7303 //===============================================================================================
7304 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7305 {
7306   // use short-cut for created clip planes map of created (or "registered by name") clip planes
7307   static MapOfPlanes aRegPlanes;
7308
7309   if (theArgsNb < 2)
7310   {
7311     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
7312     {
7313       theDi << aPlaneIter.Key() << " ";
7314     }
7315     return 0;
7316   }
7317
7318   TCollection_AsciiString aCommand (theArgVec[1]);
7319   aCommand.LowerCase();
7320   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
7321   if (anActiveView.IsNull())
7322   {
7323     std::cout << "Error: no active view.\n";
7324     return 1;
7325   }
7326
7327   // print maximum number of planes for current viewer
7328   if (aCommand == "-maxplanes"
7329    || aCommand == "maxplanes")
7330   {
7331     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
7332           << " plane slots provided by driver.\n";
7333     return 0;
7334   }
7335
7336   // create / delete plane instance
7337   if (aCommand == "-create"
7338    || aCommand == "create"
7339    || aCommand == "-delete"
7340    || aCommand == "delete"
7341    || aCommand == "-clone"
7342    || aCommand == "clone")
7343   {
7344     if (theArgsNb < 3)
7345     {
7346       std::cout << "Syntax error: plane name is required.\n";
7347       return 1;
7348     }
7349
7350     Standard_Boolean toCreate = aCommand == "-create"
7351                              || aCommand == "create";
7352     Standard_Boolean toClone  = aCommand == "-clone"
7353                              || aCommand == "clone";
7354     Standard_Boolean toDelete = aCommand == "-delete"
7355                              || aCommand == "delete";
7356     TCollection_AsciiString aPlane (theArgVec[2]);
7357
7358     if (toCreate)
7359     {
7360       if (aRegPlanes.IsBound (aPlane))
7361       {
7362         std::cout << "Warning: existing plane has been overridden.\n";
7363         toDelete = true;
7364       }
7365       else
7366       {
7367         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7368         return 0;
7369       }
7370     }
7371     else if (toClone) // toClone
7372     {
7373       if (!aRegPlanes.IsBound (aPlane))
7374       {
7375         std::cout << "Error: no such plane.\n";
7376         return 1;
7377       }
7378       else if (theArgsNb < 4)
7379       {
7380         std::cout << "Syntax error: enter name for new plane.\n";
7381         return 1;
7382       }
7383
7384       TCollection_AsciiString aClone (theArgVec[3]);
7385       if (aRegPlanes.IsBound (aClone))
7386       {
7387         std::cout << "Error: plane name is in use.\n";
7388         return 1;
7389       }
7390
7391       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
7392
7393       aRegPlanes.Bind (aClone, aClipPlane->Clone());
7394       return 0;
7395     }
7396
7397     if (toDelete)
7398     {
7399       if (aPlane == "ALL"
7400        || aPlane == "all"
7401        || aPlane == "*")
7402       {
7403         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
7404         {
7405           aPlane = aPlaneIter.Key();
7406           removePlane (aRegPlanes, aPlane);
7407           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
7408         }
7409       }
7410       else
7411       {
7412         removePlane (aRegPlanes, aPlane);
7413       }
7414     }
7415
7416     if (toCreate)
7417     {
7418       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7419     }
7420     return 0;
7421   }
7422
7423   // set / unset plane command
7424   if (aCommand == "set"
7425    || aCommand == "unset")
7426   {
7427     if (theArgsNb < 5)
7428     {
7429       std::cout << "Syntax error: need more arguments.\n";
7430       return 1;
7431     }
7432
7433     // redirect to new syntax
7434     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
7435     anArgVec.SetValue (1, theArgVec[0]);
7436     anArgVec.SetValue (2, theArgVec[2]);
7437     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
7438     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
7439     {
7440       anArgVec.SetValue (anIt, theArgVec[anIt]);
7441     }
7442
7443     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
7444   }
7445
7446   // change plane command
7447   TCollection_AsciiString aPlaneName;
7448   Handle(Graphic3d_ClipPlane) aClipPlane;
7449   Standard_Integer anArgIter = 0;
7450   if (aCommand == "-change"
7451    || aCommand == "change")
7452   {
7453     // old syntax support
7454     if (theArgsNb < 3)
7455     {
7456       std::cout << "Syntax error: need more arguments.\n";
7457       return 1;
7458     }
7459
7460     anArgIter  = 3;
7461     aPlaneName = theArgVec[2];
7462     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
7463     {
7464       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
7465       return 1;
7466     }
7467   }
7468   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
7469   {
7470     anArgIter  = 2;
7471     aPlaneName = theArgVec[1];
7472   }
7473   else
7474   {
7475     anArgIter  = 2;
7476     aPlaneName = theArgVec[1];
7477     aClipPlane = new Graphic3d_ClipPlane();
7478     aRegPlanes.Bind (aPlaneName, aClipPlane);
7479     theDi << "Created new plane " << aPlaneName << ".\n";
7480   }
7481
7482   if (theArgsNb - anArgIter < 1)
7483   {
7484     std::cout << "Syntax error: need more arguments.\n";
7485     return 1;
7486   }
7487
7488   for (; anArgIter < theArgsNb; ++anArgIter)
7489   {
7490     const char**     aChangeArgs   = theArgVec + anArgIter;
7491     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
7492     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
7493     aChangeArg.LowerCase();
7494
7495     Standard_Boolean toEnable = Standard_True;
7496     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
7497     {
7498       aClipPlane->SetOn (toEnable);
7499     }
7500     else if (aChangeArg == "-equation"
7501           || aChangeArg == "equation")
7502     {
7503       if (aNbChangeArgs < 5)
7504       {
7505         std::cout << "Syntax error: need more arguments.\n";
7506         return 1;
7507       }
7508
7509       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
7510       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
7511       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
7512       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
7513       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
7514       anArgIter += 4;
7515     }
7516     else if (aChangeArg == "-capping"
7517           || aChangeArg == "capping")
7518     {
7519       if (aNbChangeArgs < 2)
7520       {
7521         std::cout << "Syntax error: need more arguments.\n";
7522         return 1;
7523       }
7524
7525       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7526       {
7527         aClipPlane->SetCapping (toEnable);
7528         anArgIter += 1;
7529       }
7530       else
7531       {
7532         // just skip otherwise (old syntax)
7533       }
7534     }
7535     else if (aChangeArg == "-useobjectmaterial"
7536           || aChangeArg == "-useobjectmat"
7537           || aChangeArg == "-useobjmat"
7538           || aChangeArg == "-useobjmaterial")
7539     {
7540       if (aNbChangeArgs < 2)
7541       {
7542         std::cout << "Syntax error: need more arguments.\n";
7543         return 1;
7544       }
7545
7546       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7547       {
7548         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
7549         anArgIter += 1;
7550       }
7551     }
7552     else if (aChangeArg == "-useobjecttexture"
7553           || aChangeArg == "-useobjecttex"
7554           || aChangeArg == "-useobjtexture"
7555           || aChangeArg == "-useobjtex")
7556     {
7557       if (aNbChangeArgs < 2)
7558       {
7559         std::cout << "Syntax error: need more arguments.\n";
7560         return 1;
7561       }
7562
7563       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7564       {
7565         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
7566         anArgIter += 1;
7567       }
7568     }
7569     else if (aChangeArg == "-useobjectshader"
7570           || aChangeArg == "-useobjshader")
7571     {
7572       if (aNbChangeArgs < 2)
7573       {
7574         std::cout << "Syntax error: need more arguments.\n";
7575         return 1;
7576       }
7577
7578       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7579       {
7580         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
7581         anArgIter += 1;
7582       }
7583     }
7584     else if (aChangeArg == "-color"
7585           || aChangeArg == "color")
7586     {
7587       Quantity_Color aColor;
7588       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
7589                                                            aChangeArgs + 1,
7590                                                            aColor);
7591       if (aNbParsed == 0)
7592       {
7593         std::cout << "Syntax error: need more arguments.\n";
7594         return 1;
7595       }
7596
7597       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
7598       aMat.SetAmbientColor (aColor);
7599       aMat.SetDiffuseColor (aColor);
7600       aClipPlane->SetCappingMaterial (aMat);
7601       anArgIter += aNbParsed;
7602     }
7603     else if (aChangeArg == "-texname"
7604           || aChangeArg == "texname")
7605     {
7606       if (aNbChangeArgs < 2)
7607       {
7608         std::cout << "Syntax error: need more arguments.\n";
7609         return 1;
7610       }
7611
7612       TCollection_AsciiString aTextureName (aChangeArgs[1]);
7613       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
7614       if (!aTexture->IsDone())
7615       {
7616         aClipPlane->SetCappingTexture (NULL);
7617       }
7618       else
7619       {
7620         aTexture->EnableModulate();
7621         aTexture->EnableRepeat();
7622         aClipPlane->SetCappingTexture (aTexture);
7623       }
7624       anArgIter += 1;
7625     }
7626     else if (aChangeArg == "-texscale"
7627           || aChangeArg == "texscale")
7628     {
7629       if (aClipPlane->CappingTexture().IsNull())
7630       {
7631         std::cout << "Error: no texture is set.\n";
7632         return 1;
7633       }
7634
7635       if (aNbChangeArgs < 3)
7636       {
7637         std::cout << "Syntax error: need more arguments.\n";
7638         return 1;
7639       }
7640
7641       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7642       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7643       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
7644       anArgIter += 2;
7645     }
7646     else if (aChangeArg == "-texorigin"
7647           || aChangeArg == "texorigin") // texture origin
7648     {
7649       if (aClipPlane->CappingTexture().IsNull())
7650       {
7651         std::cout << "Error: no texture is set.\n";
7652         return 1;
7653       }
7654
7655       if (aNbChangeArgs < 3)
7656       {
7657         std::cout << "Syntax error: need more arguments.\n";
7658         return 1;
7659       }
7660
7661       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7662       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7663
7664       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
7665       anArgIter += 2;
7666     }
7667     else if (aChangeArg == "-texrotate"
7668           || aChangeArg == "texrotate") // texture rotation
7669     {
7670       if (aClipPlane->CappingTexture().IsNull())
7671       {
7672         std::cout << "Error: no texture is set.\n";
7673         return 1;
7674       }
7675
7676       if (aNbChangeArgs < 2)
7677       {
7678         std::cout << "Syntax error: need more arguments.\n";
7679         return 1;
7680       }
7681
7682       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7683       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7684       anArgIter += 1;
7685     }
7686     else if (aChangeArg == "-hatch"
7687           || aChangeArg == "hatch")
7688     {
7689       if (aNbChangeArgs < 2)
7690       {
7691         std::cout << "Syntax error: need more arguments.\n";
7692         return 1;
7693       }
7694
7695       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
7696       aHatchStr.LowerCase();
7697       if (aHatchStr == "on")
7698       {
7699         aClipPlane->SetCappingHatchOn();
7700       }
7701       else if (aHatchStr == "off")
7702       {
7703         aClipPlane->SetCappingHatchOff();
7704       }
7705       else
7706       {
7707         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
7708       }
7709       anArgIter += 1;
7710     }
7711     else if (aChangeArg == "-delete"
7712           || aChangeArg == "delete")
7713     {
7714       removePlane (aRegPlanes, aPlaneName);
7715       return 0;
7716     }
7717     else if (aChangeArg == "-set"
7718           || aChangeArg == "-unset")
7719     {
7720       // set / unset plane command
7721       Standard_Boolean toSet = aChangeArg == "-set";
7722       Standard_Integer anIt = 1;
7723       for (; anIt < aNbChangeArgs; ++anIt)
7724       {
7725         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
7726         if (anEntityName.IsEmpty()
7727          || anEntityName.Value (1) == '-')
7728         {
7729           break;
7730         }
7731         else if (ViewerTest_myViews.IsBound1 (anEntityName))
7732         {
7733           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
7734           if (toSet)
7735           {
7736             aView->AddClipPlane (aClipPlane);
7737           }
7738           else
7739           {
7740             aView->RemoveClipPlane (aClipPlane);
7741           }
7742           continue;
7743         }
7744         else if (GetMapOfAIS().IsBound2 (anEntityName))
7745         {
7746           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
7747           if (toSet)
7748           {
7749             aIObj->AddClipPlane (aClipPlane);
7750           }
7751           else
7752           {
7753             aIObj->RemoveClipPlane (aClipPlane);
7754           }
7755         }
7756         else
7757         {
7758           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
7759           return 1;
7760         }
7761       }
7762
7763       if (anIt == 1)
7764       {
7765         // apply to active view
7766         if (toSet)
7767         {
7768           anActiveView->AddClipPlane (aClipPlane);
7769         }
7770         else
7771         {
7772           anActiveView->RemoveClipPlane (aClipPlane);
7773         }
7774       }
7775       else
7776       {
7777         anArgIter = anArgIter + anIt - 1;
7778       }
7779     }
7780     else
7781     {
7782       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
7783       return 1;
7784     }
7785   }
7786
7787   ViewerTest::RedrawAllViews();
7788   return 0;
7789 }
7790
7791 //===============================================================================================
7792 //function : VZRange
7793 //purpose  :
7794 //===============================================================================================
7795 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7796 {
7797   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7798
7799   if (aCurrentView.IsNull())
7800   {
7801     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7802     return 1;
7803   }
7804
7805   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7806
7807   if (theArgsNb < 2)
7808   {
7809     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7810     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7811     return 0;
7812   }
7813
7814   if (theArgsNb == 3)
7815   {
7816     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7817     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7818
7819     if (aNewZNear >= aNewZFar)
7820     {
7821       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7822       return 1;
7823     }
7824
7825     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7826     {
7827       std::cout << theArgVec[0] << ": invalid arguments: ";
7828       std::cout << "znear, zfar should be positive for perspective camera.\n";
7829       return 1;
7830     }
7831
7832     aCamera->SetZRange (aNewZNear, aNewZFar);
7833   }
7834   else
7835   {
7836     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7837     return 1;
7838   }
7839
7840   aCurrentView->Redraw();
7841
7842   return 0;
7843 }
7844
7845 //===============================================================================================
7846 //function : VAutoZFit
7847 //purpose  :
7848 //===============================================================================================
7849 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7850 {
7851   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7852
7853   if (aCurrentView.IsNull())
7854   {
7855     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7856     return 1;
7857   }
7858
7859   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7860
7861   if (theArgsNb > 3)
7862   {
7863     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7864     return 1;
7865   }
7866
7867   if (theArgsNb < 2)
7868   {
7869     theDi << "Auto z-fit mode: \n"
7870           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7871           << "Scale: " << aScale << "\n";
7872     return 0;
7873   }
7874
7875   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7876
7877   if (theArgsNb >= 3)
7878   {
7879     aScale = Draw::Atoi (theArgVec[2]);
7880   }
7881
7882   aCurrentView->SetAutoZFitMode (isOn, aScale);
7883   aCurrentView->AutoZFit();
7884   aCurrentView->Redraw();
7885
7886   return 0;
7887 }
7888
7889 //! Auxiliary function to print projection type
7890 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7891 {
7892   switch (theProjType)
7893   {
7894     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7895     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7896     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7897     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7898     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7899   }
7900   return "UNKNOWN";
7901 }
7902
7903 //===============================================================================================
7904 //function : VCamera
7905 //purpose  :
7906 //===============================================================================================
7907 static int VCamera (Draw_Interpretor& theDI,
7908                     Standard_Integer  theArgsNb,
7909                     const char**      theArgVec)
7910 {
7911   Handle(V3d_View) aView = ViewerTest::CurrentView();
7912   if (aView.IsNull())
7913   {
7914     std::cout << "Error: no active view.\n";
7915     return 1;
7916   }
7917
7918   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7919   if (theArgsNb < 2)
7920   {
7921     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7922     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7923     theDI << "Distance:   " << aCamera->Distance() << "\n";
7924     theDI << "IOD:        " << aCamera->IOD() << "\n";
7925     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7926     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7927     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7928     return 0;
7929   }
7930
7931   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7932   {
7933     Standard_CString        anArg = theArgVec[anArgIter];
7934     TCollection_AsciiString anArgCase (anArg);
7935     anArgCase.LowerCase();
7936     if (anArgCase == "-proj"
7937      || anArgCase == "-projection"
7938      || anArgCase == "-projtype"
7939      || anArgCase == "-projectiontype")
7940     {
7941       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7942     }
7943     else if (anArgCase == "-ortho"
7944           || anArgCase == "-orthographic")
7945     {
7946       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7947     }
7948     else if (anArgCase == "-persp"
7949           || anArgCase == "-perspective"
7950           || anArgCase == "-perspmono"
7951           || anArgCase == "-perspectivemono"
7952           || anArgCase == "-mono")
7953     {
7954       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7955     }
7956     else if (anArgCase == "-stereo"
7957           || anArgCase == "-stereoscopic"
7958           || anArgCase == "-perspstereo"
7959           || anArgCase == "-perspectivestereo")
7960     {
7961       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7962     }
7963     else if (anArgCase == "-left"
7964           || anArgCase == "-lefteye"
7965           || anArgCase == "-monoleft"
7966           || anArgCase == "-monolefteye"
7967           || anArgCase == "-perpsleft"
7968           || anArgCase == "-perpslefteye")
7969     {
7970       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7971     }
7972     else if (anArgCase == "-right"
7973           || anArgCase == "-righteye"
7974           || anArgCase == "-monoright"
7975           || anArgCase == "-monorighteye"
7976           || anArgCase == "-perpsright")
7977     {
7978       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7979     }
7980     else if (anArgCase == "-dist"
7981           || anArgCase == "-distance")
7982     {
7983       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7984       if (anArgValue != NULL
7985       && *anArgValue != '-')
7986       {
7987         ++anArgIter;
7988         aCamera->SetDistance (Draw::Atof (anArgValue));
7989         continue;
7990       }
7991       theDI << aCamera->Distance() << " ";
7992     }
7993     else if (anArgCase == "-iod")
7994     {
7995       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7996       if (anArgValue != NULL
7997       && *anArgValue != '-')
7998       {
7999         ++anArgIter;
8000         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8001         continue;
8002       }
8003       theDI << aCamera->IOD() << " ";
8004     }
8005     else if (anArgCase == "-iodtype")
8006     {
8007       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8008       TCollection_AsciiString anValueCase (anArgValue);
8009       anValueCase.LowerCase();
8010       if (anValueCase == "abs"
8011        || anValueCase == "absolute")
8012       {
8013         ++anArgIter;
8014         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8015         continue;
8016       }
8017       else if (anValueCase == "rel"
8018             || anValueCase == "relative")
8019       {
8020         ++anArgIter;
8021         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8022         continue;
8023       }
8024       else if (*anArgValue != '-')
8025       {
8026         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8027         return 1;
8028       }
8029       switch (aCamera->GetIODType())
8030       {
8031         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8032         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8033       }
8034     }
8035     else if (anArgCase == "-zfocus")
8036     {
8037       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8038       if (anArgValue != NULL
8039       && *anArgValue != '-')
8040       {
8041         ++anArgIter;
8042         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8043         continue;
8044       }
8045       theDI << aCamera->ZFocus() << " ";
8046     }
8047     else if (anArgCase == "-zfocustype")
8048     {
8049       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8050       TCollection_AsciiString anValueCase (anArgValue);
8051       anValueCase.LowerCase();
8052       if (anValueCase == "abs"
8053        || anValueCase == "absolute")
8054       {
8055         ++anArgIter;
8056         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8057         continue;
8058       }
8059       else if (anValueCase == "rel"
8060             || anValueCase == "relative")
8061       {
8062         ++anArgIter;
8063         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8064         continue;
8065       }
8066       else if (*anArgValue != '-')
8067       {
8068         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8069         return 1;
8070       }
8071       switch (aCamera->ZFocusType())
8072       {
8073         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8074         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8075       }
8076     }
8077     else if (anArgCase == "-fov"
8078           || anArgCase == "-fovy")
8079     {
8080       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8081       if (anArgValue != NULL
8082       && *anArgValue != '-')
8083       {
8084         ++anArgIter;
8085         aCamera->SetFOVy (Draw::Atof (anArgValue));
8086         continue;
8087       }
8088       theDI << aCamera->FOVy() << " ";
8089     }
8090     else
8091     {
8092       std::cout << "Error: unknown argument '" << anArg << "'\n";
8093       return 1;
8094     }
8095   }
8096
8097   aView->AutoZFit();
8098   aView->Redraw();
8099
8100   return 0;
8101 }
8102
8103 //! Parse stereo output mode
8104 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8105                                          Graphic3d_StereoMode& theMode)
8106 {
8107   TCollection_AsciiString aFlag (theArg);
8108   aFlag.LowerCase();
8109   if (aFlag == "quadbuffer")
8110   {
8111     theMode = Graphic3d_StereoMode_QuadBuffer;
8112   }
8113   else if (aFlag == "anaglyph")
8114   {
8115     theMode = Graphic3d_StereoMode_Anaglyph;
8116   }
8117   else if (aFlag == "row"
8118         || aFlag == "rowinterlaced")
8119   {
8120     theMode = Graphic3d_StereoMode_RowInterlaced;
8121   }
8122   else if (aFlag == "col"
8123         || aFlag == "colinterlaced"
8124         || aFlag == "columninterlaced")
8125   {
8126     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8127   }
8128   else if (aFlag == "chess"
8129         || aFlag == "chessboard")
8130   {
8131     theMode = Graphic3d_StereoMode_ChessBoard;
8132   }
8133   else if (aFlag == "sbs"
8134         || aFlag == "sidebyside")
8135   {
8136     theMode = Graphic3d_StereoMode_SideBySide;
8137   }
8138   else if (aFlag == "ou"
8139         || aFlag == "overunder")
8140   {
8141     theMode = Graphic3d_StereoMode_OverUnder;
8142   }
8143   else if (aFlag == "pageflip"
8144         || aFlag == "softpageflip")
8145   {
8146     theMode = Graphic3d_StereoMode_SoftPageFlip;
8147   }
8148   else
8149   {
8150     return Standard_False;
8151   }
8152   return Standard_True;
8153 }
8154
8155 //! Parse anaglyph filter
8156 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8157                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8158 {
8159   TCollection_AsciiString aFlag (theArg);
8160   aFlag.LowerCase();
8161   if (aFlag == "redcyansimple")
8162   {
8163     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8164   }
8165   else if (aFlag == "redcyan"
8166         || aFlag == "redcyanoptimized")
8167   {
8168     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8169   }
8170   else if (aFlag == "yellowbluesimple")
8171   {
8172     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8173   }
8174   else if (aFlag == "yellowblue"
8175         || aFlag == "yellowblueoptimized")
8176   {
8177     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8178   }
8179   else if (aFlag == "greenmagenta"
8180         || aFlag == "greenmagentasimple")
8181   {
8182     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8183   }
8184   else
8185   {
8186     return Standard_False;
8187   }
8188   return Standard_True;
8189 }
8190
8191 //==============================================================================
8192 //function : VStereo
8193 //purpose  :
8194 //==============================================================================
8195
8196 static int VStereo (Draw_Interpretor& theDI,
8197                     Standard_Integer  theArgNb,
8198                     const char**      theArgVec)
8199 {
8200   Handle(V3d_View) aView = ViewerTest::CurrentView();
8201   if (theArgNb < 2)
8202   {
8203     if (aView.IsNull())
8204     {
8205       std::cout << "Error: no active viewer!\n";
8206       return 0;
8207     }
8208
8209     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8210     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8211     if (isActive)
8212     {
8213       TCollection_AsciiString aMode;
8214       switch (aView->RenderingParams().StereoMode)
8215       {
8216         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8217         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8218         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8219         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8220         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8221         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8222         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8223         case Graphic3d_StereoMode_Anaglyph  :
8224           aMode = "anaglyph";
8225           switch (aView->RenderingParams().AnaglyphFilter)
8226           {
8227             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8228             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8229             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8230             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8231             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8232             default: break;
8233           }
8234         default: break;
8235       }
8236       theDI << "Mode " << aMode << "\n";
8237     }
8238     return 0;
8239   }
8240
8241   Handle(Graphic3d_Camera) aCamera;
8242   Graphic3d_RenderingParams*   aParams   = NULL;
8243   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8244   if (!aView.IsNull())
8245   {
8246     aParams   = &aView->ChangeRenderingParams();
8247     aMode     = aParams->StereoMode;
8248     aCamera   = aView->Camera();
8249   }
8250
8251   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8252   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8253   {
8254     Standard_CString        anArg = theArgVec[anArgIter];
8255     TCollection_AsciiString aFlag (anArg);
8256     aFlag.LowerCase();
8257     if (anUpdateTool.parseRedrawMode (aFlag))
8258     {
8259       continue;
8260     }
8261     else if (aFlag == "0"
8262           || aFlag == "off")
8263     {
8264       if (++anArgIter < theArgNb)
8265       {
8266         std::cout << "Error: wrong number of arguments!\n";
8267         return 1;
8268       }
8269
8270       if (!aCamera.IsNull()
8271        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8272       {
8273         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8274       }
8275       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8276       return 0;
8277     }
8278     else if (aFlag == "1"
8279           || aFlag == "on")
8280     {
8281       if (++anArgIter < theArgNb)
8282       {
8283         std::cout << "Error: wrong number of arguments!\n";
8284         return 1;
8285       }
8286
8287       if (!aCamera.IsNull())
8288       {
8289         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8290       }
8291       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8292       return 0;
8293     }
8294     else if (aFlag == "-reverse"
8295           || aFlag == "-reversed"
8296           || aFlag == "-swap")
8297     {
8298       Standard_Boolean toEnable = Standard_True;
8299       if (++anArgIter < theArgNb
8300       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8301       {
8302         --anArgIter;
8303       }
8304       aParams->ToReverseStereo = toEnable;
8305     }
8306     else if (aFlag == "-noreverse"
8307           || aFlag == "-noswap")
8308     {
8309       Standard_Boolean toDisable = Standard_True;
8310       if (++anArgIter < theArgNb
8311       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
8312       {
8313         --anArgIter;
8314       }
8315       aParams->ToReverseStereo = !toDisable;
8316     }
8317     else if (aFlag == "-mode"
8318           || aFlag == "-stereomode")
8319     {
8320       if (++anArgIter >= theArgNb
8321       || !parseStereoMode (theArgVec[anArgIter], aMode))
8322       {
8323         std::cout << "Error: syntax error at '" << anArg << "'\n";
8324         return 1;
8325       }
8326
8327       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8328       {
8329         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8330       }
8331     }
8332     else if (aFlag == "-anaglyph"
8333           || aFlag == "-anaglyphfilter")
8334     {
8335       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8336       if (++anArgIter >= theArgNb
8337       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
8338       {
8339         std::cout << "Error: syntax error at '" << anArg << "'\n";
8340         return 1;
8341       }
8342
8343       aMode = Graphic3d_StereoMode_Anaglyph;
8344       aParams->AnaglyphFilter = aFilter;
8345     }
8346     else if (parseStereoMode (anArg, aMode)) // short syntax
8347     {
8348       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8349       {
8350         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8351       }
8352     }
8353     else
8354     {
8355       std::cout << "Error: syntax error at '" << anArg << "'\n";
8356       return 1;
8357     }
8358   }
8359
8360   if (!aView.IsNull())
8361   {
8362     aParams->StereoMode = aMode;
8363     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8364   }
8365   return 0;
8366 }
8367
8368 //===============================================================================================
8369 //function : VDefaults
8370 //purpose  :
8371 //===============================================================================================
8372 static int VDefaults (Draw_Interpretor& theDi,
8373                       Standard_Integer  theArgsNb,
8374                       const char**      theArgVec)
8375 {
8376   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
8377   if (aCtx.IsNull())
8378   {
8379     std::cerr << "No active viewer!\n";
8380     return 1;
8381   }
8382
8383   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
8384   if (theArgsNb < 2)
8385   {
8386     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
8387     {
8388       theDi << "DeflType:           relative\n"
8389             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
8390     }
8391     else
8392     {
8393       theDi << "DeflType:           absolute\n"
8394             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
8395     }
8396     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
8397     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
8398     return 0;
8399   }
8400
8401   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8402   {
8403     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8404     anArg.UpperCase();
8405     if (anArg == "-ABSDEFL"
8406      || anArg == "-ABSOLUTEDEFLECTION"
8407      || anArg == "-DEFL"
8408      || anArg == "-DEFLECTION")
8409     {
8410       if (++anArgIter >= theArgsNb)
8411       {
8412         std::cout << "Error: wrong syntax at " << anArg << "\n";
8413         return 1;
8414       }
8415       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
8416       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
8417     }
8418     else if (anArg == "-RELDEFL"
8419           || anArg == "-RELATIVEDEFLECTION"
8420           || anArg == "-DEVCOEFF"
8421           || anArg == "-DEVIATIONCOEFF"
8422           || anArg == "-DEVIATIONCOEFFICIENT")
8423     {
8424       if (++anArgIter >= theArgsNb)
8425       {
8426         std::cout << "Error: wrong syntax at " << anArg << "\n";
8427         return 1;
8428       }
8429       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
8430       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
8431     }
8432     else if (anArg == "-ANGDEFL"
8433           || anArg == "-ANGULARDEFL"
8434           || anArg == "-ANGULARDEFLECTION")
8435     {
8436       if (++anArgIter >= theArgsNb)
8437       {
8438         std::cout << "Error: wrong syntax at " << anArg << "\n";
8439         return 1;
8440       }
8441       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
8442       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
8443     }
8444     else if (anArg == "-AUTOTR"
8445           || anArg == "-AUTOTRIANG"
8446           || anArg == "-AUTOTRIANGULATION")
8447     {
8448       if (++anArgIter >= theArgsNb)
8449       {
8450         std::cout << "Error: wrong syntax at " << anArg << "\n";
8451         return 1;
8452       }
8453       TCollection_AsciiString aValue (theArgVec[anArgIter]);
8454       aValue.LowerCase();
8455       if (aValue == "on"
8456        || aValue == "1")
8457       {
8458         aDefParams->SetAutoTriangulation (Standard_True);
8459       }
8460       else if (aValue == "off"
8461             || aValue == "0")
8462       {
8463         aDefParams->SetAutoTriangulation (Standard_False);
8464       }
8465     }
8466     else
8467     {
8468       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
8469     }
8470   }
8471
8472   return 0;
8473 }
8474
8475 //! Auxiliary method
8476 inline void addLight (const Handle(V3d_Light)& theLightNew,
8477                       const Standard_Boolean   theIsGlobal)
8478 {
8479   if (theLightNew.IsNull())
8480   {
8481     return;
8482   }
8483
8484   if (theIsGlobal)
8485   {
8486     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
8487   }
8488   else
8489   {
8490     ViewerTest::CurrentView()->SetLightOn (theLightNew);
8491   }
8492 }
8493
8494 //! Auxiliary method
8495 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
8496 {
8497   TCollection_AsciiString anArgNextCase (theArgNext);
8498   anArgNextCase.UpperCase();
8499   if (anArgNextCase.Length() > 5
8500    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
8501   {
8502     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
8503   }
8504   else
8505   {
8506     return theArgNext.IntegerValue();
8507   }
8508 }
8509
8510 //===============================================================================================
8511 //function : VLight
8512 //purpose  :
8513 //===============================================================================================
8514 static int VLight (Draw_Interpretor& theDi,
8515                    Standard_Integer  theArgsNb,
8516                    const char**      theArgVec)
8517 {
8518   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8519   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8520   if (aView.IsNull()
8521    || aViewer.IsNull())
8522   {
8523     std::cerr << "No active viewer!\n";
8524     return 1;
8525   }
8526
8527   Standard_Real        anXYZ[3];
8528   Quantity_Coefficient anAtten[2];
8529   if (theArgsNb < 2)
8530   {
8531     // print lights info
8532     Standard_Integer aLightId = 0;
8533     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
8534     {
8535       Handle(V3d_Light) aLight = aLightIter.Value();
8536       const Quantity_Color aColor = aLight->Color();
8537       theDi << "Light" << aLightId << "\n";
8538       switch (aLight->Type())
8539       {
8540         case V3d_AMBIENT:
8541         {
8542           theDi << "  Type:       Ambient\n";
8543           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8544           break;
8545         }
8546         case V3d_DIRECTIONAL:
8547         {
8548           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
8549           theDi << "  Type:       Directional\n";
8550           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8551           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8552           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8553           if (!aLightDir.IsNull())
8554           {
8555             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8556             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8557             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8558             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8559           }
8560           break;
8561         }
8562         case V3d_POSITIONAL:
8563         {
8564           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
8565           theDi << "  Type:       Positional\n";
8566           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8567           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8568           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8569           if (!aLightPos.IsNull())
8570           {
8571             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8572             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8573             aLightPos->Attenuation (anAtten[0], anAtten[1]);
8574             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8575           }
8576           break;
8577         }
8578         case V3d_SPOT:
8579         {
8580           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
8581           theDi << "  Type:       Spot\n";
8582           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8583           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8584           if (!aLightSpot.IsNull())
8585           {
8586             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8587             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8588             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8589             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8590             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8591             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8592             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
8593             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
8594           }
8595           break;
8596         }
8597         default:
8598         {
8599           theDi << "  Type:       UNKNOWN\n";
8600           break;
8601         }
8602       }
8603       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
8604     }
8605   }
8606
8607   Handle(V3d_Light) aLightNew;
8608   Handle(V3d_Light) aLightOld;
8609   Standard_Boolean  isGlobal = Standard_True;
8610   Standard_Boolean  toCreate = Standard_False;
8611   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8612   {
8613     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
8614     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
8615     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
8616     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
8617     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
8618
8619     TCollection_AsciiString aName, aValue;
8620     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
8621     TCollection_AsciiString anArgCase (anArg);
8622     anArgCase.UpperCase();
8623     if (anArgCase.IsEqual ("NEW")
8624      || anArgCase.IsEqual ("ADD")
8625      || anArgCase.IsEqual ("CREATE"))
8626     {
8627       toCreate = Standard_True;
8628     }
8629     else if (anArgCase.IsEqual ("GLOB")
8630           || anArgCase.IsEqual ("GLOBAL"))
8631     {
8632       isGlobal = Standard_True;
8633     }
8634     else if (anArgCase.IsEqual ("LOC")
8635           || anArgCase.IsEqual ("LOCAL"))
8636     {
8637       isGlobal = Standard_False;
8638     }
8639     else if (anArgCase.IsEqual ("DEF")
8640           || anArgCase.IsEqual ("DEFAULTS"))
8641     {
8642       toCreate = Standard_False;
8643       aViewer->SetDefaultLights();
8644     }
8645     else if (anArgCase.IsEqual ("CLR")
8646           || anArgCase.IsEqual ("CLEAR"))
8647     {
8648       toCreate = Standard_False;
8649       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
8650       {
8651         Handle(V3d_Light) aLight = aLightIter.Value();
8652         aViewer->DelLight (aLight);
8653         aLightIter = aView->ActiveLightIterator();
8654       }
8655     }
8656     else if (anArgCase.IsEqual ("AMB")
8657           || anArgCase.IsEqual ("AMBIENT")
8658           || anArgCase.IsEqual ("AMBLIGHT"))
8659     {
8660       addLight (aLightNew, isGlobal);
8661       if (!toCreate)
8662       {
8663         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8664         return 1;
8665       }
8666       toCreate  = Standard_False;
8667       aLightNew = new V3d_AmbientLight (aViewer);
8668     }
8669     else if (anArgCase.IsEqual ("DIRECTIONAL")
8670           || anArgCase.IsEqual ("DIRLIGHT"))
8671     {
8672       addLight (aLightNew, isGlobal);
8673       if (!toCreate)
8674       {
8675         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8676         return 1;
8677       }
8678       toCreate  = Standard_False;
8679       aLightNew = new V3d_DirectionalLight (aViewer);
8680     }
8681     else if (anArgCase.IsEqual ("SPOT")
8682           || anArgCase.IsEqual ("SPOTLIGHT"))
8683     {
8684       addLight (aLightNew, isGlobal);
8685       if (!toCreate)
8686       {
8687         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8688         return 1;
8689       }
8690       toCreate  = Standard_False;
8691       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
8692     }
8693     else if (anArgCase.IsEqual ("POSLIGHT")
8694           || anArgCase.IsEqual ("POSITIONAL"))
8695     {
8696       addLight (aLightNew, isGlobal);
8697       if (!toCreate)
8698       {
8699         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8700         return 1;
8701       }
8702       toCreate  = Standard_False;
8703       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
8704     }
8705     else if (anArgCase.IsEqual ("CHANGE"))
8706     {
8707       addLight (aLightNew, isGlobal);
8708       aLightNew.Nullify();
8709       if (++anArgIt >= theArgsNb)
8710       {
8711         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8712         return 1;
8713       }
8714
8715       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
8716       Standard_Integer aLightIt = 0;
8717       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8718       {
8719         if (aLightIt == aLightId)
8720         {
8721           aLightOld = aLightIter.Value();
8722           break;
8723         }
8724       }
8725
8726       if (aLightOld.IsNull())
8727       {
8728         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
8729         return 1;
8730       }
8731     }
8732     else if (anArgCase.IsEqual ("DEL")
8733           || anArgCase.IsEqual ("DELETE"))
8734     {
8735       Handle(V3d_Light) aLightDel;
8736       if (++anArgIt >= theArgsNb)
8737       {
8738         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8739         return 1;
8740       }
8741
8742       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8743       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
8744       Standard_Integer aLightIt = 0;
8745       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8746       {
8747         aLightDel = aLightIter.Value();
8748         if (aLightIt == aLightDelId)
8749         {
8750           break;
8751         }
8752       }
8753       if (!aLightDel.IsNull())
8754       {
8755         aViewer->DelLight (aLightDel);
8756       }
8757     }
8758     else if (anArgCase.IsEqual ("COLOR")
8759           || anArgCase.IsEqual ("COLOUR"))
8760     {
8761       if (++anArgIt >= theArgsNb)
8762       {
8763         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8764         return 1;
8765       }
8766
8767       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8768       anArgNext.UpperCase();
8769       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8770       if (!aLightCurr.IsNull())
8771       {
8772         aLightCurr->SetColor (aColor);
8773       }
8774     }
8775     else if (anArgCase.IsEqual ("POS")
8776           || anArgCase.IsEqual ("POSITION"))
8777     {
8778       if ((anArgIt + 3) >= theArgsNb)
8779       {
8780         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8781         return 1;
8782       }
8783
8784       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8785       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8786       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8787       if (!aLightDir.IsNull())
8788       {
8789         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8790       }
8791       else if (!aLightPos.IsNull())
8792       {
8793         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8794       }
8795       else if (!aLightSpot.IsNull())
8796       {
8797         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8798       }
8799       else
8800       {
8801         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8802         return 1;
8803       }
8804     }
8805     else if (anArgCase.IsEqual ("DIR")
8806           || anArgCase.IsEqual ("DIRECTION"))
8807     {
8808       if ((anArgIt + 3) >= theArgsNb)
8809       {
8810         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8811         return 1;
8812       }
8813
8814       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8815       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8816       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8817       if (!aLightDir.IsNull())
8818       {
8819         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8820       }
8821       else if (!aLightSpot.IsNull())
8822       {
8823         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8824       }
8825       else
8826       {
8827         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8828         return 1;
8829       }
8830     }
8831     else if (anArgCase.IsEqual ("SM")
8832           || anArgCase.IsEqual ("SMOOTHNESS"))
8833     {
8834       if (++anArgIt >= theArgsNb)
8835       {
8836         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8837         return 1;
8838       }
8839
8840       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8841
8842       if (fabs (aSmoothness) < Precision::Confusion())
8843       {
8844         aLightCurr->SetIntensity (1.f);
8845       }
8846       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8847       {
8848         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8849       }
8850       else
8851       {
8852         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8853         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8854       }
8855
8856       if (!aLightPos.IsNull())
8857       {
8858         aLightPos->SetSmoothRadius (aSmoothness);
8859       }
8860       else if (!aLightDir.IsNull())
8861       {
8862         aLightDir->SetSmoothAngle (aSmoothness);
8863       }
8864     }
8865     else if (anArgCase.IsEqual ("INT")
8866           || anArgCase.IsEqual ("INTENSITY"))
8867     {
8868       if (++anArgIt >= theArgsNb)
8869       {
8870         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8871         return 1;
8872       }
8873
8874       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8875
8876       if (!aLightCurr.IsNull())
8877       {
8878         aLightCurr->SetIntensity (aIntensity);
8879       }
8880     }
8881     else if (anArgCase.IsEqual ("ANG")
8882           || anArgCase.IsEqual ("ANGLE"))
8883     {
8884       if (++anArgIt >= theArgsNb)
8885       {
8886         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8887         return 1;
8888       }
8889
8890       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8891
8892       if (!aLightSpot.IsNull())
8893       {
8894         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8895       }
8896     }
8897     else if (anArgCase.IsEqual ("CONSTATTEN")
8898           || anArgCase.IsEqual ("CONSTATTENUATION"))
8899     {
8900       if (++anArgIt >= theArgsNb)
8901       {
8902         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8903         return 1;
8904       }
8905
8906       if (!aLightPos.IsNull())
8907       {
8908         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8909         anAtten[0] = Atof (theArgVec[anArgIt]);
8910         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8911       }
8912       else if (!aLightSpot.IsNull())
8913       {
8914         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8915         anAtten[0] = Atof (theArgVec[anArgIt]);
8916         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8917       }
8918       else
8919       {
8920         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8921         return 1;
8922       }
8923     }
8924     else if (anArgCase.IsEqual ("LINATTEN")
8925           || anArgCase.IsEqual ("LINEARATTEN")
8926           || anArgCase.IsEqual ("LINEARATTENUATION"))
8927     {
8928       if (++anArgIt >= theArgsNb)
8929       {
8930         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8931         return 1;
8932       }
8933
8934       if (!aLightPos.IsNull())
8935       {
8936         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8937         anAtten[1] = Atof (theArgVec[anArgIt]);
8938         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8939       }
8940       else if (!aLightSpot.IsNull())
8941       {
8942         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8943         anAtten[1] = Atof (theArgVec[anArgIt]);
8944         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8945       }
8946       else
8947       {
8948         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8949         return 1;
8950       }
8951     }
8952     else if (anArgCase.IsEqual ("EXP")
8953           || anArgCase.IsEqual ("EXPONENT")
8954           || anArgCase.IsEqual ("SPOTEXP")
8955           || anArgCase.IsEqual ("SPOTEXPONENT"))
8956     {
8957       if (++anArgIt >= theArgsNb)
8958       {
8959         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8960         return 1;
8961       }
8962
8963       if (!aLightSpot.IsNull())
8964       {
8965         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8966       }
8967       else
8968       {
8969         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8970         return 1;
8971       }
8972     }
8973     else if (anArgCase.IsEqual ("HEAD")
8974           || anArgCase.IsEqual ("HEADLIGHT"))
8975     {
8976       if (++anArgIt >= theArgsNb)
8977       {
8978         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8979         return 1;
8980       }
8981
8982       if (aLightAmb.IsNull()
8983        && !aLightCurr.IsNull())
8984       {
8985         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8986       }
8987       else
8988       {
8989         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8990         return 1;
8991       }
8992     }
8993     else
8994     {
8995       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
8996     }
8997   }
8998
8999   addLight (aLightNew, isGlobal);
9000   aViewer->UpdateLights();
9001
9002   return 0;
9003 }
9004
9005 //=======================================================================
9006 //function : VRenderParams
9007 //purpose  : Enables/disables rendering features
9008 //=======================================================================
9009
9010 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9011                                        Standard_Integer  theArgNb,
9012                                        const char**      theArgVec)
9013 {
9014   Handle(V3d_View) aView = ViewerTest::CurrentView();
9015   if (aView.IsNull())
9016   {
9017     std::cerr << "Error: no active viewer!\n";
9018     return 1;
9019   }
9020
9021   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9022   TCollection_AsciiString aCmdName (theArgVec[0]);
9023   aCmdName.LowerCase();
9024   if (aCmdName == "vraytrace")
9025   {
9026     if (theArgNb == 1)
9027     {
9028       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9029       return 0;
9030     }
9031     else if (theArgNb == 2)
9032     {
9033       TCollection_AsciiString aValue (theArgVec[1]);
9034       aValue.LowerCase();
9035       if (aValue == "on"
9036        || aValue == "1")
9037       {
9038         aParams.Method = Graphic3d_RM_RAYTRACING;
9039         aView->Redraw();
9040         return 0;
9041       }
9042       else if (aValue == "off"
9043             || aValue == "0")
9044       {
9045         aParams.Method = Graphic3d_RM_RASTERIZATION;
9046         aView->Redraw();
9047         return 0;
9048       }
9049       else
9050       {
9051         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9052         return 1;
9053       }
9054     }
9055     else
9056     {
9057       std::cout << "Error: wrong number of arguments\n";
9058       return 1;
9059     }
9060   }
9061
9062   if (theArgNb < 2)
9063   {
9064     theDI << "renderMode:  ";
9065     switch (aParams.Method)
9066     {
9067       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9068       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9069     }
9070     theDI << "\n";
9071     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9072     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9073     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9074     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9075     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9076     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9077     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9078     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9079     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9080     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9081     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9082     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9083     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
9084     theDI << "shadingModel: ";
9085     switch (aView->ShadingModel())
9086     {
9087       case V3d_COLOR:   theDI << "color";   break;
9088       case V3d_FLAT:    theDI << "flat";    break;
9089       case V3d_GOURAUD: theDI << "gouraud"; break;
9090       case V3d_PHONG:   theDI << "phong";   break;
9091     }
9092     theDI << "\n";
9093     return 0;
9094   }
9095
9096   Standard_Boolean toPrint = Standard_False;
9097   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9098   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9099   {
9100     Standard_CString        anArg (theArgVec[anArgIter]);
9101     TCollection_AsciiString aFlag (anArg);
9102     aFlag.LowerCase();
9103     if (anUpdateTool.parseRedrawMode (aFlag))
9104     {
9105       continue;
9106     }
9107     else if (aFlag == "-echo"
9108           || aFlag == "-print")
9109     {
9110       toPrint = Standard_True;
9111       anUpdateTool.Invalidate();
9112     }
9113     else if (aFlag == "-mode"
9114           || aFlag == "-rendermode"
9115           || aFlag == "-render_mode")
9116     {
9117       if (toPrint)
9118       {
9119         switch (aParams.Method)
9120         {
9121           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9122           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9123         }
9124         continue;
9125       }
9126       else
9127       {
9128         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9129         return 1;
9130       }
9131     }
9132     else if (aFlag == "-ray"
9133           || aFlag == "-raytrace")
9134     {
9135       if (toPrint)
9136       {
9137         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9138         continue;
9139       }
9140
9141       aParams.Method = Graphic3d_RM_RAYTRACING;
9142     }
9143     else if (aFlag == "-rast"
9144           || aFlag == "-raster"
9145           || aFlag == "-rasterization")
9146     {
9147       if (toPrint)
9148       {
9149         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9150         continue;
9151       }
9152
9153       aParams.Method = Graphic3d_RM_RASTERIZATION;
9154     }
9155     else if (aFlag == "-msaa")
9156     {
9157       if (toPrint)
9158       {
9159         theDI << aParams.NbMsaaSamples << " ";
9160         continue;
9161       }
9162       else if (++anArgIter >= theArgNb)
9163       {
9164         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9165         return 1;
9166       }
9167
9168       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9169       if (aNbSamples < 0)
9170       {
9171         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9172         return 1;
9173       }
9174       else
9175       {
9176         aParams.NbMsaaSamples = aNbSamples;
9177       }
9178     }
9179     else if (aFlag == "-raydepth"
9180           || aFlag == "-ray_depth")
9181     {
9182       if (toPrint)
9183       {
9184         theDI << aParams.RaytracingDepth << " ";
9185         continue;
9186       }
9187       else if (++anArgIter >= theArgNb)
9188       {
9189         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9190         return 1;
9191       }
9192
9193       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9194
9195       // We allow RaytracingDepth be more than 10 in case of GI enabled
9196       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9197       {
9198         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9199         return 1;
9200       }
9201       else
9202       {
9203         aParams.RaytracingDepth = aDepth;
9204       }
9205     }
9206     else if (aFlag == "-shad"
9207           || aFlag == "-shadows")
9208     {
9209       if (toPrint)
9210       {
9211         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9212         continue;
9213       }
9214
9215       Standard_Boolean toEnable = Standard_True;
9216       if (++anArgIter < theArgNb
9217       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9218       {
9219         --anArgIter;
9220       }
9221       aParams.IsShadowEnabled = toEnable;
9222     }
9223     else if (aFlag == "-refl"
9224           || aFlag == "-reflections")
9225     {
9226       if (toPrint)
9227       {
9228         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
9229         continue;
9230       }
9231
9232       Standard_Boolean toEnable = Standard_True;
9233       if (++anArgIter < theArgNb
9234       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9235       {
9236         --anArgIter;
9237       }
9238       aParams.IsReflectionEnabled = toEnable;
9239     }
9240     else if (aFlag == "-fsaa")
9241     {
9242       if (toPrint)
9243       {
9244         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
9245         continue;
9246       }
9247
9248       Standard_Boolean toEnable = Standard_True;
9249       if (++anArgIter < theArgNb
9250       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9251       {
9252         --anArgIter;
9253       }
9254       aParams.IsAntialiasingEnabled = toEnable;
9255     }
9256     else if (aFlag == "-gleam")
9257     {
9258       if (toPrint)
9259       {
9260         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
9261         continue;
9262       }
9263
9264       Standard_Boolean toEnable = Standard_True;
9265       if (++anArgIter < theArgNb
9266       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9267       {
9268         --anArgIter;
9269       }
9270       aParams.IsTransparentShadowEnabled = toEnable;
9271     }
9272     else if (aFlag == "-gi")
9273     {
9274       if (toPrint)
9275       {
9276         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
9277         continue;
9278       }
9279
9280       Standard_Boolean toEnable = Standard_True;
9281       if (++anArgIter < theArgNb
9282       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9283       {
9284         --anArgIter;
9285       }
9286       aParams.IsGlobalIlluminationEnabled = toEnable;
9287       if (!toEnable)
9288       {
9289         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
9290       }
9291     }
9292     else if (aFlag == "-blockedrng"
9293           || aFlag == "-brng")
9294     {
9295       if (toPrint)
9296       {
9297         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
9298         continue;
9299       }
9300
9301       Standard_Boolean toEnable = Standard_True;
9302       if (++anArgIter < theArgNb
9303         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9304       {
9305         --anArgIter;
9306       }
9307       aParams.CoherentPathTracingMode = toEnable;
9308     }
9309     else if (aFlag == "-maxrad")
9310     {
9311       if (toPrint)
9312       {
9313         theDI << aParams.RadianceClampingValue << " ";
9314         continue;
9315       }
9316       else if (++anArgIter >= theArgNb)
9317       {
9318         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9319         return 1;
9320       }
9321
9322       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
9323       if (!aMaxRadStr.IsRealValue())
9324       {
9325         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9326         return 1;
9327       }
9328
9329       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
9330       if (aMaxRadiance <= 0.0)
9331       {
9332         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
9333         return 1;
9334       }
9335       else
9336       {
9337         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
9338       }
9339     }
9340     else if (aFlag == "-iss")
9341     {
9342       if (toPrint)
9343       {
9344         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
9345         continue;
9346       }
9347
9348       Standard_Boolean toEnable = Standard_True;
9349       if (++anArgIter < theArgNb
9350         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9351       {
9352         --anArgIter;
9353       }
9354       aParams.AdaptiveScreenSampling = toEnable;
9355     }
9356     else if (aFlag == "-issd")
9357     {
9358       if (toPrint)
9359       {
9360         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
9361         continue;
9362       }
9363
9364       Standard_Boolean toEnable = Standard_True;
9365       if (++anArgIter < theArgNb
9366         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9367       {
9368         --anArgIter;
9369       }
9370       aParams.ShowSamplingTiles = toEnable;
9371     }
9372     else if (aFlag == "-nbtiles")
9373     {
9374       if (toPrint)
9375       {
9376         theDI << aParams.NbRayTracingTiles << " ";
9377         continue;
9378       }
9379       else if (++anArgIter >= theArgNb)
9380       {
9381         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9382         return 1;
9383       }
9384
9385       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
9386
9387       if (aNbTiles < 64)
9388       {
9389         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
9390         std::cerr << "Specify value in range [64, 1024].\n";
9391         return 1;
9392       }
9393       else
9394       {
9395         aParams.NbRayTracingTiles = aNbTiles;
9396       }
9397     }
9398     else if (aFlag == "-env")
9399     {
9400       if (toPrint)
9401       {
9402         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
9403         continue;
9404       }
9405
9406       Standard_Boolean toEnable = Standard_True;
9407       if (++anArgIter < theArgNb
9408         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9409       {
9410         --anArgIter;
9411       }
9412       aParams.UseEnvironmentMapBackground = toEnable;
9413     }
9414     else if (aFlag == "-twoside")
9415     {
9416       if (toPrint)
9417       {
9418         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
9419         continue;
9420       }
9421
9422       Standard_Boolean toEnable = Standard_True;
9423       if (++anArgIter < theArgNb
9424         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9425       {
9426         --anArgIter;
9427       }
9428       aParams.TwoSidedBsdfModels = toEnable;
9429     }
9430     else if (aFlag == "-shademodel"
9431           || aFlag == "-shadingmodel"
9432           || aFlag == "-shading")
9433     {
9434       if (toPrint)
9435       {
9436         switch (aView->ShadingModel())
9437         {
9438           case V3d_COLOR:   theDI << "color ";   break;
9439           case V3d_FLAT:    theDI << "flat ";    break;
9440           case V3d_GOURAUD: theDI << "gouraud "; break;
9441           case V3d_PHONG:   theDI << "phong ";   break;
9442         }
9443         continue;
9444       }
9445
9446       if (++anArgIter >= theArgNb)
9447       {
9448         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9449       }
9450
9451       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9452       aMode.LowerCase();
9453       if (aMode == "color"
9454        || aMode == "none")
9455       {
9456         aView->SetShadingModel (V3d_COLOR);
9457       }
9458       else if (aMode == "flat"
9459             || aMode == "facet")
9460       {
9461         aView->SetShadingModel (V3d_FLAT);
9462       }
9463       else if (aMode == "gouraud"
9464             || aMode == "vertex"
9465             || aMode == "vert")
9466       {
9467         aView->SetShadingModel (V3d_GOURAUD);
9468       }
9469       else if (aMode == "phong"
9470             || aMode == "fragment"
9471             || aMode == "frag"
9472             || aMode == "pixel")
9473       {
9474         aView->SetShadingModel (V3d_PHONG);
9475       }
9476       else
9477       {
9478         std::cout << "Error: unknown shading model '" << aMode << "'\n";
9479         return 1;
9480       }
9481     }
9482     else if (aFlag == "-resolution")
9483     {
9484       if (++anArgIter >= theArgNb)
9485       {
9486         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9487         return 1;
9488       }
9489
9490       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
9491       if (aResolution.IsIntegerValue())
9492       {
9493         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
9494       }
9495       else
9496       {
9497         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9498         return 1;
9499       }
9500     }
9501     else if (aFlag == "-rebuildglsl"
9502           || aFlag == "-rebuild")
9503     {
9504       if (toPrint)
9505       {
9506         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
9507         continue;
9508       }
9509
9510       Standard_Boolean toEnable = Standard_True;
9511       if (++anArgIter < theArgNb
9512           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9513       {
9514         --anArgIter;
9515       }
9516       aParams.RebuildRayTracingShaders = toEnable;
9517     }
9518     else
9519     {
9520       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
9521       return 1;
9522     }
9523   }
9524
9525   return 0;
9526 }
9527
9528 //=======================================================================
9529 //function : VProgressiveMode
9530 //purpose  :
9531 //=======================================================================
9532 #if defined(_WIN32)
9533 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
9534                                           Standard_Integer  /*theNbArgs*/,
9535                                           const char**      /*theArgs*/)
9536 {
9537   Handle(V3d_View) aView = ViewerTest::CurrentView();
9538   if (aView.IsNull())
9539   {
9540     std::cerr << "Error: no active viewer!\n";
9541     return 1;
9542   }
9543
9544   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
9545
9546   for (;;)
9547   {
9548     aView->Redraw();
9549
9550     Standard_Boolean toExit = Standard_False;
9551
9552     MSG aMsg;
9553     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
9554     {
9555       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
9556       {
9557         toExit = Standard_True;
9558       }
9559
9560       TranslateMessage (&aMsg);
9561       DispatchMessageW (&aMsg);
9562     }
9563
9564     if (toExit)
9565     {
9566       break;
9567     }
9568   }
9569
9570   return 0;
9571 }
9572 #endif
9573
9574 //=======================================================================
9575 //function : VFrustumCulling
9576 //purpose  : enables/disables view volume's culling.
9577 //=======================================================================
9578 static int VFrustumCulling (Draw_Interpretor& theDI,
9579                             Standard_Integer  theArgNb,
9580                             const char**      theArgVec)
9581 {
9582   Handle(V3d_View) aView = ViewerTest::CurrentView();
9583   if (aView.IsNull())
9584   {
9585     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
9586     return 1;
9587   }
9588
9589   if (theArgNb < 2)
9590   {
9591     theDI << (aView->IsCullingEnabled() ? "on" : "off");
9592     return 0;
9593   }
9594   else if (theArgNb != 2)
9595   {
9596     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
9597     return 1;
9598   }
9599
9600   TCollection_AsciiString aModeStr (theArgVec[1]);
9601   aModeStr.LowerCase();
9602   Standard_Boolean toEnable = 0;
9603   if (aModeStr == "on")
9604   {
9605     toEnable = 1;
9606   }
9607   else if (aModeStr == "off")
9608   {
9609     toEnable = 0;
9610   }
9611   else
9612   {
9613     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9614   }
9615
9616   aView->SetFrustumCulling (toEnable);
9617   aView->Redraw();
9618   return 0;
9619 }
9620
9621 //=======================================================================
9622 //function : VHighlightSelected
9623 //purpose  : 
9624 //=======================================================================
9625 static int VHighlightSelected (Draw_Interpretor& theDI,
9626                                Standard_Integer  theArgNb,
9627                                const char**      theArgVec)
9628 {
9629   if (ViewerTest::GetAISContext().IsNull())
9630   {
9631     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
9632     return 1;
9633   }
9634
9635   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9636
9637   if (theArgNb < 2)
9638   {
9639     theDI << (aContext->ToHilightSelected() ? "on" : "off");
9640     return 0;
9641   }
9642
9643   if (theArgNb != 2)
9644   {
9645     std::cout  << theArgVec[0] << " error : wrong number of parameters."
9646           << "Type 'help" << theArgVec[0] << "' for more information.";
9647     return 1;
9648   }
9649
9650   // Parse parameter
9651   TCollection_AsciiString aMode (theArgVec[1]);
9652   aMode.LowerCase();
9653   Standard_Boolean toEnable = Standard_False;
9654   if (aMode.IsEqual ("on"))
9655   {
9656     toEnable = Standard_True;
9657   }
9658   else if (aMode.IsEqual ("off"))
9659   {
9660     toEnable = Standard_False;
9661   }
9662   else
9663   {
9664     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9665   }
9666
9667   if (toEnable != aContext->ToHilightSelected())
9668   {
9669     aContext->SetToHilightSelected (toEnable);
9670
9671     // Move cursor to null position and  back to process updating of detection
9672     // and highlighting of selected object immediatly.
9673     Standard_Integer aPixX = 0;
9674     Standard_Integer aPixY = 0;
9675     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
9676
9677     anEventManager->GetCurrentPosition (aPixX, aPixY);
9678     anEventManager->MoveTo (0, 0);
9679     anEventManager->MoveTo (aPixX, aPixY);
9680   }
9681
9682   return 0;
9683 }
9684
9685 //=======================================================================
9686 //function : VXRotate
9687 //purpose  :
9688 //=======================================================================
9689 static Standard_Integer VXRotate (Draw_Interpretor& di,
9690                                    Standard_Integer argc,
9691                                    const char ** argv)
9692 {
9693   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9694   if (aContext.IsNull())
9695   {
9696     di << argv[0] << "ERROR : use 'vinit' command before \n";
9697     return 1;
9698   }
9699   
9700   if (argc != 3)
9701   {
9702     di << "ERROR : Usage : " << argv[0] << " name angle\n";
9703     return 1;
9704   }
9705
9706   TCollection_AsciiString aName (argv[1]);
9707   Standard_Real anAngle = Draw::Atof (argv[2]);
9708
9709   // find object
9710   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
9711   Handle(AIS_InteractiveObject) anIObj;
9712   if (!aMap.IsBound2 (aName) )
9713   {
9714     di << "Use 'vdisplay' before\n";
9715     return 1;
9716   }
9717   else
9718   {
9719     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
9720
9721     gp_Trsf aTransform;
9722     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
9723     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
9724
9725     aContext->SetLocation (anIObj, aTransform);
9726     aContext->UpdateCurrentViewer();
9727   }
9728
9729   return 0;
9730 }
9731
9732 //===============================================================================================
9733 //class   : ViewerTest_AISManipulator
9734 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
9735 //===============================================================================================
9736 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9737
9738 class ViewerTest_AISManipulator : public AIS_Manipulator
9739 {
9740 public:
9741
9742   ViewerTest_AISManipulator() : AIS_Manipulator()
9743   {
9744     GetMapOfAISManipulators().Add (this);
9745   }
9746
9747   virtual ~ViewerTest_AISManipulator()
9748   {
9749     GetMapOfAISManipulators().Remove (this);
9750   }
9751
9752   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9753 };
9754
9755 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9756 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9757
9758 //===============================================================================================
9759 //function : VManipulator
9760 //purpose  :
9761 //===============================================================================================
9762 static int VManipulator (Draw_Interpretor& theDi,
9763                          Standard_Integer  theArgsNb,
9764                          const char**      theArgVec)
9765 {
9766   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9767   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9768   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
9769   if (aView.IsNull()
9770    || aViewer.IsNull())
9771   {
9772     std::cerr << "No active viewer!\n";
9773     return 1;
9774   }
9775
9776   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
9777   Standard_Integer anArgIter = 1;
9778   for (; anArgIter < theArgsNb; ++anArgIter)
9779   {
9780     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
9781   }
9782
9783   ViewerTest_CmdParser aCmd;
9784   aCmd.AddDescription ("Manages manipulator for interactive objects:");
9785   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
9786   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
9787   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
9788   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
9789   aCmd.AddOption ("detach",         "...       - detach manipulator");
9790
9791   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
9792   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
9793   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
9794
9795   aCmd.AddOption ("move",   "... x y z - move object");
9796   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
9797   aCmd.AddOption ("scale",  "... factor - scale object");
9798
9799   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
9800   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
9801   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
9802   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
9803   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
9804   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
9805   aCmd.AddOption ("size",              "... size - set size of manipulator");
9806   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
9807
9808   aCmd.Parse (theArgsNb, theArgVec);
9809
9810   if (aCmd.HasOption ("help"))
9811   {
9812     theDi.PrintHelp (theArgVec[0]);
9813     return 0;
9814   }
9815
9816   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
9817
9818   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
9819
9820   if (aName.IsEmpty())
9821   {
9822     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
9823     return 1;
9824   }
9825
9826   // ----------------------------------
9827   // detach existing manipulator object
9828   // ----------------------------------
9829
9830   if (aCmd.HasOption ("detach"))
9831   {
9832     if (!aMapAIS.IsBound2 (aName))
9833     {
9834       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
9835       return 1;
9836     }
9837
9838     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9839     if (aManipulator.IsNull())
9840     {
9841       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9842       return 1;
9843     }
9844
9845     aManipulator->Detach();
9846     aMapAIS.UnBind2 (aName);
9847     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
9848
9849     return 0;
9850   }
9851
9852   // -----------------------------------------------
9853   // find or create manipulator if it does not exist
9854   // -----------------------------------------------
9855
9856   Handle(AIS_Manipulator) aManipulator;
9857   if (!aMapAIS.IsBound2 (aName))
9858   {
9859     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
9860
9861     aManipulator = new ViewerTest_AISManipulator();
9862     aMapAIS.Bind (aManipulator, aName);
9863   }
9864   else
9865   {
9866     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
9867     if (aManipulator.IsNull())
9868     {
9869       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
9870       return 1;
9871     }
9872   }
9873
9874   // -----------------------------------------
9875   // change properties of manipulator instance
9876   // -----------------------------------------
9877
9878   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
9879   {
9880     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
9881   }
9882   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
9883   {
9884     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
9885   }
9886   if (aCmd.HasOption ("followRotation", 1, Standard_True))
9887   {
9888     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
9889   }
9890   if (aCmd.HasOption ("gap", 1, Standard_True))
9891   {
9892     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
9893   }
9894   if (aCmd.HasOption ("part", 3, Standard_True))
9895   {
9896     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
9897     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
9898     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
9899     if (aMode < 1 || aMode > 3)
9900     {
9901       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
9902       return 1;
9903     }
9904
9905     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
9906   }
9907   if (aCmd.HasOption ("pos", 3, Standard_True))
9908   {
9909     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
9910     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
9911     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
9912
9913     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
9914   }
9915   if (aCmd.HasOption ("size", 1, Standard_True))
9916   {
9917     aManipulator->SetSize (aCmd.ArgFloat ("size"));
9918   }
9919   if (aCmd.HasOption ("zoomable", 1, Standard_True))
9920   {
9921     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
9922
9923     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
9924     {
9925       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
9926       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
9927     }
9928   }
9929
9930   // ---------------------------------------------------
9931   // attach, detach or access manipulator from an object
9932   // ---------------------------------------------------
9933
9934   if (aCmd.HasOption ("attach"))
9935   {
9936     // Find an object and attach manipulator to it
9937     if (!aCmd.HasOption ("attach", 1, Standard_True))
9938     {
9939       return 1;
9940     }
9941
9942     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
9943     if (!aMapAIS.IsBound2 (anObjName))
9944     {
9945       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
9946       return 1;
9947     }
9948
9949     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
9950     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
9951     for (; anIt.More(); anIt.Next())
9952     {
9953       if (anIt.Value()->IsAttached()
9954        && anIt.Value()->Object() == anObject)
9955       {
9956         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
9957         return 1;
9958       }
9959     }
9960
9961     AIS_Manipulator::OptionsForAttach anOptions;
9962     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
9963     {
9964       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
9965     }
9966     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
9967     {
9968       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
9969     }
9970     if (aCmd.HasOption ("enableModes", 1, Standard_True))
9971     {
9972       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
9973     }
9974
9975     aManipulator->Attach (anObject, anOptions);
9976   }
9977
9978   // --------------------------------------
9979   // apply transformation using manipulator
9980   // --------------------------------------
9981
9982   if (aCmd.HasOption ("startTransform", 2, Standard_True))
9983   {
9984     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
9985   }
9986   if (aCmd.HasOption ("transform", 2, Standard_True))
9987   {
9988     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
9989   }
9990   if (aCmd.HasOption ("stopTransform"))
9991   {
9992     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
9993
9994     aManipulator->StopTransform (toApply);
9995   }
9996
9997   gp_Trsf aT;
9998   if (aCmd.HasOption ("move", 3, Standard_True))
9999   {
10000     aT.SetTranslationPart (aCmd.ArgVec ("move"));
10001   }
10002   if (aCmd.HasOption ("rotate", 7, Standard_True))
10003   {
10004     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
10005   }
10006   if (aCmd.HasOption ("scale", 1))
10007   {
10008     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
10009   }
10010
10011   if (aT.Form() != gp_Identity)
10012   {
10013     aManipulator->Transform (aT);
10014   }
10015
10016   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
10017
10018   return 0;
10019 }
10020
10021 //===============================================================================================
10022 //function : VSelectionProperties
10023 //purpose  :
10024 //===============================================================================================
10025 static int VSelectionProperties (Draw_Interpretor& theDi,
10026                                  Standard_Integer  theArgsNb,
10027                                  const char**      theArgVec)
10028 {
10029   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10030   if (aCtx.IsNull())
10031   {
10032     std::cerr << "No active viewer!\n";
10033     return 1;
10034   }
10035
10036   Standard_Boolean toPrint  = theArgsNb == 1;
10037   Standard_Boolean toRedraw = Standard_False;
10038   Standard_Integer anArgIter = 1;
10039   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10040   if (anArgIter < theArgsNb)
10041   {
10042     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10043     anArgFirst.LowerCase();
10044     ++anArgIter;
10045     if (anArgFirst == "dynhighlight"
10046      || anArgFirst == "dynhilight"
10047      || anArgFirst == "dynamichighlight"
10048      || anArgFirst == "dynamichilight")
10049     {
10050       aType = Prs3d_TypeOfHighlight_Dynamic;
10051     }
10052     else if (anArgFirst == "localdynhighlight"
10053           || anArgFirst == "localdynhilight"
10054           || anArgFirst == "localdynamichighlight"
10055           || anArgFirst == "localdynamichilight")
10056     {
10057       aType = Prs3d_TypeOfHighlight_LocalDynamic;
10058     }
10059     else if (anArgFirst == "selhighlight"
10060           || anArgFirst == "selhilight"
10061           || anArgFirst == "selectedhighlight"
10062           || anArgFirst == "selectedhilight")
10063     {
10064       aType = Prs3d_TypeOfHighlight_Selected;
10065     }
10066     else if (anArgFirst == "localselhighlight"
10067           || anArgFirst == "localselhilight"
10068           || anArgFirst == "localselectedhighlight"
10069           || anArgFirst == "localselectedhilight")
10070     {
10071       aType = Prs3d_TypeOfHighlight_LocalSelected;
10072     }
10073     else
10074     {
10075       --anArgIter;
10076     }
10077   }
10078   for (; anArgIter < theArgsNb; ++anArgIter)
10079   {
10080     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10081     anArg.LowerCase();
10082     if (anArg == "-help")
10083     {
10084       theDi.PrintHelp (theArgVec[0]);
10085       return 0;
10086     }
10087     else if (anArg == "-print")
10088     {
10089       toPrint = Standard_True;
10090     }
10091     else if (anArg == "-autoactivate")
10092     {
10093       Standard_Boolean toEnable = Standard_True;
10094       if (anArgIter + 1 < theArgsNb
10095        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
10096       {
10097         ++anArgIter;
10098       }
10099       aCtx->SetAutoActivateSelection (toEnable);
10100     }
10101     else if (anArg == "-pixtol"
10102           && anArgIter + 1 < theArgsNb)
10103     {
10104       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
10105     }
10106     else if ((anArg == "-mode"
10107            || anArg == "-dispmode")
10108           && anArgIter + 1 < theArgsNb)
10109     {
10110       if (aType == Prs3d_TypeOfHighlight_None)
10111       {
10112         std::cout << "Syntax error: type of highlighting is undefined\n";
10113         return 1;
10114       }
10115
10116       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
10117       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10118       aStyle->SetDisplayMode (aDispMode);
10119       toRedraw = Standard_True;
10120     }
10121     else if (anArg == "-layer"
10122           && anArgIter + 1 < theArgsNb)
10123     {
10124       if (aType == Prs3d_TypeOfHighlight_None)
10125       {
10126         std::cout << "Syntax error: type of highlighting is undefined\n";
10127         return 1;
10128       }
10129
10130       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
10131       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
10132       {
10133         TColStd_SequenceOfInteger aLayers;
10134         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
10135         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
10136         {
10137           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
10138           return 1;
10139         }
10140       }
10141
10142       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10143       aStyle->SetZLayer (aNewLayer);
10144       toRedraw = Standard_True;
10145     }
10146     else if (anArg == "-hicolor"
10147           || anArg == "-selcolor"
10148           || anArg == "-color")
10149     {
10150       if (anArg.StartsWith ("-hi"))
10151       {
10152         aType = Prs3d_TypeOfHighlight_Dynamic;
10153       }
10154       else if (anArg.StartsWith ("-sel"))
10155       {
10156         aType = Prs3d_TypeOfHighlight_Selected;
10157       }
10158       else if (aType == Prs3d_TypeOfHighlight_None)
10159       {
10160         std::cout << "Syntax error: type of highlighting is undefined\n";
10161         return 1;
10162       }
10163
10164       Quantity_Color aColor;
10165       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
10166                                                            theArgVec + anArgIter + 1,
10167                                                            aColor);
10168       if (aNbParsed == 0)
10169       {
10170         std::cout << "Syntax error: need more arguments.\n";
10171         return 1;
10172       }
10173       anArgIter += aNbParsed;
10174
10175       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10176       aStyle->SetColor (aColor);
10177       toRedraw = Standard_True;
10178     }
10179     else if ((anArg == "-transp"
10180            || anArg == "-transparency"
10181            || anArg == "-hitransp"
10182            || anArg == "-seltransp"
10183            || anArg == "-hitransplocal"
10184            || anArg == "-seltransplocal")
10185           && anArgIter + 1 < theArgsNb)
10186     {
10187       if (anArg.StartsWith ("-hi"))
10188       {
10189         aType = Prs3d_TypeOfHighlight_Dynamic;
10190       }
10191       else if (anArg.StartsWith ("-sel"))
10192       {
10193         aType = Prs3d_TypeOfHighlight_Selected;
10194       }
10195       else if (aType == Prs3d_TypeOfHighlight_None)
10196       {
10197         std::cout << "Syntax error: type of highlighting is undefined\n";
10198         return 1;
10199       }
10200
10201       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
10202       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10203       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
10204       toRedraw = Standard_True;
10205     }
10206     else if ((anArg == "-mat"
10207            || anArg == "-material")
10208           && anArgIter + 1 < theArgsNb)
10209     {
10210       if (aType == Prs3d_TypeOfHighlight_None)
10211       {
10212         std::cout << "Syntax error: type of highlighting is undefined\n";
10213         return 1;
10214       }
10215
10216       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10217       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
10218       if (aMatName != Graphic3d_NOM_DEFAULT)
10219       {
10220         ++anArgIter;
10221         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
10222         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
10223         Graphic3d_MaterialAspect aMat (aMatName);
10224         aMat.SetColor (aStyle->Color());
10225         aMat.SetTransparency (aStyle->Transparency());
10226         anAspect->SetFrontMaterial (aMat);
10227         anAspect->SetInteriorColor (aStyle->Color());
10228         aStyle->SetBasicFillAreaAspect (anAspect);
10229       }
10230       else
10231       {
10232         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
10233       }
10234       toRedraw = Standard_True;
10235     }
10236     else
10237     {
10238       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
10239     }
10240   }
10241
10242   if (toPrint)
10243   {
10244     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
10245     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
10246     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
10247     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
10248     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
10249     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
10250     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
10251     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
10252     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
10253     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
10254     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
10255     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
10256   }
10257
10258   if (aCtx->NbSelected() != 0 && toRedraw)
10259   {
10260     aCtx->HilightSelected (Standard_True);
10261   }
10262
10263   return 0;
10264 }
10265
10266 //===============================================================================================
10267 //function : VDumpSelectionImage
10268 //purpose  :
10269 //===============================================================================================
10270 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
10271                                 Standard_Integer  theArgsNb,
10272                                 const char**      theArgVec)
10273 {
10274   if (theArgsNb < 2)
10275   {
10276     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
10277     return 1;
10278   }
10279
10280   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
10281   if (aContext.IsNull())
10282   {
10283     std::cout << "Error: no active view.\n";
10284     return 1;
10285   }
10286
10287   TCollection_AsciiString aFile;
10288   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10289   Image_PixMap::ImgFormat anImgFormat = Image_PixMap::ImgBGR;
10290   Standard_Integer aPickedIndex = 1;
10291   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10292   {
10293     TCollection_AsciiString aParam (theArgVec[anArgIter]);
10294     aParam.LowerCase();
10295     if (aParam == "-type")
10296     {
10297       if (++anArgIter >= theArgsNb)
10298       {
10299         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
10300         return 1;
10301       }
10302
10303       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10304       aValue.LowerCase();
10305       if (aValue == "depth"
10306        || aValue == "normdepth"
10307        || aValue == "normalizeddepth")
10308       {
10309         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10310         anImgFormat = Image_PixMap::ImgGrayF;
10311       }
10312       if (aValue == "depthinverted"
10313        || aValue == "normdepthinverted"
10314        || aValue == "normalizeddepthinverted"
10315        || aValue == "inverted")
10316       {
10317         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
10318         anImgFormat = Image_PixMap::ImgGrayF;
10319       }
10320       else if (aValue == "unnormdepth"
10321             || aValue == "unnormalizeddepth")
10322       {
10323         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
10324         anImgFormat = Image_PixMap::ImgGrayF;
10325       }
10326       else if (aValue == "objectcolor"
10327             || aValue == "object"
10328             || aValue == "color")
10329       {
10330         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
10331       }
10332       else if (aValue == "entitycolor"
10333             || aValue == "entity")
10334       {
10335         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
10336       }
10337       else if (aValue == "ownercolor"
10338             || aValue == "owner")
10339       {
10340         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
10341       }
10342       else if (aValue == "selectionmodecolor"
10343             || aValue == "selectionmode"
10344             || aValue == "selmodecolor"
10345             || aValue == "selmode")
10346       {
10347         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
10348       }
10349     }
10350     else if (aParam == "-picked"
10351           || aParam == "-pickeddepth"
10352           || aParam == "-pickedindex")
10353     {
10354       if (++anArgIter >= theArgsNb)
10355       {
10356         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
10357         return 1;
10358       }
10359
10360       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
10361     }
10362     else if (aFile.IsEmpty())
10363     {
10364       aFile = theArgVec[anArgIter];
10365     }
10366     else
10367     {
10368       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
10369       return 1;
10370     }
10371   }
10372   if (aFile.IsEmpty())
10373   {
10374     std::cout << "Syntax error: image file name is missing.\n";
10375     return 1;
10376   }
10377
10378   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
10379   Standard_Integer aWidth = 0, aHeight = 0;
10380   aView->Window()->Size (aWidth, aHeight);
10381
10382   Image_AlienPixMap aPixMap;
10383   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
10384   {
10385     std::cout << "Error: can't allocate image.\n";
10386     return 1;
10387   }
10388   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
10389   {
10390     std::cout << "Error: can't generate selection image.\n";
10391     return 1;
10392   }
10393   if (!aPixMap.Save (aFile))
10394   {
10395     std::cout << "Error: can't save selection image.\n";
10396     return 0;
10397   }
10398   return 0;
10399 }
10400
10401 //=======================================================================
10402 //function : ViewerCommands
10403 //purpose  :
10404 //=======================================================================
10405
10406 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
10407 {
10408
10409   const char *group = "ZeViewer";
10410   theCommands.Add("vinit",
10411 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10412     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10413 #else
10414     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10415 #endif
10416     " - Creates new View window with specified name view_name.\n"
10417     "By default the new view is created in the viewer and in"
10418     " graphic driver shared with active view.\n"
10419     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
10420     "If driverName isn't specified the driver will be shared with active view.\n"
10421     "If viewerName isn't specified the viewer will be shared with active view.\n"
10422 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10423     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
10424     "is used in creation of graphic driver\n"
10425 #endif
10426     " - l, t: pixel position of left top corner of the window\n"
10427     " - w,h: width and heigth of window respectively.\n"
10428     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
10429     __FILE__,VInit,group);
10430   theCommands.Add("vclose" ,
10431     "[view_id [keep_context=0|1]]\n"
10432     "or vclose ALL - to remove all created views\n"
10433     " - removes view(viewer window) defined by its view_id.\n"
10434     " - keep_context: by default 0; if 1 and the last view is deleted"
10435     " the current context is not removed.",
10436     __FILE__,VClose,group);
10437   theCommands.Add("vactivate" ,
10438     "view_id"
10439     " - activates view(viewer window) defined by its view_id",
10440     __FILE__,VActivate,group);
10441   theCommands.Add("vviewlist",
10442     "vviewlist [format={tree, long}]"
10443     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
10444     " - format: format of result output, if tree the output is a tree view;"
10445     "otherwise it's a list of full view names. By default format = tree",
10446     __FILE__,VViewList,group);
10447   theCommands.Add("vhelp" ,
10448     "vhelp            : display help on the viewer commands",
10449     __FILE__,VHelp,group);
10450   theCommands.Add("vtop" ,
10451     "vtop or <T>      : Top view. Orientation +X+Y" ,
10452     __FILE__,VTop,group);
10453   theCommands.Add("vbottom" ,
10454     "vbottom          : Bottom view. Orientation +X-Y" ,
10455     __FILE__,VBottom,group);
10456   theCommands.Add("vleft" ,
10457     "vleft            : Left view. Orientation -Y+Z" ,
10458     __FILE__,VLeft,group);
10459   theCommands.Add("vright" ,
10460     "vright           : Right view. Orientation +Y+Z" ,
10461     __FILE__,VRight,group);
10462   theCommands.Add("vaxo" ,
10463     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
10464     __FILE__,VAxo,group);
10465   theCommands.Add("vfront" ,
10466     "vfront           : Front view. Orientation +X+Z" ,
10467     __FILE__,VFront,group);
10468   theCommands.Add("vback" ,
10469     "vback            : Back view. Orientation -X+Z" ,
10470     __FILE__,VBack,group);
10471   theCommands.Add("vpick" ,
10472     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
10473     VPick,group);
10474   theCommands.Add("vfit",
10475     "vfit or <F> [-selected] [-noupdate]"
10476     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
10477     __FILE__,VFit,group);
10478   theCommands.Add ("vfitarea",
10479     "vfitarea x1 y1 x2 y2"
10480     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
10481     "\n\t\t: Fit view to show area located between two points"
10482     "\n\t\t: given in world 2D or 3D corrdinates.",
10483     __FILE__, VFitArea, group);
10484   theCommands.Add ("vzfit", "vzfit [scale]\n"
10485     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
10486     "   \"scale\" - specifies factor to scale computed z range.\n",
10487     __FILE__, VZFit, group);
10488   theCommands.Add("vrepaint",
10489     "vrepaint        : vrepaint, force redraw",
10490     __FILE__,VRepaint,group);
10491   theCommands.Add("vclear",
10492     "vclear          : vclear"
10493     "\n\t\t: remove all the object from the viewer",
10494     __FILE__,VClear,group);
10495   theCommands.Add("vsetbg",
10496     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
10497     __FILE__,VSetBg,group);
10498   theCommands.Add("vsetbgmode",
10499     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
10500     __FILE__,VSetBgMode,group);
10501   theCommands.Add("vsetgradientbg",
10502     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
10503     __FILE__,VSetGradientBg,group);
10504   theCommands.Add("vsetgrbgmode",
10505     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
10506     __FILE__,VSetGradientBgMode,group);
10507   theCommands.Add("vsetcolorbg",
10508     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
10509     __FILE__,VSetColorBg,group);
10510   theCommands.Add("vsetdefaultbg",
10511     "vsetdefaultbg r g b\n"
10512     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
10513     "\n\t\t: Set default viewer background fill color (flat/gradient).",
10514     __FILE__,VSetDefaultBg,group);
10515   theCommands.Add("vscale",
10516     "vscale          : vscale X Y Z",
10517     __FILE__,VScale,group);
10518   theCommands.Add("vzbufftrihedron",
10519             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
10520     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
10521     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
10522     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
10523     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
10524     "\n\t\t: Displays a trihedron",
10525     __FILE__,VZBuffTrihedron,group);
10526   theCommands.Add("vrotate",
10527     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
10528     "\n                : Option -mouseStart starts rotation according to the mouse position"
10529     "\n                : Option -mouseMove continues rotation with angle computed"
10530     "\n                : from last and new mouse position."
10531     "\n                : vrotate AX AY AZ [X Y Z]",
10532     __FILE__,VRotate,group);
10533   theCommands.Add("vzoom",
10534     "vzoom           : vzoom coef",
10535     __FILE__,VZoom,group);
10536   theCommands.Add("vpan",
10537     "vpan            : vpan dx dy",
10538     __FILE__,VPan,group);
10539   theCommands.Add("vexport",
10540     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
10541     " : exports the view to a vector file of a given format"
10542     " : notice that EMF format requires patched gl2ps",
10543     __FILE__,VExport,group);
10544   theCommands.Add("vcolorscale",
10545     "vcolorscale name [-noupdate|-update] [-demo]"
10546     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
10547     "\n\t\t:       [-font HeightFont=20]"
10548     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
10549     "\n\t\t:       [-smoothTransition {on|off}=off]"
10550     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
10551     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
10552     "\n\t\t:       [-textpos {left|right|center|none}=right]"
10553     "\n\t\t:       [-labelAtBorder {on|off}=on]"
10554     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
10555     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
10556     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
10557     "\n\t\t:       [-xy Left=0 Bottom=0]"
10558     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
10559     "\n\t\t:  -colors   - set colors for all intervals"
10560     "\n\t\t:  -color    - set color for specific interval"
10561     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
10562     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
10563     "\n\t\t:              at border means the value inbetween neighbor intervals,"
10564     "\n\t\t:              at center means the center value within current interval"
10565     "\n\t\t:  -labels   - set labels for all intervals"
10566     "\n\t\t:  -freeLabels - same as -labels but does not require"
10567     "\n\t\t:              matching the number of intervals"
10568     "\n\t\t:  -label    - set label for specific interval"
10569     "\n\t\t:  -title    - set title"
10570     "\n\t\t:  -reversed - setup smooth color transition between intervals"
10571     "\n\t\t:  -smoothTransition - swap colorscale direction"
10572     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
10573     __FILE__, VColorScale, group);
10574   theCommands.Add("vgraduatedtrihedron",
10575     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
10576     "\t[-namefont Name] [-valuesfont Name]\n"
10577     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
10578     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
10579     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
10580     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
10581     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
10582     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
10583     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
10584     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
10585     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
10586     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
10587     " - Displays or erases graduated trihedron"
10588     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
10589     " - namefont - font of axes names. Default: Arial\n"
10590     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
10591     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
10592     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
10593     " - valuesfont - font of axes values. Default: Arial\n"
10594     " - xcolor, ycolor, zcolor - color of axis and values\n"
10595     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
10596     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
10597     __FILE__,VGraduatedTrihedron,group);
10598   theCommands.Add("vtile" ,
10599             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
10600     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
10601     "\n\t\t:  -totalSize the size of virtual bigger viewport"
10602     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
10603     "\n\t\t:  -lowerLeft tile offset as lower left corner"
10604     "\n\t\t:  -upperLeft tile offset as upper left corner",
10605     __FILE__, VTile, group);
10606   theCommands.Add("vzlayer",
10607               "vzlayer [layerId]"
10608       "\n\t\t:         [-add|-delete|-get|-settings]"
10609       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
10610       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
10611       "\n\t\t: ZLayer list management:"
10612       "\n\t\t:   -add      add new z layer to viewer and print its id"
10613       "\n\t\t:   -delete   delete z layer"
10614       "\n\t\t:   -get      print sequence of z layers"
10615       "\n\t\t:   -settings print status of z layer settings"
10616       "\n\t\t:   -disable  disables given setting"
10617       "\n\t\t:   -enable   enables  given setting",
10618     __FILE__,VZLayer,group);
10619   theCommands.Add("vlayerline",
10620     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
10621     __FILE__,VLayerLine,group);
10622   theCommands.Add ("vgrid",
10623     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
10624     " : Mode - rectangular or circular"
10625     " : Type - lines or points",
10626     __FILE__, VGrid, group);
10627   theCommands.Add ("vpriviledgedplane",
10628     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
10629     "\n\t\t:   Ox, Oy, Oz - plane origin"
10630     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
10631     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
10632     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
10633     __FILE__, VPriviledgedPlane, group);
10634   theCommands.Add ("vconvert",
10635     "vconvert v [Mode={window|view}]"
10636     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
10637     "\n\t\t: vconvert x y z [Mode={window|grid}]"
10638     "\n\t\t:   window - convert to window coordinates, pixels"
10639     "\n\t\t:   view   - convert to view projection plane"
10640     "\n\t\t:   grid   - convert to model coordinates, given on grid"
10641     "\n\t\t:   ray    - convert projection ray to model coordiantes"
10642     "\n\t\t: - vconvert v window : convert view to window;"
10643     "\n\t\t: - vconvert v view   : convert window to view;"
10644     "\n\t\t: - vconvert x y window : convert view to window;"
10645     "\n\t\t: - vconvert x y view : convert window to view;"
10646     "\n\t\t: - vconvert x y : convert window to model;"
10647     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
10648     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
10649     "\n\t\t: - vconvert x y z window : convert model to window;"
10650     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
10651     "\n\t\t: Converts the given coordinates to window/view/model space.",
10652     __FILE__, VConvert, group);
10653   theCommands.Add ("vfps",
10654     "vfps [framesNb=100] : estimate average frame rate for active view",
10655     __FILE__, VFps, group);
10656   theCommands.Add ("vgldebug",
10657             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
10658     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
10659     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
10660     "\n\t\t: Debug context can be requested only on Windows"
10661     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
10662     "\n\t\t:  -sync     - request synchronized debug GL context"
10663     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
10664     "\n\t\t:              which are suppressed by default,"
10665     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
10666     "\n\t\t:              which are suppressed by default",
10667     __FILE__, VGlDebug, group);
10668   theCommands.Add ("vvbo",
10669     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
10670     __FILE__, VVbo, group);
10671   theCommands.Add ("vstereo",
10672             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
10673     "\n\t\t:         [-anaglyph Filter]"
10674     "\n\t\t: Control stereo output mode. Available modes for -mode:"
10675     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
10676     "\n\t\t:                     requires driver support."
10677     "\n\t\t:                     Should be called BEFORE vinit!"
10678     "\n\t\t:  anaglyph         - Anaglyph glasses"
10679     "\n\t\t:  rowInterlaced    - row-interlaced display"
10680     "\n\t\t:  columnInterlaced - column-interlaced display"
10681     "\n\t\t:  chessBoard       - chess-board output"
10682     "\n\t\t:  sideBySide       - horizontal pair"
10683     "\n\t\t:  overUnder        - vertical   pair"
10684     "\n\t\t: Available Anaglyph filters for -anaglyph:"
10685     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
10686     "\n\t\t:  greenMagentaSimple",
10687     __FILE__, VStereo, group);
10688   theCommands.Add ("vcaps",
10689             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
10690     "\n\t\t:       [-compatibleProfile {0|1}]"
10691     "\n\t\t:       [-vsync {0|1}]"
10692     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
10693     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
10694     "\n\t\t: Modify particular graphic driver options:"
10695     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
10696     "\n\t\t:             built-in GLSL programs"
10697     "\n\t\t:            (requires compatible profile)"
10698     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
10699     "\n\t\t:             arrays to GPU memory)"
10700     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
10701     "\n\t\t:  vsync    - switch VSync on or off"
10702     "\n\t\t: Context creation options:"
10703     "\n\t\t:  softMode          - software OpenGL implementation"
10704     "\n\t\t:  compatibleProfile - backward-compatible profile"
10705     "\n\t\t:  quadbuffer        - QuadBuffer"
10706     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
10707     "\n\t\t: rendering paths producing the same visual result when"
10708     "\n\t\t: possible."
10709     "\n\t\t: Command is intended for testing old hardware compatibility.",
10710     __FILE__, VCaps, group);
10711   theCommands.Add ("vmemgpu",
10712     "vmemgpu [f]: print system-dependent GPU memory information if available;"
10713     " with f option returns free memory in bytes",
10714     __FILE__, VMemGpu, group);
10715   theCommands.Add ("vreadpixel",
10716     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
10717     " : Read pixel value for active view",
10718     __FILE__, VReadPixel, group);
10719   theCommands.Add("diffimage",
10720     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
10721     __FILE__, VDiffImage, group);
10722   theCommands.Add ("vselect",
10723     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
10724     "- emulates different types of selection:\n"
10725     "- 1) single click selection\n"
10726     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
10727     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
10728     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
10729     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
10730     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
10731     " (partial inclusion - overlap - is not allowed by default)\n"
10732     "- 5) any of these selections with shift button pressed",
10733     __FILE__, VSelect, group);
10734   theCommands.Add ("vmoveto",
10735     "vmoveto x y"
10736     "- emulates cursor movement to pixel postion (x,y)",
10737     __FILE__, VMoveTo, group);
10738   theCommands.Add ("vviewparams",
10739               "vviewparams [-args] [-scale [s]]"
10740       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
10741       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
10742       "\n\t\t: Manage current view parameters or prints all"
10743       "\n\t\t: current values when called without argument."
10744       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
10745       "\n\t\t:   -eye  [x y z] prints or sets eye location"
10746       "\n\t\t:   -at   [x y z] prints or sets center of look"
10747       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
10748       "\n\t\t:   -proj [x y z] prints or sets direction of look"
10749       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
10750       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
10751       "\n\t\t:                 or changes the size of its maximum dimension"
10752       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
10753     __FILE__, VViewParams, group);
10754
10755   theCommands.Add("vanimation", "Alias for vanim",
10756     __FILE__, VAnimation, group);
10757
10758   theCommands.Add("vanim",
10759             "List existing animations:"
10760     "\n\t\t:  vanim"
10761     "\n\t\t: Animation playback:"
10762     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
10763     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
10764     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
10765     "\n\t\t:   -freeLook skip camera animations"
10766     "\n\t\t:   -lockLoop disable any interactions"
10767     "\n\t\t:"
10768     "\n\t\t: Animation definition:"
10769     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
10770     "\n\t\t:        [start TimeSec] [duration TimeSec]"
10771     "\n\t\t:"
10772     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
10773     "\n\t\t: specifies nested animations."
10774     "\n\t\t: There is no syntax to explicitly add new animation,"
10775     "\n\t\t: and all non-existing animations within the name will be"
10776     "\n\t\t: implicitly created on first use (including parents)."
10777     "\n\t\t:"
10778     "\n\t\t: Each animation might define the SINGLE action (see below),"
10779     "\n\t\t: like camera transition, object transformation or custom callback."
10780     "\n\t\t: Child animations can be used for defining concurrent actions."
10781     "\n\t\t:"
10782     "\n\t\t: Camera animation:"
10783     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
10784     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
10785     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
10786     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
10787     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
10788     "\n\t\t:   -atX    camera Center positions pair"
10789     "\n\t\t:   -upX    camera Up directions pair"
10790     "\n\t\t:   -scaleX camera Scale factors pair"
10791     "\n\t\t: Object animation:"
10792     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
10793     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
10794     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
10795     "\n\t\t:   -locX   object Location points pair (translation)"
10796     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
10797     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
10798     "\n\t\t: Custom callback:"
10799     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
10800     "\n\t\t:   %Pts        overall animation presentation timestamp"
10801     "\n\t\t:   %LocalPts   local animation timestamp"
10802     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
10803     __FILE__, VAnimation, group);
10804
10805   theCommands.Add("vchangeselected",
10806     "vchangeselected shape"
10807     "- adds to shape to selection or remove one from it",
10808                 __FILE__, VChangeSelected, group);
10809   theCommands.Add ("vnbselected",
10810     "vnbselected"
10811     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
10812   theCommands.Add ("vcamera",
10813               "vcamera [-ortho] [-projtype]"
10814       "\n\t\t:         [-persp]"
10815       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
10816       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
10817       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
10818       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
10819       "\n\t\t: Manage camera parameters."
10820       "\n\t\t: Prints current value when option called without argument."
10821       "\n\t\t: Orthographic camera:"
10822       "\n\t\t:   -ortho      activate orthographic projection"
10823       "\n\t\t: Perspective camera:"
10824       "\n\t\t:   -persp      activate perspective  projection (mono)"
10825       "\n\t\t:   -fovy       field of view in y axis, in degrees"
10826       "\n\t\t:   -distance   distance of eye from camera center"
10827       "\n\t\t: Stereoscopic camera:"
10828       "\n\t\t:   -stereo     perspective  projection (stereo)"
10829       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
10830       "\n\t\t:   -rightEye   perspective  projection (right eye)"
10831       "\n\t\t:   -iod        intraocular distance value"
10832       "\n\t\t:   -iodType    distance type, absolute or relative"
10833       "\n\t\t:   -zfocus     stereographic focus value"
10834       "\n\t\t:   -zfocusType focus type, absolute or relative",
10835     __FILE__, VCamera, group);
10836   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
10837     "- vautozfit [on={1|0}] [scale]\n"
10838     "    Prints or changes parameters of automatic z-fit mode:\n"
10839     "   \"on\" - turns automatic z-fit on or off\n"
10840     "   \"scale\" - specifies factor to scale computed z range.\n",
10841     __FILE__, VAutoZFit, group);
10842   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
10843     "   vzrange                - without parameters shows current values\n"
10844     "   vzrange [znear] [zfar] - applies provided values to view",
10845     __FILE__,VZRange, group);
10846   theCommands.Add ("vpurgedisplay",
10847     "vpurgedisplay"
10848     "- removes structures which don't belong to objects displayed in neutral point",
10849     __FILE__, VPurgeDisplay, group);
10850   theCommands.Add("vsetviewsize",
10851     "vsetviewsize size",
10852     __FILE__,VSetViewSize,group);
10853   theCommands.Add("vmoveview",
10854     "vmoveview Dx Dy Dz [Start = 1|0]",
10855     __FILE__,VMoveView,group);
10856   theCommands.Add("vtranslateview",
10857     "vtranslateview Dx Dy Dz [Start = 1|0)]",
10858     __FILE__,VTranslateView,group);
10859   theCommands.Add("vturnview",
10860     "vturnview Ax Ay Az [Start = 1|0]",
10861     __FILE__,VTurnView,group);
10862   theCommands.Add("vtextureenv",
10863     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
10864     "or user-defined file and optionally applying texture mapping parameters\n"
10865     "                  Usage:\n"
10866     "                  vtextureenv off - disables environment mapping\n"
10867     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
10868     "                              std_texture = (0..7)\n"
10869     "                              rep         = {clamp|repeat}\n"
10870     "                              mod         = {decal|modulate}\n"
10871     "                              flt         = {nearest|bilinear|trilinear}\n"
10872     "                              ss, st      - scale factors for s and t texture coordinates\n"
10873     "                              ts, tt      - translation for s and t texture coordinates\n"
10874     "                              rot         - texture rotation angle in degrees",
10875     __FILE__, VTextureEnv, group);
10876   theCommands.Add("vhlr" ,
10877     "is_enabled={on|off} [show_hidden={1|0}]"
10878     " - Hidden line removal algorithm:"
10879     " - is_enabled: if is on HLR algorithm is applied\n"
10880     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
10881     __FILE__,VHLR,group);
10882   theCommands.Add("vhlrtype" ,
10883     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
10884     " - Changes the type of HLR algorithm using for shapes."
10885     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
10886     "   if equals to polyalgo, polygonal HLR algorithm is applied."
10887     "If shapes are not given HLR algoithm of given type is applied"
10888     " to all shapes in the view\n",
10889     __FILE__,VHLRType,group);
10890   theCommands.Add("vclipplane",
10891               "vclipplane planeName [{0|1}]"
10892       "\n\t\t:   [-equation A B C D]"
10893       "\n\t\t:   [-set|-unset [objects|views]]"
10894       "\n\t\t:   [-maxPlanes]"
10895       "\n\t\t:   [-capping {0|1}]"
10896       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
10897       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
10898       "\n\t\t:       [-texRotate Angle]"
10899       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
10900       "\n\t\t:       [-useObjShader {0|1}]"
10901       "\n\t\t: Clipping planes management:"
10902       "\n\t\t:   -maxPlanes   print plane limit for view"
10903       "\n\t\t:   -delete      delete plane with given name"
10904       "\n\t\t:   {off|on|0|1} turn clipping on/off"
10905       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
10906       "\n\t\t:                applied to active View when list is omitted"
10907       "\n\t\t:   -equation A B C D change plane equation"
10908       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
10909       "\n\t\t: Capping options:"
10910       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
10911       "\n\t\t:   -color R G B          set capping color"
10912       "\n\t\t:   -texName Texture      set capping texture"
10913       "\n\t\t:   -texScale SX SY       set capping tex scale"
10914       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
10915       "\n\t\t:   -texRotate Angle      set capping tex rotation"
10916       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
10917       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
10918       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
10919       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
10920       __FILE__, VClipPlane, group);
10921   theCommands.Add("vdefaults",
10922                "vdefaults [-absDefl value]"
10923        "\n\t\t:           [-devCoeff value]"
10924        "\n\t\t:           [-angDefl value]"
10925        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
10926     , __FILE__, VDefaults, group);
10927   theCommands.Add("vlight",
10928     "tool to manage light sources, without arguments shows list of lights."
10929     "\n    Main commands: "
10930     "\n      'clear' to clear lights"
10931     "\n      '{def}aults' to load deafault lights"
10932     "\n      'add' (or 'new') <type> to add any light source"
10933     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
10934     "\n      'change' <lightId> to edit light source with specified lightId"
10935     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
10936     "\n        {pos}ition X Y Z"
10937     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
10938     "\n        color colorName"
10939     "\n        {head}light 0|1"
10940     "\n        {sm}oothness value"
10941     "\n        {int}ensity value"
10942     "\n        {constAtten}uation value"
10943     "\n        {linearAtten}uation value"
10944     "\n        angle angleDeg"
10945     "\n        {spotexp}onent value"
10946     "\n        local|global"
10947     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
10948     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
10949     __FILE__, VLight, group);
10950   theCommands.Add("vraytrace",
10951             "vraytrace [0|1]"
10952     "\n\t\t: Turns on/off ray-tracing renderer."
10953     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
10954     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
10955     __FILE__, VRenderParams, group);
10956   theCommands.Add("vrenderparams",
10957     "\n    Manages rendering parameters: "
10958     "\n      '-raster'                Disables GPU ray-tracing"
10959     "\n      '-msaa         0..4'     Specifies number of samples for MSAA"
10960     "\n      '-rayTrace'              Enables  GPU ray-tracing"
10961     "\n      '-rayDepth     0..10'    Defines maximum ray-tracing depth"
10962     "\n      '-shadows      on|off'   Enables/disables shadows rendering"
10963     "\n      '-reflections  on|off'   Enables/disables specular reflections"
10964     "\n      '-fsaa         on|off'   Enables/disables adaptive anti-aliasing"
10965     "\n      '-gleam        on|off'   Enables/disables transparency shadow effects"
10966     "\n      '-gi           on|off'   Enables/disables global illumination effects"
10967     "\n      '-brng         on|off'   Enables/disables blocked RNG (fast coherent PT)"
10968     "\n      '-env          on|off'   Enables/disables environment map background"
10969     "\n      '-twoside      on|off'   Enables/disables two-sided BSDF models (PT mode)"
10970     "\n      '-iss          on|off'   Enables/disables adaptive screen sampling (PT mode)"
10971     "\n      '-issd         on|off'   Shows screen sampling distribution in ISS mode"
10972     "\n      '-maxrad       > 0.0'    Value used for clamping radiance estimation (PT mode)"
10973     "\n      '-nbtiles      64..1024' Specifies number of screen tiles in ISS mode"
10974     "\n      '-rebuildGlsl  on|off'   Rebuild Ray-Tracing GLSL programs (for debugging)"
10975     "\n      '-shadingModel model'    Controls shading model from enumeration"
10976     "\n                               color, flat, gouraud, phong"
10977     "\n      '-resolution   value'    Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
10978     "\n    Unlike vcaps, these parameters dramatically change visual properties."
10979     "\n    Command is intended to control presentation quality depending on"
10980     "\n    hardware capabilities and performance.",
10981     __FILE__, VRenderParams, group);
10982   theCommands.Add("vfrustumculling",
10983     "vfrustumculling [toEnable]: enables/disables objects clipping",
10984     __FILE__,VFrustumCulling,group);
10985   theCommands.Add("vhighlightselected",
10986     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
10987     "Without arguments it shows if highlighting of selected objects is enabled now.",
10988     __FILE__,VHighlightSelected,group);
10989   theCommands.Add ("vplace",
10990             "vplace dx dy"
10991     "\n\t\t: Places the point (in pixels) at the center of the window",
10992     __FILE__, VPlace, group);
10993   theCommands.Add("vxrotate",
10994     "vxrotate",
10995     __FILE__,VXRotate,group);
10996
10997     theCommands.Add("vmanipulator",
10998       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
10999       "\n    tool to create and manage AIS manipulators."
11000       "\n    Options: "
11001       "\n      '-attach AISObject'                 attach manipulator to AISObject"
11002       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
11003       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
11004       "\n      '-enableModes    {0|1}'             enable modes when attaching"
11005       "\n      '-detach'                           detach manipulator"
11006       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
11007       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
11008       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
11009       "\n      '-move x y z'                     - move attached object"
11010       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
11011       "\n      '-scale factor'                   - scale attached object"
11012       "\n      '-autoActivate      {0|1}'        - set activation on detection"
11013       "\n      '-followTranslation {0|1}'        - set following translation transform"
11014       "\n      '-followRotation    {0|1}'        - set following rotation transform"
11015       "\n      '-gap value'                      - set gap between sub-parts"
11016       "\n      '-part axis mode    {0|1}'        - set visual part"
11017       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
11018       "\n      '-size value'                     - set size of manipulator"
11019       "\n      '-zoomable {0|1}'                 - set zoom persistence",
11020     __FILE__, VManipulator, group);
11021
11022   theCommands.Add("vselprops",
11023     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
11024     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
11025     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
11026     "\n    -pixTol    value        : sets up pixel tolerance"
11027     "\n    -dispMode  dispMode     : sets display mode for highlighting"
11028     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
11029     "\n    -color     {name|r g b} : sets highlight color"
11030     "\n    -transp    value        : sets transparency coefficient for highlight"
11031     "\n    -material  material     : sets highlight material"
11032     "\n    -print                  : prints current state of all mentioned parameters",
11033     __FILE__, VSelectionProperties, group);
11034
11035   theCommands.Add ("vseldump",
11036                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
11037                    "\n\t\t: Generate an image based on detection results:"
11038                    "\n\t\t:   depth       normalized depth values"
11039                    "\n\t\t:   unnormDepth unnormalized depth values"
11040                    "\n\t\t:   object      color of detected object"
11041                    "\n\t\t:   owner       color of detected owner"
11042                    "\n\t\t:   selMode     color of selection mode"
11043                    "\n\t\t:   entity      color of etected entity",
11044                    __FILE__, VDumpSelectionImage, group);
11045
11046 #if defined(_WIN32)
11047   theCommands.Add("vprogressive",
11048     "vprogressive",
11049     __FILE__, VProgressiveMode, group);
11050 #endif
11051 }