6992046e1fa7fed6cb67b02e91e4587acfda3f55
[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 #include <AIS_ColorScale.hxx>
19 #include <AIS_Manipulator.hxx>
20 #include <AIS_RubberBand.hxx>
21 #include <AIS_Shape.hxx>
22 #include <AIS_InteractiveObject.hxx>
23 #include <AIS_ListOfInteractive.hxx>
24 #include <AIS_ListIteratorOfListOfInteractive.hxx>
25 #include <DBRep.hxx>
26 #include <Graphic3d_ArrayOfPolylines.hxx>
27 #include <Graphic3d_AspectMarker3d.hxx>
28 #include <Graphic3d_ExportFormat.hxx>
29 #include <Graphic3d_NameOfTextureEnv.hxx>
30 #include <Graphic3d_GraduatedTrihedron.hxx>
31 #include <Graphic3d_TextureEnv.hxx>
32 #include <Graphic3d_TextureParams.hxx>
33 #include <Graphic3d_TypeOfTextureFilter.hxx>
34 #include <Graphic3d_AspectFillArea3d.hxx>
35 #include <ViewerTest.hxx>
36 #include <ViewerTest_AutoUpdater.hxx>
37 #include <ViewerTest_EventManager.hxx>
38 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
39 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
40 #include <ViewerTest_CmdParser.hxx>
41 #include <V3d_AmbientLight.hxx>
42 #include <V3d_DirectionalLight.hxx>
43 #include <V3d_PositionalLight.hxx>
44 #include <V3d_SpotLight.hxx>
45 #include <NCollection_DoubleMap.hxx>
46 #include <NCollection_List.hxx>
47 #include <NCollection_Vector.hxx>
48 #include <AIS_InteractiveContext.hxx>
49 #include <Draw_Interpretor.hxx>
50 #include <Draw.hxx>
51 #include <Draw_Appli.hxx>
52 #include <Image_AlienPixMap.hxx>
53 #include <OpenGl_GraphicDriver.hxx>
54 #include <OSD_Timer.hxx>
55 #include <TColStd_HSequenceOfAsciiString.hxx>
56 #include <TColStd_SequenceOfInteger.hxx>
57 #include <TColStd_HSequenceOfReal.hxx>
58 #include <TColgp_Array1OfPnt2d.hxx>
59 #include <TColStd_MapOfAsciiString.hxx>
60 #include <Aspect_TypeOfLine.hxx>
61 #include <Image_Diff.hxx>
62 #include <Aspect_DisplayConnection.hxx>
63 #include <gp_Pnt.hxx>
64 #include <gp_Dir.hxx>
65 #include <gp_Pln.hxx>
66 #include <PrsMgr_PresentableObject.hxx>
67 #include <Graphic3d_ClipPlane.hxx>
68 #include <NCollection_DataMap.hxx>
69 #include <Graphic3d_Texture2Dmanual.hxx>
70 #include <Prs3d_ShadingAspect.hxx>
71 #include <Prs3d_Drawer.hxx>
72 #include <Prs3d_LineAspect.hxx>
73 #include <Prs3d_Root.hxx>
74
75 #ifdef _WIN32
76 #undef DrawText
77 #endif
78
79 #include <cstdlib>
80
81 #if defined(_WIN32)
82   #include <WNT_WClass.hxx>
83   #include <WNT_Window.hxx>
84 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
85   #include <Cocoa_Window.hxx>
86 #else
87   #include <Xw_Window.hxx>
88   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
89   #include <X11/Xutil.h>
90   #include <tk.h>
91 #endif
92
93 // Auxiliary definitions
94 static const char THE_KEY_DELETE = 127;
95
96 //==============================================================================
97 //  VIEWER GLOBAL VARIABLES
98 //==============================================================================
99
100 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
101 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
102
103 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
104 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
105
106 extern int VErase (Draw_Interpretor& theDI,
107                    Standard_Integer  theArgNb,
108                    const char**      theArgVec);
109
110 #if defined(_WIN32)
111 static Handle(WNT_Window)& VT_GetWindow() {
112   static Handle(WNT_Window) WNTWin;
113   return WNTWin;
114 }
115 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
116 static Handle(Cocoa_Window)& VT_GetWindow()
117 {
118   static Handle(Cocoa_Window) aWindow;
119   return aWindow;
120 }
121 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
122 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
123 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
124
125 #else
126 static Handle(Xw_Window)& VT_GetWindow(){
127   static Handle(Xw_Window) XWWin;
128   return XWWin;
129 }
130
131 static void VProcessEvents(ClientData,int);
132 #endif
133
134 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
135 {
136   static Handle(Aspect_DisplayConnection) aDisplayConnection;
137   return aDisplayConnection;
138 }
139
140 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
141 {
142   GetDisplayConnection() = theDisplayConnection;
143 }
144
145 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
146 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
147 {
148   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
149 #if defined(_WIN32)
150   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
151   if (!aWindow.IsNull())
152     return aWindow->HWindow();
153 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
154   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156   return aWindow->XWindow();
157 #endif
158   return aWindowHandle;
159 }
160 #endif
161
162 static Standard_Boolean MyHLRIsOn = Standard_False;
163
164 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
165 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
166 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
167 static OpenGl_Caps ViewerTest_myDefaultCaps;
168
169 static void OSWindowSetup();
170
171 static struct
172 {
173   Quantity_Color FlatColor;
174   Quantity_Color GradientColor1;
175   Quantity_Color GradientColor2;
176   Aspect_GradientFillMethod FillMethod;
177 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
178
179 //==============================================================================
180 //  EVENT GLOBAL VARIABLES
181 //==============================================================================
182
183 static int Start_Rot = 0;
184 int X_Motion = 0; // Current cursor position
185 int Y_Motion = 0;
186 int X_ButtonPress = 0; // Last ButtonPress position
187 int Y_ButtonPress = 0;
188 Standard_Boolean IsDragged = Standard_False;
189 Standard_Boolean DragFirst = Standard_False;
190
191
192 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
193 {
194   static Handle(AIS_RubberBand) aBand;
195   if (aBand.IsNull())
196   {
197     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
198     aBand->SetDisplayMode (0);
199   }
200   return aBand;
201 }
202
203 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
204
205 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
206 {
207   static ViewerTest_MapOfAISManipulators aMap;
208   return aMap;
209 }
210
211 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
212 {
213   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
214   for (; anIt.More(); anIt.Next())
215   {
216     if (anIt.Value()->HasActiveMode())
217     {
218       return anIt.Value();
219     }
220   }
221   return NULL;
222 }
223
224 //==============================================================================
225
226 #ifdef _WIN32
227 static LRESULT WINAPI ViewerWindowProc(
228                                        HWND hwnd,
229                                        UINT uMsg,
230                                        WPARAM wParam,
231                                        LPARAM lParam );
232 static LRESULT WINAPI AdvViewerWindowProc(
233   HWND hwnd,
234   UINT uMsg,
235   WPARAM wParam,
236   LPARAM lParam );
237 #endif
238
239
240 //==============================================================================
241 //function : WClass
242 //purpose  :
243 //==============================================================================
244
245 const Handle(MMgt_TShared)& ViewerTest::WClass()
246 {
247   static Handle(MMgt_TShared) theWClass;
248 #if defined(_WIN32)
249   if (theWClass.IsNull())
250   {
251     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
252       CS_VREDRAW | CS_HREDRAW, 0, 0,
253       ::LoadCursor (NULL, IDC_ARROW));
254   }
255 #endif
256   return theWClass;
257 }
258
259 //==============================================================================
260 //function : CreateName
261 //purpose  : Create numerical name for new object in theMap
262 //==============================================================================
263 template <typename ObjectType>
264 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
265                                     const TCollection_AsciiString& theDefaultString)
266 {
267   if (theObjectMap.IsEmpty())
268     return theDefaultString + TCollection_AsciiString(1);
269
270   Standard_Integer aNextKey = 1;
271   Standard_Boolean isFound = Standard_False;
272   while (!isFound)
273   {
274     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
275     // Look for objects with default names
276     if (theObjectMap.IsBound1(aStringKey))
277     {
278       aNextKey++;
279     }
280     else
281       isFound = Standard_True;
282   }
283
284   return theDefaultString + TCollection_AsciiString(aNextKey);
285 }
286
287 //==============================================================================
288 //structure : ViewerTest_Names
289 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
290 //==============================================================================
291 struct ViewerTest_Names
292 {
293 private:
294   TCollection_AsciiString myDriverName;
295   TCollection_AsciiString myViewerName;
296   TCollection_AsciiString myViewName;
297
298 public:
299
300   const TCollection_AsciiString& GetDriverName () const
301   {
302     return myDriverName;
303   }
304   void SetDriverName (const TCollection_AsciiString& theDriverName)
305   {
306     myDriverName = theDriverName;
307   }
308   const TCollection_AsciiString& GetViewerName () const
309   {
310     return myViewerName;
311   }
312   void SetViewerName (const TCollection_AsciiString& theViewerName)
313   {
314     myViewerName = theViewerName;
315   }
316   const TCollection_AsciiString& GetViewName () const
317   {
318     return myViewName;
319   }
320   void SetViewName (const TCollection_AsciiString& theViewName)
321   {
322     myViewName = theViewName;
323   }
324
325   //===========================================================================
326   //function : Constructor for ViewerTest_Names
327   //purpose  : Get view, viewer, driver names from custom string
328   //===========================================================================
329
330   ViewerTest_Names (const TCollection_AsciiString& theInputString)
331   {
332     TCollection_AsciiString aName(theInputString);
333     if (theInputString.IsEmpty())
334     {
335       // Get current configuration
336       if (ViewerTest_myDrivers.IsEmpty())
337         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
338           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
339       else
340         myDriverName = ViewerTest_myDrivers.Find2
341         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
342
343       if(ViewerTest_myContexts.IsEmpty())
344       {
345         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
346           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
347       }
348       else
349         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
350
351         myViewName = CreateName <Handle(V3d_View)>
352           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
353     }
354     else
355     {
356       // There is at least view name
357       Standard_Integer aParserNumber = 0;
358       for (Standard_Integer i = 0; i < 3; ++i)
359       {
360         Standard_Integer aParserPos = aName.SearchFromEnd("/");
361         if(aParserPos != -1)
362         {
363           aParserNumber++;
364           aName.Split(aParserPos-1);
365         }
366         else
367           break;
368       }
369       if (aParserNumber == 0)
370       {
371         // Only view name
372         if (!ViewerTest::GetAISContext().IsNull())
373         {
374           myDriverName = ViewerTest_myDrivers.Find2
375           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
376           myViewerName = ViewerTest_myContexts.Find2
377           (ViewerTest::GetAISContext());
378         }
379         else
380         {
381           // There is no opened contexts here, need to create names for viewer and driver
382           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
383             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
384
385           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
386             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
387         }
388         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
389       }
390       else if (aParserNumber == 1)
391       {
392         // Here is viewerName/viewName
393         if (!ViewerTest::GetAISContext().IsNull())
394           myDriverName = ViewerTest_myDrivers.Find2
395           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
396         else
397         {
398           // There is no opened contexts here, need to create name for driver
399           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
400             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
401         }
402         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
403
404         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
405       }
406       else
407       {
408         //Here is driverName/viewerName/viewName
409         myDriverName = TCollection_AsciiString(aName);
410
411         TCollection_AsciiString aViewerName(theInputString);
412         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
413         myViewerName = TCollection_AsciiString(aViewerName);
414
415         myViewName = TCollection_AsciiString(theInputString);
416       }
417     }
418   }
419 };
420
421 //==============================================================================
422 //function : FindContextByView
423 //purpose  : Find AIS_InteractiveContext by View
424 //==============================================================================
425
426 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
427 {
428   Handle(AIS_InteractiveContext) anAISContext;
429
430   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
431        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
432   {
433     if (anIter.Value()->CurrentViewer() == theView->Viewer())
434        return anIter.Key2();
435   }
436   return anAISContext;
437 }
438
439
440 //==============================================================================
441 //function : SetWindowTitle
442 //purpose  : Set window title
443 //==============================================================================
444
445 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
446                      Standard_CString theTitle)
447 {
448 #if defined(_WIN32)
449   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
450     theTitle);
451 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
452   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
453 #else
454   if(GetDisplayConnection()->GetDisplay())
455   {
456     Window aWindow =
457       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
458     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
459   }
460 #endif
461 }
462
463 //==============================================================================
464 //function : IsWindowOverlapped
465 //purpose  : Check if theWindow overlapp another view
466 //==============================================================================
467
468 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
469                                      const Standard_Integer thePxTop,
470                                      const Standard_Integer thePxRight,
471                                      const Standard_Integer thePxBottom,
472                                      TCollection_AsciiString& theViewId)
473 {
474   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
475       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
476   {
477     Standard_Integer aTop = 0,
478       aLeft = 0,
479       aRight = 0,
480       aBottom = 0;
481     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
482     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
483         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
484         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
485         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
486     {
487       theViewId = anIter.Key1();
488       return Standard_True;
489     }
490   }
491   return Standard_False;
492 }
493
494 // Workaround: to create and delete non-orthographic views outside ViewerTest
495 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
496 {
497   ViewerTest_myViews.UnBind1 (theName);
498 }
499
500 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
501                                const Handle(V3d_View)& theView)
502 {
503   ViewerTest_myViews.Bind (theName, theView);
504 }
505
506 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
507 {
508   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
509 }
510 //==============================================================================
511 //function : ViewerInit
512 //purpose  : Create the window viewer and initialize all the global variable
513 //==============================================================================
514
515 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
516                                                 const Standard_Integer thePxTop,
517                                                 const Standard_Integer thePxWidth,
518                                                 const Standard_Integer thePxHeight,
519                                                 Standard_CString theViewName,
520                                                 Standard_CString theDisplayName)
521 {
522   // Default position and dimension of the viewer window.
523   // Note that left top corner is set to be sufficiently small to have
524   // window fit in the small screens (actual for remote desktops, see #23003).
525   // The position corresponds to the window's client area, thus some
526   // gap is added for window frame to be visible.
527   Standard_Integer aPxLeft   = 20;
528   Standard_Integer aPxTop    = 40;
529   Standard_Integer aPxWidth  = 409;
530   Standard_Integer aPxHeight = 409;
531   Standard_Boolean toCreateViewer = Standard_False;
532
533   Handle(OpenGl_GraphicDriver) aGraphicDriver;
534   ViewerTest_Names aViewNames(theViewName);
535   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
536     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
537
538   if (thePxLeft != 0)
539     aPxLeft = thePxLeft;
540   if (thePxTop != 0)
541     aPxTop = thePxTop;
542   if (thePxWidth != 0)
543     aPxWidth = thePxWidth;
544   if (thePxHeight != 0)
545     aPxHeight = thePxHeight;
546
547   // Get graphic driver (create it or get from another view)
548   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
549   {
550     // Get connection string
551   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
552     TCollection_AsciiString aDisplayName(theDisplayName);
553     if (!aDisplayName.IsEmpty())
554       SetDisplayConnection (new Aspect_DisplayConnection ());
555     else
556       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
557   #else
558     (void)theDisplayName; // avoid warning on unused argument
559     SetDisplayConnection (new Aspect_DisplayConnection ());
560   #endif
561
562     if (Draw_VirtualWindows)
563     {
564       // don't waste the time waiting for VSync when window is not displayed on the screen
565       ViewerTest_myDefaultCaps.swapInterval = 0;
566       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
567       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
568     }
569     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
570     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
571
572     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
573     toCreateViewer = Standard_True;
574   }
575   else
576   {
577     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
578   }
579
580   //Dispose the window if input parameters are default
581   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
582   {
583     Standard_Integer aTop = 0,
584                      aLeft = 0,
585                      aRight = 0,
586                      aBottom = 0,
587                      aScreenWidth = 0,
588                      aScreenHeight = 0;
589
590     // Get screen resolution
591 #if defined(_WIN32) || defined(__WIN32__)
592     RECT aWindowSize;
593     GetClientRect(GetDesktopWindow(), &aWindowSize);
594     aScreenHeight = aWindowSize.bottom;
595     aScreenWidth = aWindowSize.right;
596 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
597     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
598 #else
599     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
600     aScreenWidth = WidthOfScreen(aScreen);
601     aScreenHeight = HeightOfScreen(aScreen);
602 #endif
603
604     TCollection_AsciiString anOverlappedViewId("");
605
606     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
607     {
608       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
609
610       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
611         && aRight + 2*aPxWidth + 40 > aScreenWidth)
612       {
613         if (aBottom + aPxHeight + 40 > aScreenHeight)
614         {
615           aPxLeft = 20;
616           aPxTop = 40;
617           break;
618         }
619         aPxLeft = 20;
620         aPxTop = aBottom + 40;
621       }
622       else
623         aPxLeft = aRight + 20;
624     }
625   }
626
627   // Get viewer name
628   TCollection_AsciiString aTitle("3D View - ");
629   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
630
631   // Change name of current active window
632   if (!ViewerTest::CurrentView().IsNull())
633   {
634     TCollection_AsciiString anActiveWindowTitle("3D View - ");
635     anActiveWindowTitle = anActiveWindowTitle
636       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
637     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
638   }
639
640   // Create viewer
641   Handle(V3d_Viewer) a3DViewer;
642   // If it's the single view, we first look for empty context
643   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
644   {
645     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
646       anIter(ViewerTest_myContexts);
647     if (anIter.More())
648       ViewerTest::SetAISContext (anIter.Value());
649     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
650   }
651   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
652   {
653     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
654     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
655   }
656   else if (a3DViewer.IsNull())
657   {
658     toCreateViewer = Standard_True;
659     TCollection_ExtendedString NameOfWindow("Viewer3D");
660     a3DViewer = new V3d_Viewer(aGraphicDriver, NameOfWindow.ToExtString());
661     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
662     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
663                                            ViewerTest_DefaultBackground.GradientColor2,
664                                            ViewerTest_DefaultBackground.FillMethod);
665   }
666
667   // AIS context setup
668   if (ViewerTest::GetAISContext().IsNull() ||
669       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
670   {
671     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
672     ViewerTest::SetAISContext (aContext);
673     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
674   }
675   else
676   {
677     ViewerTest::ResetEventManager();
678   }
679
680   // Create window
681 #if defined(_WIN32)
682   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
683                                     Handle(WNT_WClass)::DownCast (WClass()),
684                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
685                                     aPxLeft, aPxTop,
686                                     aPxWidth, aPxHeight,
687                                     Quantity_NOC_BLACK);
688 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
689   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
690                                      aPxLeft, aPxTop,
691                                      aPxWidth, aPxHeight);
692   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
693 #else
694   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
695                                   aTitle.ToCString(),
696                                   aPxLeft, aPxTop,
697                                   aPxWidth, aPxHeight);
698 #endif
699   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
700
701   // View setup
702   Handle(V3d_View) aView = a3DViewer->CreateView();
703   aView->SetWindow (VT_GetWindow());
704   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
705
706   ViewerTest::CurrentView(aView);
707   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
708
709   // Setup for X11 or NT
710   OSWindowSetup();
711
712   // Set parameters for V3d_View and V3d_Viewer
713   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
714   aV3dView->SetComputedMode(Standard_False);
715   MyHLRIsOn = aV3dView->ComputedMode();
716
717   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
718   if (toCreateViewer)
719   {
720     a3DViewer->SetDefaultLights();
721     a3DViewer->SetLightOn();
722   }
723
724   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
725   #if TCL_MAJOR_VERSION  < 8
726   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
727       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
728   #else
729   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
730       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
731   #endif
732   #endif
733
734   VT_GetWindow()->Map();
735
736   // Set the handle of created view in the event manager
737   ViewerTest::ResetEventManager();
738
739   ViewerTest::CurrentView()->Redraw();
740
741   aView.Nullify();
742   a3DViewer.Nullify();
743
744   return aViewNames.GetViewName();
745 }
746
747 //==============================================================================
748 //function : RedrawAllViews
749 //purpose  : Redraw all created views
750 //==============================================================================
751 void ViewerTest::RedrawAllViews()
752 {
753   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
754   for (; aViewIt.More(); aViewIt.Next())
755   {
756     const Handle(V3d_View)& aView = aViewIt.Key2();
757     aView->Redraw();
758   }
759 }
760
761 //==============================================================================
762 //function : Vinit
763 //purpose  : Create the window viewer and initialize all the global variable
764 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
765 //==============================================================================
766
767 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
768 {
769   if (theArgsNb > 9)
770   {
771     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
772               << "Type help for more information.\n";
773     return 1;
774   }
775
776   TCollection_AsciiString aViewName, aDisplayName;
777   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
778   TCollection_AsciiString aName, aValue;
779   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
780   {
781     const TCollection_AsciiString anArg = theArgVec[anArgIt];
782     TCollection_AsciiString anArgCase = anArg;
783     anArgCase.UpperCase();
784     if (ViewerTest::SplitParameter (anArg, aName, aValue))
785     {
786       aName.UpperCase();
787       if (aName.IsEqual ("NAME"))
788       {
789         aViewName = aValue;
790       }
791       else if (aName.IsEqual ("L")
792             || aName.IsEqual ("LEFT"))
793       {
794         aPxLeft = aValue.IntegerValue();
795       }
796       else if (aName.IsEqual ("T")
797             || aName.IsEqual ("TOP"))
798       {
799         aPxTop = aValue.IntegerValue();
800       }
801     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
802       else if (aName.IsEqual ("DISP")
803             || aName.IsEqual ("DISPLAY"))
804       {
805         aDisplayName = aValue;
806       }
807     #endif
808       else if (aName.IsEqual ("W")
809             || aName.IsEqual ("WIDTH"))
810       {
811         aPxWidth = aValue.IntegerValue();
812       }
813       else if (aName.IsEqual ("H")
814             || aName.IsEqual ("HEIGHT"))
815       {
816         aPxHeight = aValue.IntegerValue();
817       }
818       else
819       {
820         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
821       }
822     }
823     else if (aViewName.IsEmpty())
824     {
825       aViewName = anArg;
826     }
827     else
828     {
829       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
830     }
831   }
832
833   ViewerTest_Names aViewNames (aViewName);
834   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
835   {
836     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
837     theDi.Eval (aCommand.ToCString());
838     return 0;
839   }
840
841   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
842                                                             aViewName.ToCString(),
843                                                             aDisplayName.ToCString());
844   theDi << aViewId;
845   return 0;
846 }
847
848 //==============================================================================
849 //function : VHLR
850 //purpose  : hidden lines removal algorithm
851 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
852 //==============================================================================
853
854 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
855 {
856   if (ViewerTest::CurrentView().IsNull())
857   {
858     di << argv[0] << ": Call vinit before this command, please.\n";
859     return 1;
860   }
861
862   if (argc < 2)
863   {
864     di << argv[0] << ": Wrong number of command arguments.\n"
865       << "Type help " << argv[0] << " for more information.\n";
866     return 1;
867   }
868
869   // Enable or disable HLR mode.
870   Standard_Boolean isHLROn =
871     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
872
873   if (isHLROn != MyHLRIsOn)
874   {
875     MyHLRIsOn = isHLROn;
876     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
877   }
878
879   // Show or hide hidden lines in HLR mode.
880   Standard_Boolean isCurrentShowHidden
881     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
882
883   Standard_Boolean isShowHidden =
884     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
885                 : isCurrentShowHidden;
886
887
888   if (isShowHidden != isCurrentShowHidden)
889   {
890     if (isShowHidden)
891     {
892       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
893     }
894     else
895     {
896       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
897     }
898
899     // Redisplay shapes.
900     if (MyHLRIsOn)
901     {
902       AIS_ListOfInteractive aListOfShapes;
903       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
904
905       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
906       {
907         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
908         if (aShape.IsNull())
909         {
910           continue;
911         }
912         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
913       }
914     }
915   }
916
917   ViewerTest::CurrentView()->Update();
918   return 0;
919 }
920
921 //==============================================================================
922 //function : VHLRType
923 //purpose  : change type of using HLR algorithm
924 //==============================================================================
925
926 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
927 {
928   if (ViewerTest::CurrentView().IsNull())
929   {
930     di << argv[0] << ": Call vinit before this command, please.\n";
931     return 1;
932   }
933
934   if (argc < 2)
935   {
936     di << argv[0] << ": Wrong number of command arguments.\n"
937       << "Type help " << argv[0] << " for more information.\n";
938     return 1;
939   }
940
941   Prs3d_TypeOfHLR aTypeOfHLR =
942     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
943
944   if (argc == 2)
945   {
946     AIS_ListOfInteractive aListOfShapes;
947     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
948     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
949     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
950       anIter.More(); anIter.Next())
951     {
952       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
953       if (aShape.IsNull())
954         continue;
955       if (aShape->TypeOfHLR() != aTypeOfHLR)
956         aShape->SetTypeOfHLR (aTypeOfHLR);
957       if (MyHLRIsOn)
958         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
959     }
960     ViewerTest::CurrentView()->Update();
961     return 0;
962   }
963   else
964   {
965     for (Standard_Integer i = 2; i < argc; ++i)
966     {
967       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
968       TCollection_AsciiString aName (argv[i]);
969
970       if (!aMap.IsBound2 (aName))
971       {
972         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
973         continue;
974       }
975       Handle(AIS_Shape) anAISObject =
976         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
977       if (anAISObject.IsNull())
978         continue;
979       anAISObject->SetTypeOfHLR (aTypeOfHLR);
980       if (MyHLRIsOn)
981         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
982     }
983     ViewerTest::CurrentView()->Update();
984   }
985
986   return 0;
987 }
988
989 //==============================================================================
990 //function : FindViewIdByWindowHandle
991 //purpose  : Find theView Id in the map of views by window handle
992 //==============================================================================
993 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
994 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
995 {
996   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
997        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
998   {
999     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1000     if (aWindowHandle == theWindowHandle)
1001       return anIter.Key1();
1002   }
1003   return TCollection_AsciiString("");
1004 }
1005 #endif
1006
1007 //==============================================================================
1008 //function : ActivateView
1009 //purpose  : Make the view active
1010 //==============================================================================
1011
1012 void ActivateView (const TCollection_AsciiString& theViewName)
1013 {
1014   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1015   if (!aView.IsNull())
1016   {
1017     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1018     if (!anAISContext.IsNull())
1019     {
1020       if (!ViewerTest::CurrentView().IsNull())
1021       {
1022         TCollection_AsciiString aTitle("3D View - ");
1023         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1024         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1025       }
1026
1027       ViewerTest::CurrentView (aView);
1028       // Update degenerate mode
1029       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1030       ViewerTest::SetAISContext (anAISContext);
1031       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1032       aTitle = aTitle + theViewName + "(*)";
1033       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1034 #if defined(_WIN32) || defined(__WIN32__)
1035       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1036 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1037       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1038 #else
1039       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1040 #endif
1041       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1042       ViewerTest::CurrentView()->Redraw();
1043     }
1044   }
1045 }
1046
1047 //==============================================================================
1048 //function : RemoveView
1049 //purpose  :
1050 //==============================================================================
1051 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1052                              const Standard_Boolean  theToRemoveContext)
1053 {
1054   if (!ViewerTest_myViews.IsBound2 (theView))
1055   {
1056     return;
1057   }
1058
1059   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1060   RemoveView (aViewName, theToRemoveContext);
1061 }
1062
1063 //==============================================================================
1064 //function : RemoveView
1065 //purpose  : Close and remove view from display, clear maps if neccessary
1066 //==============================================================================
1067 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1068 {
1069   if (!ViewerTest_myViews.IsBound1(theViewName))
1070   {
1071     cout << "Wrong view name\n";
1072     return;
1073   }
1074
1075   // Activate another view if it's active now
1076   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1077   {
1078     if (ViewerTest_myViews.Extent() > 1)
1079     {
1080       TCollection_AsciiString aNewViewName;
1081       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1082            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1083         if (anIter.Key1() != theViewName)
1084         {
1085           aNewViewName = anIter.Key1();
1086           break;
1087         }
1088         ActivateView (aNewViewName);
1089     }
1090     else
1091     {
1092       Handle(V3d_View) anEmptyView;
1093 #if defined(_WIN32) || defined(__WIN32__)
1094       Handle(WNT_Window) anEmptyWindow;
1095 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1096       Handle(Cocoa_Window) anEmptyWindow;
1097 #else
1098       Handle(Xw_Window) anEmptyWindow;
1099 #endif
1100       VT_GetWindow() = anEmptyWindow;
1101       ViewerTest::CurrentView (anEmptyView);
1102       if (isContextRemoved)
1103       {
1104         Handle(AIS_InteractiveContext) anEmptyContext;
1105         ViewerTest::SetAISContext(anEmptyContext);
1106       }
1107     }
1108   }
1109
1110   // Delete view
1111   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1112   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1113
1114   // Remove view resources
1115   ViewerTest_myViews.UnBind1(theViewName);
1116   aView->Remove();
1117
1118 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1119   XFlush (GetDisplayConnection()->GetDisplay());
1120 #endif
1121
1122   // Keep context opened only if the closed view is last to avoid
1123   // unused empty contexts
1124   if (!aCurrentContext.IsNull())
1125   {
1126     // Check if there are more difined views in the viewer
1127     aCurrentContext->CurrentViewer()->InitDefinedViews();
1128     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1129     {
1130       // Remove driver if there is no viewers that use it
1131       Standard_Boolean isRemoveDriver = Standard_True;
1132       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1133           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1134       {
1135         if (aCurrentContext != anIter.Key2() &&
1136           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1137         {
1138           isRemoveDriver = Standard_False;
1139           break;
1140         }
1141       }
1142       if(isRemoveDriver)
1143       {
1144         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1145       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1146         #if TCL_MAJOR_VERSION  < 8
1147         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1148         #else
1149         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1150         #endif
1151       #endif
1152       }
1153
1154       ViewerTest_myContexts.UnBind2(aCurrentContext);
1155     }
1156   }
1157   cout << "3D View - " << theViewName << " was deleted.\n";
1158
1159 }
1160
1161 //==============================================================================
1162 //function : VClose
1163 //purpose  : Remove the view defined by its name
1164 //==============================================================================
1165
1166 static int VClose (Draw_Interpretor& /*theDi*/,
1167                    Standard_Integer  theArgsNb,
1168                    const char**      theArgVec)
1169 {
1170   NCollection_List<TCollection_AsciiString> aViewList;
1171   if (theArgsNb > 1)
1172   {
1173     TCollection_AsciiString anArg (theArgVec[1]);
1174     anArg.UpperCase();
1175     if (anArg.IsEqual ("ALL")
1176      || anArg.IsEqual ("*"))
1177     {
1178       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1179            anIter.More(); anIter.Next())
1180       {
1181         aViewList.Append (anIter.Key1());
1182       }
1183       if (aViewList.IsEmpty())
1184       {
1185         std::cout << "No view to close\n";
1186         return 0;
1187       }
1188     }
1189     else
1190     {
1191       ViewerTest_Names aViewName (theArgVec[1]);
1192       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1193       {
1194         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1195         return 1;
1196       }
1197       aViewList.Append (aViewName.GetViewName());
1198     }
1199   }
1200   else
1201   {
1202     // close active view
1203     if (ViewerTest::CurrentView().IsNull())
1204     {
1205       std::cerr << "No active view!\n";
1206       return 1;
1207     }
1208     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1209   }
1210
1211   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1212   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1213        anIter.More(); anIter.Next())
1214   {
1215     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1216   }
1217
1218   return 0;
1219 }
1220
1221 //==============================================================================
1222 //function : VActivate
1223 //purpose  : Activate the view defined by its ID
1224 //==============================================================================
1225
1226 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1227 {
1228   if (theArgsNb > 2)
1229   {
1230     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1231     << "Usage: " << theArgVec[0] << " ViewID\n";
1232     return 1;
1233   }
1234   if(theArgsNb == 1)
1235   {
1236     theDi.Eval("vviewlist");
1237     return 0;
1238   }
1239
1240   TCollection_AsciiString aNameString(theArgVec[1]);
1241   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1242   {
1243     TCollection_AsciiString aTitle("3D View - ");
1244     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1245     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1246     Handle(V3d_View) anEmptyView;
1247 #if defined(_WIN32) || defined(__WIN32__)
1248     Handle(WNT_Window) anEmptyWindow;
1249 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1250     Handle(Cocoa_Window) anEmptyWindow;
1251 #else
1252     Handle(Xw_Window) anEmptyWindow;
1253 #endif
1254     VT_GetWindow() = anEmptyWindow;
1255     ViewerTest::CurrentView (anEmptyView);
1256     ViewerTest::ResetEventManager();
1257     theDi << theArgVec[0] << ": all views are inactive\n";
1258     return 0;
1259   }
1260
1261   ViewerTest_Names aViewNames(aNameString);
1262
1263   // Check if this view exists in the viewer with the driver
1264   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1265   {
1266     theDi << "Wrong view name\n";
1267     return 1;
1268   }
1269
1270   // Check if it is active already
1271   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1272   {
1273     theDi << theArgVec[0] << ": the view is active already\n";
1274     return 0;
1275   }
1276
1277   ActivateView (aViewNames.GetViewName());
1278   return 0;
1279 }
1280
1281 //==============================================================================
1282 //function : VViewList
1283 //purpose  : Print current list of views per viewer and graphic driver ID
1284 //           shared between viewers
1285 //==============================================================================
1286
1287 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1288 {
1289   if (theArgsNb > 2)
1290   {
1291     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1292           << "Usage: " << theArgVec[0] << " name";
1293     return 1;
1294   }
1295   if (ViewerTest_myContexts.Size() < 1)
1296     return 0;
1297
1298   Standard_Boolean isTreeView =
1299     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1300
1301   if (isTreeView)
1302     theDi << theArgVec[0] <<":\n";
1303
1304     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1305       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1306     {
1307       if (isTreeView)
1308         theDi << aDriverIter.Key1() << ":\n";
1309
1310       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1311         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1312       {
1313         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1314         {
1315           if (isTreeView)
1316           {
1317             TCollection_AsciiString aContextName(aContextIter.Key1());
1318             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1319           }
1320
1321           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1322             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1323           {
1324             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1325             {
1326               TCollection_AsciiString aViewName(aViewIter.Key1());
1327               if (isTreeView)
1328               {
1329                 if (aViewIter.Value() == ViewerTest::CurrentView())
1330                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1331                 else
1332                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1333               }
1334               else
1335               {
1336                 theDi << aViewName << " ";
1337               }
1338             }
1339           }
1340         }
1341       }
1342     }
1343   return 0;
1344 }
1345
1346 //==============================================================================
1347 //function : VT_ProcessKeyPress
1348 //purpose  : Handle KeyPress event from a CString
1349 //==============================================================================
1350 void VT_ProcessKeyPress (const char* buf_ret)
1351 {
1352   //cout << "KeyPress" << endl;
1353   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1354   // Letter in alphabetic order
1355
1356   if (!strcasecmp (buf_ret, "A"))
1357   {
1358     // AXO
1359     aView->SetProj(V3d_XposYnegZpos);
1360   }
1361   else if (!strcasecmp (buf_ret, "D"))
1362   {
1363     // Reset
1364     aView->Reset();
1365   }
1366   else if (!strcasecmp (buf_ret, "F"))
1367   {
1368     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1369     {
1370       ViewerTest::GetAISContext()->FitSelected (aView);
1371     }
1372     else
1373     {
1374       // FitAll
1375       aView->FitAll();
1376     }
1377   }
1378   else if (!strcasecmp (buf_ret, "H"))
1379   {
1380     // HLR
1381     cout << "HLR" << endl;
1382     aView->SetComputedMode (!aView->ComputedMode());
1383     MyHLRIsOn = aView->ComputedMode();
1384   }
1385   else if (!strcasecmp (buf_ret, "P"))
1386   {
1387     // Type of HLR
1388     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1389     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1390       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1391     else
1392       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1393     if (aContext->NbSelected()==0)
1394     {
1395       AIS_ListOfInteractive aListOfShapes;
1396       aContext->DisplayedObjects(aListOfShapes);
1397       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1398         anIter.More(); anIter.Next())
1399       {
1400         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1401         if (aShape.IsNull())
1402           continue;
1403         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1404           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1405         else
1406           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1407         aContext->Redisplay (aShape, Standard_False);
1408       }
1409     }
1410     else
1411     {
1412       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1413       {
1414         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1415         if (aShape.IsNull())
1416           continue;
1417         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1418           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1419         else
1420           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1421         aContext->Redisplay (aShape, Standard_False);
1422       }
1423     }
1424
1425     aContext->UpdateCurrentViewer();
1426
1427   }
1428   else if (!strcasecmp (buf_ret, "S"))
1429   {
1430     std::cout << "setup Shaded display mode" << std::endl;
1431
1432     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1433     if(Ctx->NbSelected()==0)
1434       Ctx->SetDisplayMode(AIS_Shaded);
1435     else{
1436       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1437         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1438       Ctx->UpdateCurrentViewer();
1439     }
1440   }
1441   else if (!strcasecmp (buf_ret, "U"))
1442   {
1443     // Unset display mode
1444     std::cout << "reset display mode to defaults" << std::endl;
1445
1446     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1447     if(Ctx->NbSelected()==0)
1448       Ctx->SetDisplayMode(AIS_WireFrame);
1449     else{
1450       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1451         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1452       Ctx->UpdateCurrentViewer();
1453     }
1454
1455   }
1456   else if (!strcasecmp (buf_ret, "T"))
1457   {
1458     // Top
1459     aView->SetProj(V3d_Zpos);
1460   }
1461   else if (!strcasecmp (buf_ret, "B"))
1462   {
1463     // Bottom
1464     aView->SetProj(V3d_Zneg);
1465   }
1466   else if (!strcasecmp (buf_ret, "L"))
1467   {
1468     // Left
1469     aView->SetProj(V3d_Xneg);
1470   }
1471   else if (!strcasecmp (buf_ret, "R"))
1472   {
1473     // Right
1474     aView->SetProj(V3d_Xpos);
1475   }
1476   else if (!strcasecmp (buf_ret, "W"))
1477   {
1478     std::cout << "setup WireFrame display mode" << std::endl;
1479     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1480     if(Ctx->NbSelected()==0)
1481       Ctx->SetDisplayMode(AIS_WireFrame);
1482     else{
1483       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1484         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1485       Ctx->UpdateCurrentViewer();
1486     }
1487   }
1488   else if (!strcasecmp (buf_ret, ","))
1489   {
1490     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1491   }
1492   else if (!strcasecmp (buf_ret, "."))
1493   {
1494     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1495   }
1496   else if (!strcasecmp (buf_ret, "/"))
1497   {
1498     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1499     if (aCamera->IsStereo())
1500     {
1501       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1502       aView->Redraw();
1503     }
1504   }
1505   else if (!strcasecmp (buf_ret, "*"))
1506   {
1507     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1508     if (aCamera->IsStereo())
1509     {
1510       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1511       aView->Redraw();
1512     }
1513   }
1514   else if (*buf_ret == THE_KEY_DELETE)
1515   {
1516     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1517     if (!aCtx.IsNull()
1518      && aCtx->NbSelected() > 0)
1519     {
1520       Draw_Interprete ("verase");
1521     }
1522   }
1523   else
1524   {
1525     // Number
1526     Standard_Integer Num = Draw::Atoi(buf_ret);
1527     if(Num>=0 && Num<=7)
1528       ViewerTest::StandardModeActivation(Num);
1529   }
1530 }
1531
1532 //==============================================================================
1533 //function : VT_ProcessExpose
1534 //purpose  : Redraw the View on an Expose Event
1535 //==============================================================================
1536 void VT_ProcessExpose()
1537 {
1538   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1539   if (!aView3d.IsNull())
1540   {
1541     aView3d->Redraw();
1542   }
1543 }
1544
1545 //==============================================================================
1546 //function : VT_ProcessConfigure
1547 //purpose  : Resize the View on an Configure Event
1548 //==============================================================================
1549 void VT_ProcessConfigure()
1550 {
1551   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1552   if (aView3d.IsNull())
1553   {
1554     return;
1555   }
1556
1557   aView3d->MustBeResized();
1558   aView3d->Update();
1559   aView3d->Redraw();
1560 }
1561
1562 //==============================================================================
1563 //function : VT_ProcessButton1Press
1564 //purpose  : Picking
1565 //==============================================================================
1566 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1567                                          const char**     theArgVec,
1568                                          Standard_Boolean theToPick,
1569                                          Standard_Boolean theIsShift)
1570 {
1571   if (theToPick)
1572   {
1573     Standard_Real X, Y, Z;
1574     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1575
1576     Draw::Set (theArgVec[1], X);
1577     Draw::Set (theArgVec[2], Y);
1578     Draw::Set (theArgVec[3], Z);
1579   }
1580
1581   if (theIsShift)
1582   {
1583     ViewerTest::CurrentEventManager()->ShiftSelect();
1584   }
1585   else
1586   {
1587     ViewerTest::CurrentEventManager()->Select();
1588   }
1589
1590   return Standard_False;
1591 }
1592
1593 //==============================================================================
1594 //function : VT_ProcessButton1Release
1595 //purpose  : End selecting
1596 //==============================================================================
1597 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1598 {
1599   if (IsDragged)
1600   {
1601     IsDragged = Standard_False;
1602     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1603     if (theIsShift)
1604     {
1605       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1606                        X_Motion, Y_Motion);
1607     }
1608     else
1609     {
1610       EM->Select (X_ButtonPress, Y_ButtonPress,
1611                   X_Motion, Y_Motion);
1612     }
1613   }
1614 }
1615
1616 //==============================================================================
1617 //function : VT_ProcessButton3Press
1618 //purpose  : Start Rotation
1619 //==============================================================================
1620 void VT_ProcessButton3Press()
1621 {
1622   Start_Rot = 1;
1623   if (MyHLRIsOn)
1624   {
1625     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1626   }
1627   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1628 }
1629
1630 //==============================================================================
1631 //function : VT_ProcessButton3Release
1632 //purpose  : End rotation
1633 //==============================================================================
1634 void VT_ProcessButton3Release()
1635 {
1636   if (Start_Rot)
1637   {
1638     Start_Rot = 0;
1639     if (MyHLRIsOn)
1640     {
1641       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1642     }
1643   }
1644 }
1645
1646 //==============================================================================
1647 //function : ProcessControlButton1Motion
1648 //purpose  : Zoom
1649 //==============================================================================
1650
1651 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1652 static void ProcessControlButton1Motion()
1653 {
1654   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1655
1656   X_ButtonPress = X_Motion;
1657   Y_ButtonPress = Y_Motion;
1658 }
1659 #endif
1660
1661 //==============================================================================
1662 //function : VT_ProcessControlButton2Motion
1663 //purpose  : Panning
1664 //==============================================================================
1665 void VT_ProcessControlButton2Motion()
1666 {
1667   Standard_Integer aDx = X_Motion - X_ButtonPress;
1668   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1669
1670   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1671
1672   ViewerTest::CurrentView()->Pan (aDx, aDy);
1673
1674   X_ButtonPress = X_Motion;
1675   Y_ButtonPress = Y_Motion;
1676 }
1677
1678 //==============================================================================
1679 //function : VT_ProcessControlButton3Motion
1680 //purpose  : Rotation
1681 //==============================================================================
1682 void VT_ProcessControlButton3Motion()
1683 {
1684   if (Start_Rot)
1685   {
1686     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1687   }
1688 }
1689
1690 //==============================================================================
1691 //function : VT_ProcessMotion
1692 //purpose  :
1693 //==============================================================================
1694 void VT_ProcessMotion()
1695 {
1696   //pre-hilights detected objects at mouse position
1697
1698   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1699   EM->MoveTo(X_Motion, Y_Motion);
1700 }
1701
1702
1703 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1704 {
1705   Xpix = X_Motion;Ypix=Y_Motion;
1706 }
1707
1708 //==============================================================================
1709 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1710 //purpose  : Switches to an axonometric, top, left and other views
1711 //==============================================================================
1712
1713 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1714 {
1715   if ( ViewerTest::CurrentView().IsNull() )
1716   {
1717     di<<"Call vinit before this command, please\n";
1718     return 1;
1719   }
1720
1721   ViewerTest::CurrentView()->SetProj(ori);
1722   return 0;
1723 }
1724
1725 //==============================================================================
1726 //function : VAxo
1727 //purpose  : Switch to an Axonometric view
1728 //Draw arg : No args
1729 //==============================================================================
1730
1731 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1732 {
1733   return ViewProject(di, V3d_XposYnegZpos);
1734 }
1735
1736 //==============================================================================
1737 //function : VTop
1738 //purpose  : Switch to a Top View
1739 //Draw arg : No args
1740 //==============================================================================
1741
1742 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1743 {
1744   return ViewProject(di, V3d_Zpos);
1745 }
1746
1747 //==============================================================================
1748 //function : VBottom
1749 //purpose  : Switch to a Bottom View
1750 //Draw arg : No args
1751 //==============================================================================
1752
1753 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1754 {
1755   return ViewProject(di, V3d_Zneg);
1756 }
1757
1758 //==============================================================================
1759 //function : VLeft
1760 //purpose  : Switch to a Left View
1761 //Draw arg : No args
1762 //==============================================================================
1763
1764 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1765 {
1766   return ViewProject(di, V3d_Xneg);
1767 }
1768
1769 //==============================================================================
1770 //function : VRight
1771 //purpose  : Switch to a Right View
1772 //Draw arg : No args
1773 //==============================================================================
1774
1775 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1776 {
1777   return ViewProject(di, V3d_Xpos);
1778 }
1779
1780 //==============================================================================
1781 //function : VFront
1782 //purpose  : Switch to a Front View
1783 //Draw arg : No args
1784 //==============================================================================
1785
1786 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1787 {
1788   return ViewProject(di, V3d_Yneg);
1789 }
1790
1791 //==============================================================================
1792 //function : VBack
1793 //purpose  : Switch to a Back View
1794 //Draw arg : No args
1795 //==============================================================================
1796
1797 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1798 {
1799   return ViewProject(di, V3d_Ypos);
1800 }
1801
1802 //==============================================================================
1803 //function : VHelp
1804 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1805 //Draw arg : No args
1806 //==============================================================================
1807
1808 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1809 {
1810
1811   di << "Q : Quit the application\n";
1812
1813   di << "=========================\n";
1814   di << "F : FitAll\n";
1815   di << "T : TopView\n";
1816   di << "B : BottomView\n";
1817   di << "R : RightView\n";
1818   di << "L : LeftView\n";
1819   di << "A : AxonometricView\n";
1820   di << "D : ResetView\n";
1821
1822   di << "=========================\n";
1823   di << "S : Shading\n";
1824   di << "W : Wireframe\n";
1825   di << "H : HidelLineRemoval\n";
1826   di << "U : Unset display mode\n";
1827   di << "Delete : Remove selection from viewer\n";
1828
1829   di << "=========================\n";
1830   di << "Selection mode \n";
1831   di << "0 : Shape\n";
1832   di << "1 : Vertex\n";
1833   di << "2 : Edge\n";
1834   di << "3 : Wire\n";
1835   di << "4 : Face\n";
1836   di << "5 : Shell\n";
1837   di << "6 : Solid\n";
1838   di << "7 : Compound\n";
1839
1840   di << "=========================\n";
1841   di << "Z : Switch Z clipping On/Off\n";
1842   di << ", : Hilight next detected\n";
1843   di << ". : Hilight previous detected\n";
1844
1845   return 0;
1846 }
1847
1848 #ifdef _WIN32
1849
1850 static Standard_Boolean Ppick = 0;
1851 static Standard_Integer Pargc = 0;
1852 static const char**           Pargv = NULL;
1853
1854
1855 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1856                                           UINT Msg,
1857                                           WPARAM wParam,
1858                                           LPARAM lParam )
1859 {
1860   if (!ViewerTest_myViews.IsEmpty()) {
1861
1862     WPARAM fwKeys = wParam;
1863
1864     switch( Msg ) {
1865     case WM_CLOSE:
1866        {
1867          // Delete view from map of views
1868          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1869          return 0;
1870        }
1871        break;
1872     case WM_ACTIVATE:
1873       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1874         || ViewerTest::CurrentView().IsNull())
1875       {
1876         // Activate inactive window
1877         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1878         {
1879           ActivateView (FindViewIdByWindowHandle(hwnd));
1880         }
1881       }
1882       break;
1883
1884     case WM_LBUTTONUP:
1885       if (IsDragged && !DragFirst)
1886       {
1887         if (!GetActiveAISManipulator().IsNull())
1888         {
1889           GetActiveAISManipulator()->StopTransform();
1890           ViewerTest::GetAISContext()->ClearSelected();
1891         }
1892
1893         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1894         {
1895           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1896           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1897         }
1898
1899         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1900       }
1901       IsDragged = Standard_False;
1902       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1903
1904     case WM_RBUTTONUP:
1905       if (IsDragged && !DragFirst)
1906       {
1907         if (!GetActiveAISManipulator().IsNull())
1908         {
1909           GetActiveAISManipulator()->StopTransform (Standard_False);
1910           ViewerTest::GetAISContext()->ClearSelected();
1911         }
1912         IsDragged = Standard_False;
1913       }
1914       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1915
1916     case WM_LBUTTONDOWN:
1917       if (!GetActiveAISManipulator().IsNull())
1918       {
1919         IsDragged = ( fwKeys == MK_LBUTTON );
1920       }
1921       else
1922       {
1923         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1924       }
1925
1926       if (IsDragged)
1927       {
1928         DragFirst = Standard_True;
1929         X_ButtonPress = LOWORD(lParam);
1930         Y_ButtonPress = HIWORD(lParam);
1931       }
1932       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1933
1934     case WM_MOUSEMOVE:
1935       if (IsDragged)
1936       {
1937         X_Motion = LOWORD (lParam);
1938         Y_Motion = HIWORD (lParam);
1939         if (!GetActiveAISManipulator().IsNull())
1940         {
1941           if (DragFirst)
1942           {
1943             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1944           }
1945           else
1946           {
1947             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1948             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1949           }
1950         }
1951         else
1952         {
1953           bool toRedraw = false;
1954           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1955           {
1956             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1957             toRedraw = true;
1958           }
1959
1960           RECT aRect;
1961           if (GetClientRect (hwnd, &aRect))
1962           {
1963             int aHeight = aRect.bottom - aRect.top;
1964             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1965             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1966             toRedraw = true;
1967           }
1968           if (toRedraw)
1969           {
1970             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1971           }
1972         }
1973
1974         DragFirst = Standard_False;
1975       }
1976       else
1977         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1978       break;
1979
1980     default:
1981       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1982     }
1983     return 0;
1984   }
1985   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1986 }
1987
1988
1989 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
1990                                        UINT Msg,
1991                                        WPARAM wParam,
1992                                        LPARAM lParam )
1993 {
1994   static int Up = 1;
1995   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
1996   if (aView.IsNull())
1997   {
1998     return DefWindowProc( hwnd, Msg, wParam, lParam );
1999   }
2000
2001     PAINTSTRUCT    ps;
2002
2003     switch( Msg ) {
2004     case WM_PAINT:
2005       BeginPaint(hwnd, &ps);
2006       EndPaint(hwnd, &ps);
2007       VT_ProcessExpose();
2008       break;
2009
2010     case WM_SIZE:
2011       VT_ProcessConfigure();
2012       break;
2013     case WM_MOVE:
2014     case WM_MOVING:
2015     case WM_SIZING:
2016       switch (aView->RenderingParams().StereoMode)
2017       {
2018         case Graphic3d_StereoMode_RowInterlaced:
2019         case Graphic3d_StereoMode_ColumnInterlaced:
2020         case Graphic3d_StereoMode_ChessBoard:
2021           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2022           break;
2023         default:
2024           break;
2025       }
2026       break;
2027
2028     case WM_KEYDOWN:
2029       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2030       {
2031         char c[2];
2032         c[0] = (char) wParam;
2033         c[1] = '\0';
2034         if (wParam == VK_DELETE)
2035         {
2036           c[0] = THE_KEY_DELETE;
2037         }
2038         // comma
2039         else if (wParam == VK_OEM_COMMA)
2040         {
2041           c[0] = ',';
2042         }
2043         // dot
2044         else if (wParam == VK_OEM_PERIOD)
2045         {
2046           c[0] = '.';
2047         }
2048         else if (wParam == VK_DIVIDE)
2049         {
2050           c[0] = '/';
2051         }
2052         // dot
2053         else if (wParam == VK_MULTIPLY)
2054         {
2055           c[0] = '*';
2056         }
2057         VT_ProcessKeyPress (c);
2058       }
2059       break;
2060
2061     case WM_LBUTTONUP:
2062     case WM_MBUTTONUP:
2063     case WM_RBUTTONUP:
2064       Up = 1;
2065       VT_ProcessButton3Release();
2066       break;
2067
2068     case WM_LBUTTONDOWN:
2069     case WM_MBUTTONDOWN:
2070     case WM_RBUTTONDOWN:
2071       {
2072         WPARAM fwKeys = wParam;
2073
2074         Up = 0;
2075
2076         X_ButtonPress = LOWORD(lParam);
2077         Y_ButtonPress = HIWORD(lParam);
2078
2079         if (Msg == WM_LBUTTONDOWN)
2080         {
2081           if ((fwKeys & MK_CONTROL) != 0)
2082           {
2083             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2084           }
2085           else
2086           {
2087             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2088           }
2089         }
2090         else if (Msg == WM_RBUTTONDOWN)
2091         {
2092           // Start rotation
2093           VT_ProcessButton3Press();
2094         }
2095       }
2096       break;
2097
2098     case WM_MOUSEWHEEL:
2099     {
2100       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2101       if (wParam & MK_CONTROL)
2102       {
2103         if (aView->Camera()->IsStereo())
2104         {
2105           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2106           if (aFocus > 0.2
2107            && aFocus < 2.0)
2108           {
2109             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2110             aView->Redraw();
2111           }
2112         }
2113       }
2114       else
2115       {
2116         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2117       }
2118       break;
2119     }
2120
2121     case WM_MOUSEMOVE:
2122       {
2123         //cout << "\t WM_MOUSEMOVE" << endl;
2124         WPARAM fwKeys = wParam;
2125         X_Motion = LOWORD(lParam);
2126         Y_Motion = HIWORD(lParam);
2127
2128         if ( Up &&
2129           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2130           {
2131             Up = 0;
2132             X_ButtonPress = LOWORD(lParam);
2133             Y_ButtonPress = HIWORD(lParam);
2134
2135             if ((fwKeys & MK_RBUTTON) != 0) {
2136               // Start rotation
2137               VT_ProcessButton3Press();
2138             }
2139           }
2140
2141           if ((fwKeys & MK_CONTROL) != 0)
2142           {
2143             if ((fwKeys & MK_LBUTTON) != 0)
2144             {
2145               ProcessControlButton1Motion();
2146             }
2147             else if ((fwKeys & MK_MBUTTON) != 0
2148                  || ((fwKeys & MK_LBUTTON) != 0
2149                   && (fwKeys & MK_RBUTTON) != 0))
2150             {
2151               VT_ProcessControlButton2Motion();
2152             }
2153             else if ((fwKeys & MK_RBUTTON) != 0)
2154             {
2155               VT_ProcessControlButton3Motion();
2156             }
2157           }
2158           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2159           {
2160             VT_ProcessMotion();
2161           }
2162       }
2163       break;
2164
2165     default:
2166       return( DefWindowProc( hwnd, Msg, wParam, lParam ));
2167     }
2168     return 0L;
2169 }
2170
2171
2172
2173
2174 //==============================================================================
2175 //function : ViewerMainLoop
2176 //purpose  : Get a Event on the view and dispatch it
2177 //==============================================================================
2178
2179
2180 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2181 {
2182   Ppick = (argc > 0)? 1 : 0;
2183   Pargc = argc;
2184   Pargv = argv;
2185
2186   if ( Ppick ) {
2187     MSG msg;
2188     msg.wParam = 1;
2189
2190     cout << "Start picking" << endl;
2191
2192     while ( Ppick == 1 ) {
2193       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2194       if (GetMessage(&msg, NULL, 0, 0) ) {
2195         TranslateMessage(&msg);
2196         DispatchMessage(&msg);
2197       }
2198     }
2199
2200     cout << "Picking done" << endl;
2201   }
2202
2203   return Ppick;
2204 }
2205
2206 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2207
2208 int min( int a, int b )
2209 {
2210   if( a<b )
2211     return a;
2212   else
2213     return b;
2214 }
2215
2216 int max( int a, int b )
2217 {
2218   if( a>b )
2219     return a;
2220   else
2221     return b;
2222 }
2223
2224 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2225
2226 {
2227   static XEvent aReport;
2228   Standard_Boolean pick = argc > 0;
2229   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2230   XNextEvent (aDisplay, &aReport);
2231
2232   // Handle event for the chosen display connection
2233   switch (aReport.type) {
2234       case ClientMessage:
2235         {
2236           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2237           {
2238             // Close the window
2239             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2240           }
2241         }
2242         return 0;
2243      case FocusIn:
2244       {
2245          // Activate inactive view
2246          Window aWindow = GetWindowHandle(VT_GetWindow());
2247          if(aWindow != aReport.xfocus.window)
2248          {
2249            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2250          }
2251       }
2252       break;
2253       case Expose:
2254         {
2255           VT_ProcessExpose();
2256         }
2257         break;
2258       case ConfigureNotify:
2259         {
2260           VT_ProcessConfigure();
2261         }
2262         break;
2263       case KeyPress:
2264         {
2265
2266           KeySym ks_ret ;
2267           char buf_ret[11] ;
2268           int ret_len ;
2269           XComposeStatus status_in_out;
2270
2271           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2272             (char *) buf_ret , 10 ,
2273             &ks_ret , &status_in_out ) ;
2274
2275
2276           buf_ret[ret_len] = '\0' ;
2277
2278           if (ret_len)
2279           {
2280             VT_ProcessKeyPress (buf_ret);
2281           }
2282         }
2283         break;
2284       case ButtonPress:
2285         {
2286           X_ButtonPress = aReport.xbutton.x;
2287           Y_ButtonPress = aReport.xbutton.y;
2288
2289           if (aReport.xbutton.button == Button1)
2290           {
2291             if (aReport.xbutton.state & ControlMask)
2292             {
2293               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2294             }
2295             else
2296             {
2297               IsDragged = Standard_True;
2298               DragFirst = Standard_True;
2299             }
2300           }
2301           else if (aReport.xbutton.button == Button3)
2302           {
2303             // Start rotation
2304             VT_ProcessButton3Press();
2305           }
2306         }
2307         break;
2308       case ButtonRelease:
2309         {
2310           if( IsDragged )
2311           {
2312             if( !DragFirst )
2313             {
2314               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2315               {
2316                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2317                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2318               }
2319             }
2320
2321             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2322             if( aContext.IsNull() )
2323             {
2324               cout << "The context is null. Please use vinit before createmesh" << endl;
2325               return 0;
2326             }
2327
2328             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2329             if( aReport.xbutton.button==1 )
2330               if( DragFirst )
2331                 if( ShiftPressed )
2332                 {
2333                   aContext->ShiftSelect();
2334                 }
2335                 else
2336                 {
2337                   aContext->Select();
2338                 }
2339               else
2340                 if( ShiftPressed )
2341                 {
2342                   aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2343                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2344                     ViewerTest::CurrentView());
2345                 }
2346                 else
2347                 {
2348                   aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2349                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2350                     ViewerTest::CurrentView() );
2351                 }
2352             else
2353               VT_ProcessButton3Release();
2354
2355             IsDragged = Standard_False;
2356           }
2357           else
2358             VT_ProcessButton3Release();
2359         }
2360         break;
2361       case MotionNotify:
2362         {
2363           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2364           {
2365             break;
2366           }
2367           if( IsDragged )
2368           {
2369             if( !DragFirst )
2370             {
2371               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2372               {
2373                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2374               }
2375             }
2376
2377             X_Motion = aReport.xmotion.x;
2378             Y_Motion = aReport.xmotion.y;
2379             DragFirst = Standard_False;
2380
2381             Window aWindow = GetWindowHandle(VT_GetWindow());
2382             Window aRoot;
2383             int anX, anY;
2384             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2385             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2386             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2387             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2388             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2389           }
2390           else
2391           {
2392             X_Motion = aReport.xmotion.x;
2393             Y_Motion = aReport.xmotion.y;
2394
2395             // remove all the ButtonMotionMaskr
2396             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2397
2398             if ( aReport.xmotion.state & ControlMask ) {
2399               if ( aReport.xmotion.state & Button1Mask ) {
2400                 ProcessControlButton1Motion();
2401               }
2402               else if ( aReport.xmotion.state & Button2Mask ) {
2403                 VT_ProcessControlButton2Motion();
2404               }
2405               else if ( aReport.xmotion.state & Button3Mask ) {
2406                 VT_ProcessControlButton3Motion();
2407               }
2408             }
2409             else
2410             {
2411               VT_ProcessMotion();
2412             }
2413           }
2414         }
2415         break;
2416 }
2417 return pick;
2418 }
2419
2420 //==============================================================================
2421 //function : VProcessEvents
2422 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2423 //       event in the Viewer window
2424 //==============================================================================
2425
2426 static void VProcessEvents(ClientData,int)
2427 {
2428   NCollection_Vector<int> anEventNumbers;
2429   // Get number of messages from every display
2430   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2431        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2432   {
2433     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2434   }
2435     // Handle events for every display
2436   int anEventIter = 0;
2437   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2438        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2439   {
2440     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2441          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2442     {
2443       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2444       int anEventResult = ViewerMainLoop( 0, NULL);
2445       // If window is closed or context was not found finish current event processing loop
2446       if (!anEventResult)
2447         return;
2448     }
2449   }
2450
2451   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2452
2453 }
2454 #endif
2455
2456 //==============================================================================
2457 //function : OSWindowSetup
2458 //purpose  : Setup for the X11 window to be able to cath the event
2459 //==============================================================================
2460
2461
2462 static void OSWindowSetup()
2463 {
2464 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2465   // X11
2466
2467   Window  window   = VT_GetWindow()->XWindow();
2468   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2469   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2470   XSynchronize(aDisplay, 1);
2471
2472   // X11 : For keyboard on SUN
2473   XWMHints wmhints;
2474   wmhints.flags = InputHint;
2475   wmhints.input = 1;
2476
2477   XSetWMHints( aDisplay, window, &wmhints);
2478
2479   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2480     ButtonPressMask | ButtonReleaseMask |
2481     StructureNotifyMask |
2482     PointerMotionMask |
2483     Button1MotionMask | Button2MotionMask |
2484     Button3MotionMask | FocusChangeMask
2485     );
2486   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2487   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2488
2489   XSynchronize(aDisplay, 0);
2490
2491 #else
2492   // _WIN32
2493 #endif
2494
2495 }
2496
2497 //==============================================================================
2498 //function : VFit
2499
2500 //purpose  : Fitall, no DRAW arguments
2501 //Draw arg : No args
2502 //==============================================================================
2503
2504 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv)
2505 {
2506   if (theArgc > 2)
2507   {
2508     std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl;
2509   }
2510
2511   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2512
2513   if (theArgc == 2)
2514   {
2515     TCollection_AsciiString anArg (theArgv[1]);
2516     anArg.LowerCase();
2517     if (anArg == "-selected")
2518     {
2519       ViewerTest::GetAISContext()->FitSelected (aView);
2520       return 0;
2521     }
2522   }
2523   if (aView.IsNull() == Standard_False) {
2524
2525     aView->FitAll();
2526   }
2527   return 0;
2528 }
2529
2530 //=======================================================================
2531 //function : VFitArea
2532 //purpose  : Fit view to show area located between two points
2533 //         : given in world 2D or 3D coordinates.
2534 //=======================================================================
2535 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2536 {
2537   Handle(V3d_View) aView = ViewerTest::CurrentView();
2538   if (aView.IsNull())
2539   {
2540     std::cerr << theArgVec[0] << "Error: No active view.\n";
2541     return 1;
2542   }
2543
2544   // Parse arguments.
2545   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2546   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2547
2548   if (theArgNb == 5)
2549   {
2550     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2551     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2552     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2553     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2554   }
2555   else if (theArgNb == 7)
2556   {
2557     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2558     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2559     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2560     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2561     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2562     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2563   }
2564   else
2565   {
2566     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2567     theDI.PrintHelp(theArgVec[0]);
2568     return 1;
2569   }
2570
2571   // Convert model coordinates to view space
2572   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2573   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2574   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2575
2576   // Determine fit area
2577   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2578   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2579
2580   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2581
2582   if (aDiagonal < Precision::Confusion())
2583   {
2584     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2585     return 1;
2586   }
2587
2588   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2589   return 0;
2590 }
2591
2592 //==============================================================================
2593 //function : VZFit
2594 //purpose  : ZFitall, no DRAW arguments
2595 //Draw arg : No args
2596 //==============================================================================
2597 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2598 {
2599   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2600
2601   if (aCurrentView.IsNull())
2602   {
2603     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2604     return 1;
2605   }
2606
2607   if (theArgsNb == 1)
2608   {
2609     aCurrentView->ZFitAll();
2610     aCurrentView->Redraw();
2611     return 0;
2612   }
2613
2614   Standard_Real aScale = 1.0;
2615
2616   if (theArgsNb >= 2)
2617   {
2618     aScale = Draw::Atoi (theArgVec[1]);
2619   }
2620
2621   aCurrentView->ZFitAll (aScale);
2622   aCurrentView->Redraw();
2623
2624   return 0;
2625 }
2626
2627 //==============================================================================
2628 //function : VRepaint
2629 //purpose  :
2630 //==============================================================================
2631 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2632 {
2633   Handle(V3d_View) V = ViewerTest::CurrentView();
2634   if ( !V.IsNull() ) V->Redraw(); return 0;
2635 }
2636
2637 //==============================================================================
2638 //function : VClear
2639 //purpose  : Remove all the object from the viewer
2640 //Draw arg : No args
2641 //==============================================================================
2642
2643 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2644 {
2645   Handle(V3d_View) V = ViewerTest::CurrentView();
2646   if(!V.IsNull())
2647     ViewerTest::Clear();
2648   return 0;
2649 }
2650
2651 //==============================================================================
2652 //function : VPick
2653 //purpose  :
2654 //==============================================================================
2655
2656 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2657 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2658
2659 if ( argc < 4 ) {
2660   di << argv[0] << "Invalid number of arguments\n";
2661   return 1;
2662 }
2663
2664 while (ViewerMainLoop( argc, argv)) {
2665 }
2666
2667 return 0;
2668 }
2669
2670 //==============================================================================
2671 //function : VSetBg
2672 //purpose  : Load image as background
2673 //==============================================================================
2674
2675 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2676 {
2677   if (argc < 2 || argc > 3)
2678   {
2679     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2680     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2681     return 1;
2682   }
2683
2684   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2685   if(AISContext.IsNull())
2686   {
2687     di << "use 'vinit' command before " << argv[0] << "\n";
2688     return 1;
2689   }
2690
2691   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2692   if (argc == 3)
2693   {
2694     const char* szType = argv[2];
2695     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2696     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2697     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2698     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2699     else
2700     {
2701       di << "Wrong fill type : " << szType << "\n";
2702       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2703       return 1;
2704     }
2705   }
2706
2707   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2708   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2709
2710   return 0;
2711 }
2712
2713 //==============================================================================
2714 //function : VSetBgMode
2715 //purpose  : Change background image fill type
2716 //==============================================================================
2717
2718 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2719 {
2720   if (argc != 2)
2721   {
2722     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2723     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2724     return 1;
2725   }
2726
2727   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2728   if(AISContext.IsNull())
2729   {
2730     di << "use 'vinit' command before " << argv[0] << "\n";
2731     return 1;
2732   }
2733   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2734   const char* szType = argv[1];
2735   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2736   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2737   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2738   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2739   else
2740   {
2741     di << "Wrong fill type : " << szType << "\n";
2742     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2743     return 1;
2744   }
2745   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2746   V3dView->SetBgImageStyle(aFillType, Standard_True);
2747   return 0;
2748 }
2749
2750 //==============================================================================
2751 //function : VSetGradientBg
2752 //purpose  : Mount gradient background
2753 //==============================================================================
2754 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2755 {
2756   if (argc != 8 )
2757   {
2758     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2759     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2760     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2761     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2762     return 1;
2763   }
2764
2765   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2766   if(AISContext.IsNull())
2767   {
2768     di << "use 'vinit' command before " << argv[0] << "\n";
2769     return 1;
2770   }
2771   if (argc == 8)
2772   {
2773
2774     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2775     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2776     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2777     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2778
2779     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2780     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2781     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2782
2783     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2784     int aType = Draw::Atoi(argv[7]);
2785     if( aType < 0 || aType > 8 )
2786     {
2787       di << "Wrong fill type \n";
2788       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2789       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2790       return 1;
2791     }
2792
2793     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2794
2795     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2796     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2797   }
2798
2799   return 0;
2800 }
2801
2802 //==============================================================================
2803 //function : VSetGradientBgMode
2804 //purpose  : Change gradient background fill style
2805 //==============================================================================
2806 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2807 {
2808   if (argc != 2 )
2809   {
2810     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2811     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2812     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2813     return 1;
2814   }
2815
2816   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2817   if(AISContext.IsNull())
2818   {
2819     di << "use 'vinit' command before " << argv[0] << "\n";
2820     return 1;
2821   }
2822   if (argc == 2)
2823   {
2824     int aType = Draw::Atoi(argv[1]);
2825     if( aType < 0 || aType > 8 )
2826     {
2827       di << "Wrong fill type \n";
2828       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2829       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2830       return 1;
2831     }
2832
2833     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2834
2835     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2836     V3dView->SetBgGradientStyle( aMethod, 1 );
2837   }
2838
2839   return 0;
2840 }
2841
2842 //==============================================================================
2843 //function : VSetColorBg
2844 //purpose  : Set color background
2845 //==============================================================================
2846 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2847 {
2848   if (argc != 4 )
2849   {
2850     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2851     di << "R,G,B = [0..255]\n";
2852     return 1;
2853   }
2854
2855   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2856   if(AISContext.IsNull())
2857   {
2858     di << "use 'vinit' command before " << argv[0] << "\n";
2859     return 1;
2860   }
2861   if (argc == 4)
2862   {
2863
2864     Standard_Real R = Draw::Atof(argv[1])/255.;
2865     Standard_Real G = Draw::Atof(argv[2])/255.;
2866     Standard_Real B = Draw::Atof(argv[3])/255.;
2867     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2868
2869     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2870     V3dView->SetBackgroundColor( aColor );
2871     V3dView->Update();
2872   }
2873
2874   return 0;
2875 }
2876
2877 //==============================================================================
2878 //function : VSetDefaultBg
2879 //purpose  : Set default viewer background fill color
2880 //==============================================================================
2881 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2882 {
2883   if (theArgNb != 4
2884    && theArgNb != 8)
2885   {
2886     std::cout << "Error: wrong syntax! See usage:\n";
2887     theDI.PrintHelp (theArgVec[0]);
2888     return 1;
2889   }
2890
2891   ViewerTest_DefaultBackground.FillMethod =
2892     theArgNb == 4 ? Aspect_GFM_NONE
2893                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2894
2895   if (theArgNb == 4)
2896   {
2897     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2898     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2899     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2900     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2901   }
2902   else
2903   {
2904     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2905     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2906     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2907     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2908
2909     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2910     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2911     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2912     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2913   }
2914
2915   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2916        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2917   {
2918     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2919     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2920     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2921                                          ViewerTest_DefaultBackground.GradientColor2,
2922                                          ViewerTest_DefaultBackground.FillMethod);
2923   }
2924
2925   return 0;
2926 }
2927
2928 //==============================================================================
2929 //function : VScale
2930 //purpose  : View Scaling
2931 //==============================================================================
2932
2933 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2934 {
2935   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2936   if ( V3dView.IsNull() ) return 1;
2937
2938   if ( argc != 4 ) {
2939     di << argv[0] << "Invalid number of arguments\n";
2940     return 1;
2941   }
2942   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2943   return 0;
2944 }
2945 //==============================================================================
2946 //function : VZBuffTrihedron
2947 //purpose  :
2948 //==============================================================================
2949
2950 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2951                             Standard_Integer  theArgNb,
2952                             const char**      theArgVec)
2953 {
2954   Handle(V3d_View) aView = ViewerTest::CurrentView();
2955   if (aView.IsNull())
2956   {
2957     std::cout << "Error: no active viewer!\n";
2958     return 1;
2959   }
2960
2961   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2962
2963   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2964   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2965   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2966   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2967   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2968   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2969   Standard_Real                 aScale        = 0.1;
2970   Standard_Real                 aSizeRatio    = 0.8;
2971   Standard_Real                 anArrowDiam   = 0.05;
2972   Standard_Integer              aNbFacets     = 12;
2973   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2974   {
2975     Standard_CString        anArg = theArgVec[anArgIter];
2976     TCollection_AsciiString aFlag (anArg);
2977     aFlag.LowerCase();
2978     if (anUpdateTool.parseRedrawMode (aFlag))
2979     {
2980       continue;
2981     }
2982     else if (aFlag == "-on")
2983     {
2984       continue;
2985     }
2986     else if (aFlag == "-off")
2987     {
2988       aView->TriedronErase();
2989       return 0;
2990     }
2991     else if (aFlag == "-pos"
2992           || aFlag == "-position"
2993           || aFlag == "-corner")
2994     {
2995       if (++anArgIter >= theArgNb)
2996       {
2997         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
2998         return 1;
2999       }
3000
3001       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3002       aPosName.LowerCase();
3003       if (aPosName == "center")
3004       {
3005         aPosition = Aspect_TOTP_CENTER;
3006       }
3007       else if (aPosName == "left_lower"
3008             || aPosName == "lower_left"
3009             || aPosName == "leftlower"
3010             || aPosName == "lowerleft")
3011       {
3012         aPosition = Aspect_TOTP_LEFT_LOWER;
3013       }
3014       else if (aPosName == "left_upper"
3015             || aPosName == "upper_left"
3016             || aPosName == "leftupper"
3017             || aPosName == "upperleft")
3018       {
3019         aPosition = Aspect_TOTP_LEFT_UPPER;
3020       }
3021       else if (aPosName == "right_lower"
3022             || aPosName == "lower_right"
3023             || aPosName == "rightlower"
3024             || aPosName == "lowerright")
3025       {
3026         aPosition = Aspect_TOTP_RIGHT_LOWER;
3027       }
3028       else if (aPosName == "right_upper"
3029             || aPosName == "upper_right"
3030             || aPosName == "rightupper"
3031             || aPosName == "upperright")
3032       {
3033         aPosition = Aspect_TOTP_RIGHT_UPPER;
3034       }
3035       else
3036       {
3037         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3038         return 1;
3039       }
3040     }
3041     else if (aFlag == "-type")
3042     {
3043       if (++anArgIter >= theArgNb)
3044       {
3045         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3046         return 1;
3047       }
3048
3049       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3050       aTypeName.LowerCase();
3051       if (aTypeName == "wireframe"
3052        || aTypeName == "wire")
3053       {
3054         aVisType = V3d_WIREFRAME;
3055       }
3056       else if (aTypeName == "zbuffer"
3057             || aTypeName == "shaded")
3058       {
3059         aVisType = V3d_ZBUFFER;
3060       }
3061       else
3062       {
3063         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3064       }
3065     }
3066     else if (aFlag == "-scale")
3067     {
3068       if (++anArgIter >= theArgNb)
3069       {
3070         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3071         return 1;
3072       }
3073
3074       aScale = Draw::Atof (theArgVec[anArgIter]);
3075     }
3076     else if (aFlag == "-size"
3077           || aFlag == "-sizeratio")
3078     {
3079       if (++anArgIter >= theArgNb)
3080       {
3081         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3082         return 1;
3083       }
3084
3085       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3086     }
3087     else if (aFlag == "-arrowdiam"
3088           || aFlag == "-arrowdiameter")
3089     {
3090       if (++anArgIter >= theArgNb)
3091       {
3092         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3093         return 1;
3094       }
3095
3096       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3097     }
3098     else if (aFlag == "-nbfacets")
3099     {
3100       if (++anArgIter >= theArgNb)
3101       {
3102         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3103         return 1;
3104       }
3105
3106       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3107     }
3108     else if (aFlag == "-colorlabel"
3109           || aFlag == "-colorlabels")
3110     {
3111       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3112                                                            theArgVec + anArgIter + 1,
3113                                                            aLabelsColor);
3114       if (aNbParsed == 0)
3115       {
3116         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3117         return 1;
3118       }
3119       anArgIter += aNbParsed;
3120     }
3121     else if (aFlag == "-colorarrowx")
3122     {
3123       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3124                                                            theArgVec + anArgIter + 1,
3125                                                            anArrowColorX);
3126       if (aNbParsed == 0)
3127       {
3128         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3129         return 1;
3130       }
3131       anArgIter += aNbParsed;
3132     }
3133     else if (aFlag == "-colorarrowy")
3134     {
3135       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3136                                                            theArgVec + anArgIter + 1,
3137                                                            anArrowColorY);
3138       if (aNbParsed == 0)
3139       {
3140         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3141         return 1;
3142       }
3143       anArgIter += aNbParsed;
3144     }
3145     else if (aFlag == "-colorarrowz")
3146     {
3147       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3148                                                            theArgVec + anArgIter + 1,
3149                                                            anArrowColorZ);
3150       if (aNbParsed == 0)
3151       {
3152         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3153         return 1;
3154       }
3155       anArgIter += aNbParsed;
3156     }
3157     else
3158     {
3159       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3160       return 1;
3161     }
3162   }
3163
3164   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3165                                aSizeRatio, anArrowDiam, aNbFacets);
3166   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3167   aView->ZFitAll();
3168   return 0;
3169 }
3170
3171 //==============================================================================
3172 //function : VRotate
3173 //purpose  : Camera Rotating
3174 //==============================================================================
3175
3176 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3177 {
3178   Handle(V3d_View) aView = ViewerTest::CurrentView();
3179   if (aView.IsNull())
3180   {
3181     std::cout << "No active view!\n";
3182     return 1;
3183   }
3184
3185   Standard_Boolean hasFlags = Standard_False;
3186   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3187   {
3188     Standard_CString        anArg (theArgVec[anArgIter]);
3189     TCollection_AsciiString aFlag (anArg);
3190     aFlag.LowerCase();
3191     if (aFlag == "-mousestart"
3192      || aFlag == "-mousefrom")
3193     {
3194       hasFlags = Standard_True;
3195       if (anArgIter + 2 >= theArgNb)
3196       {
3197         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3198         return 1;
3199       }
3200
3201       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3202       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3203       aView->StartRotation (anX, anY);
3204     }
3205     else if (aFlag == "-mousemove")
3206     {
3207       hasFlags = Standard_True;
3208       if (anArgIter + 2 >= theArgNb)
3209       {
3210         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3211         return 1;
3212       }
3213
3214       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3215       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3216       aView->Rotation (anX, anY);
3217     }
3218     else if (theArgNb != 4
3219           && theArgNb != 7)
3220     {
3221       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3222       return 1;
3223     }
3224   }
3225
3226   if (hasFlags)
3227   {
3228     return 0;
3229   }
3230   else if (theArgNb == 4)
3231   {
3232     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3233     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3234     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3235     aView->Rotate (anAX, anAY, anAZ);
3236     return 0;
3237   }
3238   else if (theArgNb == 7)
3239   {
3240     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3241     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3242     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3243
3244     Standard_Real anX = Draw::Atof (theArgVec[4]);
3245     Standard_Real anY = Draw::Atof (theArgVec[5]);
3246     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3247
3248     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3249     return 0;
3250   }
3251
3252   std::cout << "Error: Invalid number of arguments\n";
3253   return 1;
3254 }
3255
3256 //==============================================================================
3257 //function : VZoom
3258 //purpose  : View zoom in / out (relative to current zoom)
3259 //==============================================================================
3260
3261 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3262   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3263   if ( V3dView.IsNull() ) {
3264     return 1;
3265   }
3266
3267   if ( argc == 2 ) {
3268     Standard_Real coef = Draw::Atof(argv[1]);
3269     if ( coef <= 0.0 ) {
3270       di << argv[1] << "Invalid value\n";
3271       return 1;
3272     }
3273     V3dView->SetZoom( Draw::Atof(argv[1]) );
3274     return 0;
3275   } else {
3276     di << argv[0] << " Invalid number of arguments\n";
3277     return 1;
3278   }
3279 }
3280
3281 //==============================================================================
3282 //function : VPan
3283 //purpose  : View panning (in pixels)
3284 //==============================================================================
3285
3286 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3287   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3288   if ( V3dView.IsNull() ) return 1;
3289
3290   if ( argc == 3 ) {
3291     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3292     return 0;
3293   } else {
3294     di << argv[0] << " Invalid number of arguments\n";
3295     return 1;
3296   }
3297 }
3298
3299 //==============================================================================
3300 //function : VPlace
3301 //purpose  : Place the point (in pixels) at the center of the window
3302 //==============================================================================
3303 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3304 {
3305   Handle(V3d_View) aView = ViewerTest::CurrentView();
3306   if (aView.IsNull())
3307   {
3308     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3309     return 1;
3310   }
3311
3312   if (theArgNb != 3)
3313   {
3314     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3315     return 1;
3316   }
3317
3318   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3319
3320   return 0;
3321 }
3322
3323 //==============================================================================
3324 //function : VExport
3325 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3326 //==============================================================================
3327
3328 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3329 {
3330   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3331   if (V3dView.IsNull())
3332     return 1;
3333
3334   if (argc == 1)
3335   {
3336     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3337     return 1;
3338   }
3339
3340   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3341   TCollection_AsciiString aFormatStr;
3342
3343   TCollection_AsciiString aFileName (argv[1]);
3344   Standard_Integer aLen = aFileName.Length();
3345
3346   if (argc > 2)
3347   {
3348     aFormatStr = TCollection_AsciiString (argv[2]);
3349   }
3350   else if (aLen >= 4)
3351   {
3352     if (aFileName.Value (aLen - 2) == '.')
3353     {
3354       aFormatStr = aFileName.ToCString() + aLen - 2;
3355     }
3356     else if (aFileName.Value (aLen - 3) == '.')
3357     {
3358       aFormatStr = aFileName.ToCString() + aLen - 3;
3359     }
3360     else
3361     {
3362       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3363       return 1;
3364     }
3365   }
3366   else
3367   {
3368     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3369     return 1;
3370   }
3371
3372   aFormatStr.UpperCase();
3373   if (aFormatStr == "PS")
3374     anExpFormat = Graphic3d_EF_PostScript;
3375   else if (aFormatStr == "EPS")
3376     anExpFormat = Graphic3d_EF_EnhPostScript;
3377   else if (aFormatStr == "TEX")
3378     anExpFormat = Graphic3d_EF_TEX;
3379   else if (aFormatStr == "PDF")
3380     anExpFormat = Graphic3d_EF_PDF;
3381   else if (aFormatStr == "SVG")
3382     anExpFormat = Graphic3d_EF_SVG;
3383   else if (aFormatStr == "PGF")
3384     anExpFormat = Graphic3d_EF_PGF;
3385   else if (aFormatStr == "EMF")
3386     anExpFormat = Graphic3d_EF_EMF;
3387   else
3388   {
3389     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3390     return 1;
3391   }
3392
3393   try
3394   {
3395   Standard_DISABLE_DEPRECATION_WARNINGS
3396     if (!V3dView->Export (argv[1], anExpFormat))
3397   Standard_ENABLE_DEPRECATION_WARNINGS
3398     {
3399       di << "Error: export of image to " << aFormatStr << " failed!\n";
3400     }
3401   }
3402   catch (Standard_Failure)
3403   {
3404     di << "Error: export of image to " << aFormatStr << " failed";
3405     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3406   }
3407   return 0;
3408 }
3409
3410 //==============================================================================
3411 //function : VColorScale
3412 //purpose  : representation color scale
3413 //==============================================================================
3414
3415 static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
3416                                     const TCollection_AsciiString& theGreen,
3417                                     const TCollection_AsciiString& theBlue,
3418                                                     Standard_Real& theRedValue,
3419                                                     Standard_Real& theGreenValue,
3420                                                     Standard_Real& theBlueValue)
3421 {
3422   if (!theRed.IsRealValue()
3423    || !theGreen.IsRealValue()
3424    || !theBlue.IsRealValue())
3425   {
3426     std::cout << "Error: RGB color values should be real!\n";
3427     return Standard_True;
3428   }
3429   theRedValue = theRed    .RealValue();
3430   theGreenValue = theGreen.RealValue();
3431   theBlueValue = theBlue  .RealValue();
3432   if (theRedValue < 0.0 || theRedValue > 1.0
3433    || theGreenValue < 0.0 || theGreenValue > 1.0
3434    || theBlueValue < 0.0 || theBlueValue > 1.0)
3435   {
3436     std::cout << "Error: RGB color values should be within range 0..1!\n";
3437     return Standard_True;
3438   }
3439   return Standard_False;
3440 }
3441
3442 static int VColorScale (Draw_Interpretor& theDI,
3443                         Standard_Integer  theArgNb,
3444                         const char**      theArgVec)
3445 {
3446   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3447   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3448   if (aContext.IsNull())
3449   {
3450     std::cout << "Error: no active view!\n";
3451     return 1;
3452   }
3453   if (theArgNb <= 1)
3454   {
3455     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3456     return 1;
3457   }
3458
3459   Handle(AIS_ColorScale) aCS;
3460   // find object
3461   Handle(AIS_InteractiveObject) anIObj;
3462   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3463   {
3464     aCS = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3465     if (aCS.IsNull())
3466     {
3467       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3468       return 1;
3469     }
3470   }
3471   else
3472   {
3473     aCS = new AIS_ColorScale();
3474     GetMapOfAIS().Bind (aCS,theArgVec[1]);
3475   }
3476
3477   if (aCS->ZLayer() != Graphic3d_ZLayerId_TopOSD)
3478   {
3479     aCS->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3480   }
3481   if (aCS->GetTransformPersistenceMode() != Graphic3d_TMF_2d)
3482   {
3483     aContext->SetTransformPersistence (aCS, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
3484   }
3485
3486   Standard_Real                   aMinRange    = aCS->GetMin();
3487   Standard_Real                   aMaxRange    = aCS->GetMax();
3488   Standard_Integer                aBreadth     = aCS->GetBreadth();
3489   Standard_Integer                aHeight      = aCS->GetHeight();
3490   Standard_Integer                aNbIntervals = aCS->GetNumberOfIntervals();
3491   Standard_Integer                aTextHeight  = aCS->GetTextHeight();
3492   Aspect_TypeOfColorScalePosition aLabPosition = aCS->GetLabelPosition();
3493   Standard_Integer                aPosX = aCS->GetXPosition();
3494   Standard_Integer                aPosY = aCS->GetYPosition();
3495
3496   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3497
3498   if (theArgNb <= 2)
3499   {
3500     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3501           << "Min range: " << aMinRange << "\n"
3502           << "Max range: " << aMaxRange << "\n"
3503           << "Number of intervals: " << aNbIntervals << "\n"
3504           << "Text height: " << aTextHeight << "\n"
3505           << "Color scale position: " << aPosX <<" "<< aPosY<< "\n"
3506           << "Color scale title: " << aCS->GetTitle() << "\n"
3507           << "Label position: ";
3508     switch (aLabPosition)
3509     {
3510       case Aspect_TOCSP_NONE:
3511         theDI << "None\n";
3512         break;
3513       case Aspect_TOCSP_LEFT:
3514         theDI << "Left\n";
3515         break;
3516       case Aspect_TOCSP_RIGHT:
3517         theDI << "Right\n";
3518         break;
3519       case Aspect_TOCSP_CENTER:
3520         theDI << "Center\n";
3521         break;
3522     }
3523     return 0;
3524   }
3525
3526   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3527   {
3528     Standard_CString        anArg = theArgVec[anArgIter];
3529     TCollection_AsciiString aFlag (anArg);
3530     aFlag.LowerCase();
3531     if (anUpdateTool.parseRedrawMode (aFlag))
3532     {
3533       continue;
3534     }
3535     else if (aFlag == "-range")
3536     {
3537       if (anArgIter + 3 >= theArgNb)
3538       {
3539         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3540         return 1;
3541       }
3542
3543       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3544       TCollection_AsciiString anArg2 (theArgVec[++anArgIter]);
3545       TCollection_AsciiString anArg3 (theArgVec[++anArgIter]);
3546       if (!anArg1.IsRealValue())
3547       {
3548         std::cout << "Error: the minRange value should be real!\n";
3549         return 1;
3550       }
3551       else if (!anArg2.IsRealValue())
3552       {
3553         std::cout << "Error: the maxRange value should be real!\n";
3554         return 1;
3555       }
3556       else if (!anArg3.IsIntegerValue())
3557       {
3558         std::cout << "Error: the number of intervals should be integer!\n";
3559         return 1;
3560       }
3561
3562       aMinRange    = anArg1.RealValue();
3563       aMaxRange    = anArg2.RealValue();
3564       aNbIntervals = anArg3.IntegerValue();
3565     }
3566     else if (aFlag == "-font")
3567     {
3568       if (anArgIter + 1 >= theArgNb)
3569       {
3570         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3571         return 1;
3572       }
3573       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3574       if (!aFontArg.IsIntegerValue())
3575       {
3576         std::cout << "Error: HeightFont value should be integer!\n";
3577         return 1;
3578       }
3579
3580       aTextHeight = aFontArg.IntegerValue();
3581       anArgIter += 1;
3582     }
3583     else if (aFlag == "-textpos")
3584     {
3585       if (anArgIter + 1 >= theArgNb)
3586       {
3587         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3588         return 1;
3589       }
3590       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3591       aTextPosArg.LowerCase();
3592       if (aTextPosArg == "none")
3593       {
3594         aLabPosition = Aspect_TOCSP_NONE;
3595       }
3596       else if (aTextPosArg == "left")
3597       {
3598         aLabPosition = Aspect_TOCSP_LEFT;
3599       }
3600       else if (aTextPosArg == "right")
3601       {
3602         aLabPosition = Aspect_TOCSP_RIGHT;
3603       }
3604       else if (aTextPosArg == "center")
3605       {
3606         aLabPosition = Aspect_TOCSP_CENTER;
3607       }
3608       else
3609       {
3610         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3611         return 1;
3612       }
3613     }
3614     else if (aFlag == "-logarithmic"
3615           || aFlag == "-log")
3616     {
3617       if (anArgIter + 1 >= theArgNb)
3618       {
3619         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3620         return 1;
3621       }
3622       Standard_Boolean IsLog;
3623       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3624       {
3625         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3626         return 1;
3627       }
3628       aCS->SetLogarithmic (IsLog);
3629     }
3630     else if (aFlag == "-xy")
3631     {
3632       if (anArgIter + 2 >= theArgNb)
3633       {
3634         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3635         return 1;
3636       }
3637
3638       TCollection_AsciiString aX (theArgVec[++anArgIter]);
3639       TCollection_AsciiString aY (theArgVec[++anArgIter]);
3640       if (!aX.IsIntegerValue()
3641        || !aY.IsIntegerValue())
3642       {
3643         std::cout << "Error: coordinates should be integer values!\n";
3644         return 1;
3645       }
3646
3647       aPosX = aX.IntegerValue();
3648       aPosY = aY.IntegerValue();
3649     }
3650     else if (aFlag == "-width"
3651           || aFlag == "-w")
3652     {
3653       if (anArgIter + 1 >= theArgNb)
3654       {
3655         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3656         return 1;
3657       }
3658
3659       TCollection_AsciiString aW (theArgVec[++anArgIter]);
3660       if (!aW.IsIntegerValue())
3661       {
3662         std::cout << "Error: a width should be an integer value!\n";
3663         return 1;
3664       }
3665
3666       aBreadth = aW.IntegerValue();
3667     }
3668     else if (aFlag == "-height"
3669           || aFlag == "-h")
3670     {
3671       if (anArgIter + 1 >= theArgNb)
3672       {
3673         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3674         return 1;
3675       }
3676
3677       TCollection_AsciiString aH (theArgVec[++anArgIter]);
3678       if (!aH.IsIntegerValue())
3679       {
3680         std::cout << "Error: a width should be an integer value!\n";
3681         return 1;
3682       }
3683
3684       aHeight = aH.IntegerValue();
3685     }
3686     else if (aFlag == "-color")
3687     {
3688       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3689       {
3690         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3691         return 1;
3692       }
3693
3694       Quantity_NameOfColor aColorName;
3695       if (anArgIter + 4 >= theArgNb)
3696       {
3697         if (anArgIter + 2 >= theArgNb)
3698         {
3699           std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3700           return 1;
3701         }
3702         else if (!Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3703         {
3704           std::cout << "Error: wrong color name: '" << theArgVec[anArgIter + 2] << "' !\n";
3705           return 1;
3706         }
3707       }
3708
3709       TCollection_AsciiString anInd (theArgVec[anArgIter + 1]);
3710       if (!anInd.IsIntegerValue())
3711       {
3712         std::cout << "Error: Index value should be integer!\n";
3713         return 1;
3714       }
3715
3716       Standard_Integer anIndex = anInd.IntegerValue();
3717       if (anIndex <= 0 || anIndex > aNbIntervals)
3718       {
3719         std::cout << "Error: Index value should be within range 1.." << aNbIntervals <<"!\n";
3720         return 1;
3721       }
3722
3723       if (Quantity_Color::ColorFromName (theArgVec[anArgIter + 2], aColorName))
3724       {
3725         aCS->SetIntervalColor (Quantity_Color (aColorName), anIndex);
3726         aCS->SetColorType (Aspect_TOCSD_USER);
3727         anArgIter += 2;
3728         continue;
3729       }
3730
3731       TCollection_AsciiString aRed   (theArgVec[anArgIter + 2]);
3732       TCollection_AsciiString aGreen (theArgVec[anArgIter + 3]);
3733       TCollection_AsciiString aBlue  (theArgVec[anArgIter + 4]);
3734       Standard_Real aRedValue,aGreenValue, aBlueValue;
3735       if(checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3736       {
3737         return 1;
3738       }
3739       aCS->SetIntervalColor (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB), anIndex);
3740       aCS->SetColorType (Aspect_TOCSD_USER);
3741       anArgIter += 4;
3742     }
3743     else if (aFlag == "-label")
3744     {
3745       if (aCS->GetColorType() != Aspect_TOCSD_USER)
3746       {
3747         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3748         return 1;
3749       }
3750       else if (anArgIter + 2 >= theArgNb)
3751       {
3752         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3753         return 1;
3754       }
3755
3756       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3757       if (anIndex <= 0 || anIndex > aNbIntervals+1)
3758       {
3759         std::cout << "Error: Index value should be within range 1.." << aNbIntervals+1 <<"!\n";
3760         return 1;
3761       }
3762
3763       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3764       aCS->SetLabel     (aText, anIndex);
3765       aCS->SetLabelType (Aspect_TOCSD_USER);
3766       anArgIter += 2;
3767     }
3768     else if (aFlag == "-colors")
3769     {
3770       Aspect_SequenceOfColor aSeq;
3771       if (anArgIter + aNbIntervals + 1 > theArgNb)
3772       {
3773         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3774                   << aNbIntervals << " intervals\n";
3775         return 1;
3776       }
3777
3778       Standard_Integer aColorIter = anArgIter + 1;
3779       while (aColorIter < theArgNb)
3780       {
3781         if (theArgVec[aColorIter][0] == '-')
3782         {
3783           break;
3784         }
3785
3786         else if (theArgVec[aColorIter][0] >= 97
3787               && theArgVec[aColorIter][0] <= 122)
3788         {
3789           Quantity_NameOfColor aColorName;
3790           if (!Quantity_Color::ColorFromName (theArgVec[aColorIter], aColorName))
3791           {
3792             std::cout << "Error: wrong color name: " << theArgVec[aColorIter] << " !\n";
3793             return 1;
3794           }
3795           aSeq.Append (Quantity_Color (aColorName));
3796           aColorIter++;
3797           anArgIter++;
3798         }
3799         else
3800         {
3801           TCollection_AsciiString aRed   (theArgVec[aColorIter]);
3802           TCollection_AsciiString aGreen (theArgVec[aColorIter + 1]);
3803           TCollection_AsciiString aBlue  (theArgVec[aColorIter + 2]);
3804           Standard_Real aRedValue,aGreenValue, aBlueValue;
3805           if (checkColor (aRed, aGreen, aBlue, aRedValue, aGreenValue, aBlueValue))
3806           {
3807             return 1;
3808           }
3809           aSeq.Append (Quantity_Color (aRedValue, aGreenValue, aBlueValue, Quantity_TOC_RGB));
3810           aColorIter += 3;
3811           anArgIter += 3;
3812         }
3813       }
3814       if (aSeq.Length() < aNbIntervals)
3815       {
3816         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3817                   << aNbIntervals << " intervals\n";
3818         return 1;
3819       }
3820
3821       aCS->SetColors    (aSeq);
3822       aCS->SetColorType (Aspect_TOCSD_USER);
3823     }
3824     else if (aFlag == "-labels")
3825     {
3826       if (anArgIter + aNbIntervals + 1 >= theArgNb)
3827       {
3828         std::cout << "Error: not enough arguments! You should provide " << (aNbIntervals + 1)
3829                   << " text labels for " << aNbIntervals << " intervals.\n";
3830         return 1;
3831       }
3832
3833       TColStd_SequenceOfExtendedString aSeq;
3834       for (int aLabelIter = anArgIter + 1; aLabelIter <= anArgIter + aNbIntervals + 1; aLabelIter += 1)
3835       {
3836         aSeq.Append (TCollection_ExtendedString (theArgVec[aLabelIter]));
3837       }
3838       aCS->SetLabels (aSeq);
3839       aCS->SetLabelType (Aspect_TOCSD_USER);
3840       anArgIter += aSeq.Length();
3841     }
3842     else if (aFlag == "-title")
3843     {
3844       if (anArgIter + 1 >= theArgNb)
3845       {
3846         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3847         return 1;
3848       }
3849
3850       Standard_Boolean isTwoArgs = Standard_False;
3851       if (anArgIter + 2 < theArgNb)
3852       {
3853         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3854         aSecondArg.LowerCase();
3855         if (aSecondArg == "none")
3856         {
3857           aCS->SetTitlePosition (Aspect_TOCSP_NONE);
3858           isTwoArgs = Standard_True;
3859         }
3860         else if (aSecondArg == "left")
3861         {
3862           aCS->SetTitlePosition (Aspect_TOCSP_LEFT);
3863           isTwoArgs = Standard_True;
3864         }
3865         else if (aSecondArg == "right")
3866         {
3867           aCS->SetTitlePosition (Aspect_TOCSP_RIGHT);
3868           isTwoArgs = Standard_True;
3869         }
3870         else if (aSecondArg == "center")
3871         {
3872           aCS->SetTitlePosition (Aspect_TOCSP_CENTER);
3873           isTwoArgs = Standard_True;
3874         }
3875       }
3876
3877       aCS->SetTitle (theArgVec[anArgIter + 1]);
3878       if (isTwoArgs)
3879       {
3880         anArgIter += 1;
3881       }
3882       anArgIter += 1;
3883     }
3884     else if (aFlag == "-demoversion"
3885           || aFlag == "-demo")
3886     {
3887       aPosX        = 0;
3888       aPosY        = 0;
3889       aTextHeight  = 16;
3890       aMinRange    = 0.0;
3891       aMaxRange    = 100;
3892       aNbIntervals = 10;
3893       aBreadth     = 0;
3894       aHeight      = 0;
3895       aLabPosition = Aspect_TOCSP_RIGHT;
3896       aCS->SetColorType (Aspect_TOCSD_AUTO);
3897       aCS->SetLabelType (Aspect_TOCSD_AUTO);
3898     }
3899     else if (aFlag == "-findcolor")
3900     {
3901       if (anArgIter + 1 >= theArgNb)
3902       {
3903         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3904         return 1;
3905       }
3906
3907       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3908
3909       if (!anArg1.IsRealValue())
3910       {
3911         std::cout << "Error: the value should be real!\n";
3912         return 1;
3913       }
3914
3915       Quantity_Color aColor;
3916       aCS->FindColor (anArg1.RealValue(), aColor);
3917       theDI << Quantity_Color::StringName (aColor.Name());
3918       return 0;
3919     }
3920     else
3921     {
3922       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3923       return 1;
3924     }
3925   }
3926   if (!aBreadth || !aHeight)
3927   {
3928     Standard_Integer aWinWidth, aWinHeight;
3929     aView->Window()->Size (aWinWidth, aWinHeight);
3930     if (!aBreadth)
3931     {
3932       aBreadth = aWinWidth;
3933     }
3934     if (!aHeight)
3935     {
3936       aHeight = aWinHeight;
3937     }
3938   }
3939   aCS->SetSize              (aBreadth, aHeight);
3940   aCS->SetPosition          (aPosX, aPosY);
3941   aCS->SetTextHeight        (aTextHeight);
3942   aCS->SetRange             (aMinRange, aMaxRange);
3943   aCS->SetNumberOfIntervals (aNbIntervals);
3944   aCS->SetLabelPosition     (aLabPosition);
3945 //  aCS->SetColor             (aView->BackgroundColor().Invert());
3946   aCS->SetToUpdate();
3947   aContext->Display (aCS);
3948
3949   return 0;
3950 }
3951
3952 //==============================================================================
3953 //function : VGraduatedTrihedron
3954 //purpose  : Displays or hides a graduated trihedron
3955 //==============================================================================
3956 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
3957                                   Quantity_Color& theColor)
3958 {
3959   Quantity_NameOfColor aColorName;
3960   TCollection_AsciiString aVal = theValue;
3961   aVal.UpperCase();
3962   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
3963   {
3964     return Standard_False;
3965   }
3966   theColor = Quantity_Color (aColorName);
3967   return Standard_True;
3968 }
3969
3970 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
3971 {
3972   if (theArgNum < 2)
3973   {
3974     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
3975               << theArgs[0] <<"' for more information.\n";
3976     return 1;  //TCL_ERROR
3977   }
3978
3979   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
3980   TCollection_AsciiString aParseKey;
3981   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
3982   {
3983     TCollection_AsciiString anArg (theArgs [anArgIt]);
3984
3985     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
3986     {
3987       aParseKey = anArg;
3988       aParseKey.Remove (1);
3989       aParseKey.LowerCase();
3990       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
3991       continue;
3992     }
3993
3994     if (aParseKey.IsEmpty())
3995     {
3996       continue;
3997     }
3998
3999     aMapOfArgs(aParseKey)->Append (anArg);
4000   }
4001
4002   // Check parameters
4003   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4004        aMapIt.More(); aMapIt.Next())
4005   {
4006     const TCollection_AsciiString& aKey = aMapIt.Key();
4007     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4008
4009     // Bool key, without arguments
4010     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4011         && anArgs->IsEmpty())
4012     {
4013       continue;
4014     }
4015
4016     // One argument
4017     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4018           && anArgs->Length() == 1)
4019     {
4020       continue;
4021     }
4022
4023     // On/off arguments
4024     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4025         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4026         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4027         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4028         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4029     {
4030       continue;
4031     }
4032
4033     // One string argument
4034     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4035           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4036           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4037     {
4038       continue;
4039     }
4040
4041     // One integer argument
4042     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4043           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4044           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4045           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4046          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4047     {
4048       continue;
4049     }
4050
4051     // One real argument
4052     if ( aKey.IsEqual ("arrowlength")
4053          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4054     {
4055       continue;
4056     }
4057
4058     // Two string arguments
4059     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4060          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4061     {
4062       continue;
4063     }
4064
4065     TCollection_AsciiString aLowerKey;
4066     aLowerKey  = "-";
4067     aLowerKey += aKey;
4068     aLowerKey.LowerCase();
4069     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4070     std::cout << "Type help for more information.\n";
4071     return 1;
4072   }
4073
4074   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4075   if (anAISContext.IsNull())
4076   {
4077     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4078     return 1;
4079   }
4080
4081   Standard_Boolean toDisplay = Standard_True;
4082   Quantity_Color aColor;
4083   Graphic3d_GraduatedTrihedron aTrihedronData;
4084   // Process parameters
4085   Handle(TColStd_HSequenceOfAsciiString) aValues;
4086   if (aMapOfArgs.Find ("off", aValues))
4087   {
4088     toDisplay = Standard_False;
4089   }
4090
4091   // AXES NAMES
4092   if (aMapOfArgs.Find ("xname", aValues))
4093   {
4094     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4095   }
4096   if (aMapOfArgs.Find ("yname", aValues))
4097   {
4098     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4099   }
4100   if (aMapOfArgs.Find ("zname", aValues))
4101   {
4102     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4103   }
4104   if (aMapOfArgs.Find ("xdrawname", aValues))
4105   {
4106     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4107   }
4108   if (aMapOfArgs.Find ("ydrawname", aValues))
4109   {
4110     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4111   }
4112   if (aMapOfArgs.Find ("zdrawname", aValues))
4113   {
4114     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4115   }
4116   if (aMapOfArgs.Find ("xnameoffset", aValues))
4117   {
4118     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4119   }
4120   if (aMapOfArgs.Find ("ynameoffset", aValues))
4121   {
4122     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4123   }
4124   if (aMapOfArgs.Find ("znameoffset", aValues))
4125   {
4126     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4127   }
4128
4129   // COLORS
4130   if (aMapOfArgs.Find ("xnamecolor", aValues))
4131   {
4132     if (!GetColor (aValues->Value(1), aColor))
4133     {
4134       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4135       return 1;
4136     }
4137     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4138   }
4139   if (aMapOfArgs.Find ("ynamecolor", aValues))
4140   {
4141     if (!GetColor (aValues->Value(1), aColor))
4142     {
4143       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4144       return 1;
4145     }
4146     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4147   }
4148   if (aMapOfArgs.Find ("znamecolor", aValues))
4149   {
4150     if (!GetColor (aValues->Value(1), aColor))
4151     {
4152       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4153       return 1;
4154     }
4155     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4156   }
4157   if (aMapOfArgs.Find ("xcolor", aValues))
4158   {
4159     if (!GetColor (aValues->Value(1), aColor))
4160     {
4161       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4162       return 1;
4163     }
4164     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4165   }
4166   if (aMapOfArgs.Find ("ycolor", aValues))
4167   {
4168     if (!GetColor (aValues->Value(1), aColor))
4169     {
4170       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4171       return 1;
4172     }
4173     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4174   }
4175   if (aMapOfArgs.Find ("zcolor", aValues))
4176   {
4177     if (!GetColor (aValues->Value(1), aColor))
4178     {
4179       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4180       return 1;
4181     }
4182     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4183   }
4184
4185   // TICKMARKS
4186   if (aMapOfArgs.Find ("xticks", aValues))
4187   {
4188     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4189   }
4190   if (aMapOfArgs.Find ("yticks", aValues))
4191   {
4192     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4193   }
4194   if (aMapOfArgs.Find ("zticks", aValues))
4195   {
4196     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4197   }
4198   if (aMapOfArgs.Find ("xticklength", aValues))
4199   {
4200     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4201   }
4202   if (aMapOfArgs.Find ("yticklength", aValues))
4203   {
4204     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4205   }
4206   if (aMapOfArgs.Find ("zticklength", aValues))
4207   {
4208     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4209   }
4210   if (aMapOfArgs.Find ("xdrawticks", aValues))
4211   {
4212     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4213   }
4214   if (aMapOfArgs.Find ("ydrawticks", aValues))
4215   {
4216     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4217   }
4218   if (aMapOfArgs.Find ("zdrawticks", aValues))
4219   {
4220     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4221   }
4222
4223   // VALUES
4224   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4225   {
4226     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4227   }
4228   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4229   {
4230     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4231   }
4232   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4233   {
4234     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4235   }
4236   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4237   {
4238     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4239   }
4240   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4241   {
4242     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4243   }
4244   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4245   {
4246     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4247   }
4248
4249   // ARROWS
4250   if (aMapOfArgs.Find ("arrowlength", aValues))
4251   {
4252     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4253   }
4254
4255   // FONTS
4256   if (aMapOfArgs.Find ("namefont", aValues))
4257   {
4258     aTrihedronData.SetNamesFont (aValues->Value(1));
4259   }
4260   if (aMapOfArgs.Find ("valuesfont", aValues))
4261   {
4262     aTrihedronData.SetValuesFont (aValues->Value(1));
4263   }
4264
4265   if (aMapOfArgs.Find ("drawgrid", aValues))
4266   {
4267     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4268   }
4269   if (aMapOfArgs.Find ("drawaxes", aValues))
4270   {
4271     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4272   }
4273
4274   // The final step: display of erase trihedron
4275   if (toDisplay)
4276   {
4277     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4278   }
4279   else
4280   {
4281     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4282   }
4283
4284   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4285   ViewerTest::CurrentView()->Redraw();
4286
4287   return 0;
4288 }
4289
4290 //==============================================================================
4291 //function : VTile
4292 //purpose  :
4293 //==============================================================================
4294 static int VTile (Draw_Interpretor& theDI,
4295                   Standard_Integer  theArgNb,
4296                   const char**      theArgVec)
4297 {
4298   Handle(V3d_View) aView = ViewerTest::CurrentView();
4299   if (aView.IsNull())
4300   {
4301     std::cerr << "Error: no active viewer.\n";
4302     return 1;
4303   }
4304
4305   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4306   if (theArgNb < 2)
4307   {
4308     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4309           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4310           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4311     return 0;
4312   }
4313
4314   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4315   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4316   {
4317     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4318     anArg.LowerCase();
4319     if (anArg == "-lowerleft"
4320      || anArg == "-upperleft")
4321     {
4322       if (anArgIter + 3 < theArgNb)
4323       {
4324         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4325         return 1;
4326       }
4327       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4328       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4329       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4330     }
4331     else if (anArg == "-total"
4332           || anArg == "-totalsize"
4333           || anArg == "-viewsize")
4334     {
4335       if (anArgIter + 3 < theArgNb)
4336       {
4337         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4338         return 1;
4339       }
4340       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4341       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4342       if (aTile.TotalSize.x() < 1
4343        || aTile.TotalSize.y() < 1)
4344       {
4345         std::cerr << "Error: total size is incorrect.\n";
4346         return 1;
4347       }
4348     }
4349     else if (anArg == "-tilesize")
4350     {
4351       if (anArgIter + 3 < theArgNb)
4352       {
4353         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4354         return 1;
4355       }
4356
4357       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4358       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4359       if (aTile.TileSize.x() < 1
4360        || aTile.TileSize.y() < 1)
4361       {
4362         std::cerr << "Error: tile size is incorrect.\n";
4363         return 1;
4364       }
4365     }
4366     else if (anArg == "-unset")
4367     {
4368       aView->Camera()->SetTile (Graphic3d_CameraTile());
4369       aView->Redraw();
4370       return 0;
4371     }
4372   }
4373
4374   if (aTile.TileSize.x() < 1
4375    || aTile.TileSize.y() < 1)
4376   {
4377     std::cerr << "Error: tile size is undefined.\n";
4378     return 1;
4379   }
4380   else if (aTile.TotalSize.x() < 1
4381         || aTile.TotalSize.y() < 1)
4382   {
4383     std::cerr << "Error: total size is undefined.\n";
4384     return 1;
4385   }
4386
4387   aView->Camera()->SetTile (aTile);
4388   aView->Redraw();
4389   return 0;
4390 }
4391
4392 //==============================================================================
4393 //function : VZLayer
4394 //purpose  : Test z layer operations for v3d viewer
4395 //==============================================================================
4396 static int VZLayer (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4397 {
4398   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext ();
4399   if (aContextAIS.IsNull())
4400   {
4401     di << "Call vinit before!\n";
4402     return 1;
4403   }
4404   else if (argc < 2)
4405   {
4406     di << di.PrintHelp (argv[0]);
4407     return 1;
4408   }
4409
4410   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4411   if (aViewer.IsNull())
4412   {
4413     di << "No active viewer!\n";
4414     return 1;
4415   }
4416
4417   // perform operation
4418   TCollection_AsciiString anOp = TCollection_AsciiString (argv[1]);
4419   if (anOp == "add")
4420   {
4421     Standard_Integer aNewId;
4422     if (!aViewer->AddZLayer (aNewId))
4423     {
4424       di << "Impossible to add new z layer!\n";
4425       return 1;
4426     }
4427
4428     di << "New z layer added with index: " << aNewId << "\n";
4429   }
4430   else if (anOp == "del")
4431   {
4432     if (argc < 3)
4433     {
4434       di << "Please also provide as argument id of z layer to remove\n";
4435       return 1;
4436     }
4437
4438     Standard_Integer aDelId = Draw::Atoi (argv[2]);
4439     if (!aViewer->RemoveZLayer (aDelId))
4440     {
4441       di << "Impossible to remove the z layer or invalid id!\n";
4442       return 1;
4443     }
4444
4445     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4446          anObjIter.More(); anObjIter.Next())
4447     {
4448       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4449       if (aPrs.IsNull()
4450        || aPrs->ZLayer() != aDelId)
4451       {
4452         continue;
4453       }
4454       aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4455     }
4456
4457     di << "Z layer " << aDelId << " has been removed\n";
4458   }
4459   else if (anOp == "get")
4460   {
4461     TColStd_SequenceOfInteger anIds;
4462     aViewer->GetAllZLayers (anIds);
4463     for (Standard_Integer aSeqIdx = 1; aSeqIdx <= anIds.Length(); aSeqIdx++)
4464     {
4465       di << anIds.Value (aSeqIdx) << " ";
4466     }
4467
4468     di << "\n";
4469   }
4470   else if (anOp == "settings")
4471   {
4472     if (argc < 3)
4473     {
4474       di << "Please also provide an id\n";
4475       return 1;
4476     }
4477
4478     Standard_Integer anId = Draw::Atoi (argv[2]);
4479     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4480
4481     di << "Depth test - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthTest) ? "enabled" : "disabled") << "\n";
4482     di << "Depth write - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? "enabled" : "disabled") << "\n";
4483     di << "Depth buffer clearing - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthClear) ? "enabled" : "disabled") << "\n";
4484     di << "Depth offset - " << (aSettings.IsSettingEnabled (Graphic3d_ZLayerDepthOffset) ? "enabled" : "disabled") << "\n";
4485
4486   }
4487   else if (anOp == "enable")
4488   {
4489     if (argc < 3)
4490     {
4491       di << "Please also provide an option to enable\n";
4492       return 1;
4493     }
4494
4495     if (argc < 4)
4496     {
4497       di << "Please also provide a layer id\n";
4498       return 1;
4499     }
4500
4501     TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
4502     Standard_Integer anId = Draw::Atoi (argv[3]);
4503     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4504
4505     if (aSubOp == "depthtest" || aSubOp == "test")
4506     {
4507       aSettings.EnableSetting (Graphic3d_ZLayerDepthTest);
4508     }
4509     else if (aSubOp == "depthwrite" || aSubOp == "write")
4510     {
4511       aSettings.EnableSetting (Graphic3d_ZLayerDepthWrite);
4512     }
4513     else if (aSubOp == "depthclear" || aSubOp == "clear")
4514     {
4515       aSettings.EnableSetting (Graphic3d_ZLayerDepthClear);
4516     }
4517     else if (aSubOp == "depthoffset" || aSubOp == "offset")
4518     {
4519       if (argc < 6)
4520       {
4521         di << "Please also provide a factor and units values for depth offset\n";
4522         di << "Format is: vzlayer enable offset [factor] [units] [layerId]\n";
4523         return 1;
4524       }
4525
4526       Standard_ShortReal aFactor = static_cast<Standard_ShortReal> (Draw::Atof (argv[3]));
4527       Standard_ShortReal aUnits  = static_cast<Standard_ShortReal> (Draw::Atof (argv[4]));
4528       anId = Draw::Atoi (argv[5]);
4529       aSettings = aViewer->ZLayerSettings (anId);
4530
4531       aSettings.DepthOffsetFactor = aFactor;
4532       aSettings.DepthOffsetUnits  = aUnits;
4533
4534       aSettings.EnableSetting (Graphic3d_ZLayerDepthOffset);
4535     }
4536     else if (aSubOp == "positiveoffset" || aSubOp == "poffset")
4537     {
4538       aSettings.SetDepthOffsetPositive();
4539     }
4540     else if (aSubOp == "negativeoffset" || aSubOp == "noffset")
4541     {
4542       aSettings.SetDepthOffsetNegative();
4543     }
4544     else if (aSubOp == "textureenv")
4545     {
4546       aSettings.UseEnvironmentTexture = true;
4547     }
4548
4549     aViewer->SetZLayerSettings (anId, aSettings);
4550   }
4551   else if (anOp == "disable")
4552   {
4553     if (argc < 3)
4554     {
4555       di << "Please also provide an option to disable\n";
4556       return 1;
4557     }
4558
4559     if (argc < 4)
4560     {
4561       di << "Please also provide a layer id\n";
4562       return 1;
4563     }
4564
4565     TCollection_AsciiString aSubOp = TCollection_AsciiString (argv[2]);
4566     Standard_Integer anId = Draw::Atoi (argv[3]);
4567     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (anId);
4568
4569     if (aSubOp == "depthtest" || aSubOp == "test")
4570     {
4571       aSettings.DisableSetting (Graphic3d_ZLayerDepthTest);
4572     }
4573     else if (aSubOp == "depthwrite" || aSubOp == "write")
4574     {
4575       aSettings.DisableSetting (Graphic3d_ZLayerDepthWrite);
4576     }
4577     else if (aSubOp == "depthclear" || aSubOp == "clear")
4578     {
4579       aSettings.DisableSetting (Graphic3d_ZLayerDepthClear);
4580     }
4581     else if (aSubOp == "depthoffset" || aSubOp == "offset")
4582     {
4583       aSettings.DisableSetting (Graphic3d_ZLayerDepthOffset);
4584     }
4585     else if (aSubOp == "textureenv")
4586     {
4587       aSettings.UseEnvironmentTexture = false;
4588     }
4589
4590     aViewer->SetZLayerSettings (anId, aSettings);
4591   }
4592   else
4593   {
4594     di << "Invalid operation, please use { add / del / get / settings / enable / disable}\n";
4595     return 1;
4596   }
4597
4598   return 0;
4599 }
4600
4601 // The interactive presentation of 2d layer item
4602 // for "vlayerline" command it provides a presentation of
4603 // line with user-defined linewidth, linetype and transparency.
4604 class V3d_LineItem : public AIS_InteractiveObject
4605 {
4606 public:
4607   // CASCADE RTTI
4608   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4609
4610   // constructor
4611   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4612                                Standard_Real X2, Standard_Real Y2,
4613                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4614                                Standard_Real theWidth    = 0.5,
4615                                Standard_Real theTransp   = 1.0);
4616
4617   private:
4618
4619   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4620                 const Handle(Prs3d_Presentation)& thePresentation,
4621                 const Standard_Integer theMode) Standard_OVERRIDE;
4622
4623   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4624                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4625   {}
4626
4627 private:
4628
4629   Standard_Real       myX1, myY1, myX2, myY2;
4630   Aspect_TypeOfLine   myType;
4631   Standard_Real       myWidth;
4632 };
4633
4634 // default constructor for line item
4635 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4636                            Standard_Real X2, Standard_Real Y2,
4637                            Aspect_TypeOfLine theType,
4638                            Standard_Real theWidth,
4639                            Standard_Real theTransp) :
4640   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4641   myType(theType), myWidth(theWidth)
4642 {
4643   SetTransparency (1-theTransp);
4644 }
4645
4646 // render line
4647 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4648                             const Handle(Prs3d_Presentation)& thePresentation,
4649                             const Standard_Integer /*theMode*/)
4650 {
4651   thePresentation->Clear();
4652   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4653   Standard_Integer aWidth, aHeight;
4654   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4655   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4656   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4657   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4658   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4659   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4660   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4661   aGroup->AddPrimitiveArray (aPrim);
4662 }
4663
4664 //=============================================================================
4665 //function : VLayerLine
4666 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4667 //         : linewidth, transparency coefficient
4668 //============================================================================
4669 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4670 {
4671   // get the active view
4672   Handle(V3d_View) aView = ViewerTest::CurrentView();
4673   if (aView.IsNull())
4674   {
4675     di << "Call vinit before!\n";
4676     return 1;
4677   }
4678   else if (argc < 5)
4679   {
4680     di << "Use: " << argv[0];
4681     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4682     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4683     di << "              0 - solid  \n";
4684     di << "              1 - dashed \n";
4685     di << "              2 - dot    \n";
4686     di << "              3 - dashdot\n";
4687     di << " transparency : { 0.0 - 1.0 } \n";
4688     di << "                  0.0 - transparent\n";
4689     di << "                  1.0 - visible    \n";
4690     return 1;
4691   }
4692
4693   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4694   // get the input params
4695   Standard_Real X1 = Draw::Atof(argv[1]);
4696   Standard_Real Y1 = Draw::Atof(argv[2]);
4697   Standard_Real X2 = Draw::Atof(argv[3]);
4698   Standard_Real Y2 = Draw::Atof(argv[4]);
4699
4700   Standard_Real    aWidth = 0.5;
4701   Standard_Integer aType  = 0;
4702   Standard_Real    aTransparency = 1.0;
4703
4704   // has width
4705   if (argc > 5)
4706     aWidth = Draw::Atof(argv[5]);
4707
4708   // has type
4709   if (argc > 6)
4710      aType = (Standard_Integer) Draw::Atoi(argv[6]);
4711
4712   // has transparency
4713   if (argc > 7)
4714   {
4715     aTransparency = Draw::Atof(argv[7]);
4716     if (aTransparency < 0 || aTransparency > 1.0)
4717       aTransparency = 1.0;
4718   }
4719
4720   // select appropriate line type
4721   Aspect_TypeOfLine aLineType;
4722   switch (aType)
4723   {
4724     case 1:
4725       aLineType = Aspect_TOL_DASH;
4726     break;
4727
4728     case 2:
4729       aLineType = Aspect_TOL_DOT;
4730     break;
4731
4732     case 3:
4733       aLineType = Aspect_TOL_DOTDASH;
4734     break;
4735
4736     default:
4737       aLineType = Aspect_TOL_SOLID;
4738   }
4739
4740   static Handle (V3d_LineItem) aLine;
4741   if (!aLine.IsNull())
4742   {
4743     aContext->Erase (aLine);
4744   }
4745   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4746                             aLineType, aWidth,
4747                             aTransparency);
4748
4749   aContext->SetTransformPersistence (aLine, Graphic3d_TMF_2d, gp_Pnt (-1.0, -1.0, 0.0));
4750   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4751   aLine->SetToUpdate();
4752   aContext->Display (aLine, Standard_True);
4753
4754   return 0;
4755 }
4756
4757
4758 //==============================================================================
4759 //function : VGrid
4760 //purpose  :
4761 //==============================================================================
4762
4763 static int VGrid (Draw_Interpretor& /*theDI*/,
4764                   Standard_Integer  theArgNb,
4765                   const char**      theArgVec)
4766 {
4767   // get the active view
4768   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4769   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4770   if (aView.IsNull() || aViewer.IsNull())
4771   {
4772     std::cerr << "No active view. Please call vinit.\n";
4773     return 1;
4774   }
4775
4776   Aspect_GridType     aType = aViewer->GridType();
4777   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4778
4779   Standard_Integer anIter = 1;
4780   for (; anIter < theArgNb; ++anIter)
4781   {
4782     const char* aValue = theArgVec[anIter];
4783     if (*aValue == 'r')
4784     {
4785       aType = Aspect_GT_Rectangular;
4786     }
4787     else if (*aValue == 'c')
4788     {
4789       aType = Aspect_GT_Circular;
4790     }
4791     else if (*aValue == 'l')
4792     {
4793       aMode = Aspect_GDM_Lines;
4794     }
4795     else if (*aValue == 'p')
4796     {
4797       aMode = Aspect_GDM_Points;
4798     }
4799     else if (strcmp (aValue, "off" ) == 0)
4800     {
4801       aViewer->DeactivateGrid();
4802       return 0;
4803     }
4804     else
4805     {
4806       break;
4807     }
4808   }
4809
4810   Standard_Integer aTail = (theArgNb - anIter);
4811   if (aTail == 0)
4812   {
4813     aViewer->ActivateGrid (aType, aMode);
4814     return 0;
4815   }
4816   else if (aTail != 2 && aTail != 5)
4817   {
4818     std::cerr << "Incorrect arguments number! Usage:\n"
4819               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
4820     return 1;
4821   }
4822
4823   Quantity_Length anOriginX, anOriginY;
4824   Quantity_PlaneAngle aRotAngle;
4825   if (aType == Aspect_GT_Rectangular)
4826   {
4827     Quantity_Length aRStepX, aRStepY;
4828     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
4829
4830     anOriginX = Draw::Atof (theArgVec[anIter++]);
4831     anOriginY = Draw::Atof (theArgVec[anIter++]);
4832     if (aTail == 5)
4833     {
4834       aRStepX   = Draw::Atof (theArgVec[anIter++]);
4835       aRStepY   = Draw::Atof (theArgVec[anIter++]);
4836       aRotAngle = Draw::Atof (theArgVec[anIter++]);
4837     }
4838     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
4839     aViewer->ActivateGrid (aType, aMode);
4840   }
4841   else if (aType == Aspect_GT_Circular)
4842   {
4843     Quantity_Length aRadiusStep;
4844     Standard_Integer aDivisionNumber;
4845     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
4846
4847     anOriginX = Draw::Atof (theArgVec[anIter++]);
4848     anOriginY = Draw::Atof (theArgVec[anIter++]);
4849     if (aTail == 5)
4850     {
4851       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
4852       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
4853       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
4854     }
4855
4856     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
4857     aViewer->ActivateGrid (aType, aMode);
4858   }
4859
4860   return 0;
4861 }
4862
4863 //==============================================================================
4864 //function : VPriviledgedPlane
4865 //purpose  :
4866 //==============================================================================
4867
4868 static int VPriviledgedPlane (Draw_Interpretor& theDI,
4869                               Standard_Integer  theArgNb,
4870                               const char**      theArgVec)
4871 {
4872   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
4873   {
4874     std::cerr << "Error: wrong number of arguments! See usage:\n";
4875     theDI.PrintHelp (theArgVec[0]);
4876     return 1;
4877   }
4878
4879   // get the active viewer
4880   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4881   if (aViewer.IsNull())
4882   {
4883     std::cerr << "Error: no active viewer. Please call vinit.\n";
4884     return 1;
4885   }
4886
4887   if (theArgNb == 1)
4888   {
4889     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
4890     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
4891     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
4892     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
4893     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
4894           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
4895           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
4896     return 0;
4897   }
4898
4899   Standard_Integer anArgIdx = 1;
4900   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
4901   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
4902   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
4903   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
4904   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
4905   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
4906
4907   gp_Ax3 aPriviledgedPlane;
4908   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
4909   gp_Dir aNorm (aNormX, aNormY, aNormZ);
4910   if (theArgNb > 7)
4911   {
4912     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
4913     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
4914     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
4915     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
4916     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
4917   }
4918   else
4919   {
4920     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
4921   }
4922
4923   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
4924
4925   return 0;
4926 }
4927
4928 //==============================================================================
4929 //function : VConvert
4930 //purpose  :
4931 //==============================================================================
4932
4933 static int VConvert (Draw_Interpretor& theDI,
4934                      Standard_Integer  theArgNb,
4935                      const char**      theArgVec)
4936 {
4937   // get the active view
4938   Handle(V3d_View) aView = ViewerTest::CurrentView();
4939   if (aView.IsNull())
4940   {
4941     std::cerr << "Error: no active view. Please call vinit.\n";
4942     return 1;
4943   }
4944
4945   enum { Model, Ray, View, Window, Grid } aMode = Model;
4946
4947   // access coordinate arguments
4948   TColStd_SequenceOfReal aCoord;
4949   Standard_Integer anArgIdx = 1;
4950   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
4951   {
4952     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
4953     if (!anArg.IsRealValue())
4954     {
4955       break;
4956     }
4957     aCoord.Append (anArg.RealValue());
4958   }
4959
4960   // non-numeric argument too early
4961   if (aCoord.IsEmpty())
4962   {
4963     std::cerr << "Error: wrong number of arguments! See usage:\n";
4964     theDI.PrintHelp (theArgVec[0]);
4965     return 1;
4966   }
4967
4968   // collect all other arguments and options
4969   for (; anArgIdx < theArgNb; ++anArgIdx)
4970   {
4971     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
4972     anArg.LowerCase();
4973     if      (anArg == "window") aMode = Window;
4974     else if (anArg == "view")   aMode = View;
4975     else if (anArg == "grid")   aMode = Grid;
4976     else if (anArg == "ray")    aMode = Ray;
4977     else
4978     {
4979       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
4980       theDI.PrintHelp (theArgVec[0]);
4981       return 1;
4982     }
4983   }
4984
4985   // complete input checks
4986   if ((aCoord.Length() == 1 && theArgNb > 3) ||
4987       (aCoord.Length() == 2 && theArgNb > 4) ||
4988       (aCoord.Length() == 3 && theArgNb > 5))
4989   {
4990     std::cerr << "Error: wrong number of arguments! See usage:\n";
4991     theDI.PrintHelp (theArgVec[0]);
4992     return 1;
4993   }
4994
4995   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4996   Standard_Integer aXYp[2] = {0, 0};
4997
4998   // convert one-dimensional coordinate
4999   if (aCoord.Length() == 1)
5000   {
5001     switch (aMode)
5002     {
5003       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer) aCoord (1)); return 0;
5004       case Window : theDI << "Window Vp: " << aView->Convert ((Quantity_Length) aCoord (1));  return 0;
5005       default:
5006         std::cerr << "Error: wrong arguments! See usage:\n";
5007         theDI.PrintHelp (theArgVec[0]);
5008         return 1;
5009     }
5010   }
5011
5012   // convert 2D coordinates from projection or view reference space
5013   if (aCoord.Length() == 2)
5014   {
5015     switch (aMode)
5016     {
5017       case Model :
5018         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5019         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5020         return 0;
5021
5022       case View :
5023         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5024         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5025         return 0;
5026
5027       case Window :
5028         aView->Convert ((V3d_Coordinate) aCoord (1), (V3d_Coordinate) aCoord (2), aXYp[0], aXYp[1]);
5029         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5030         return 0;
5031
5032       case Grid :
5033         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5034         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5035         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5036         return 0;
5037
5038       case Ray :
5039         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5040                                 (Standard_Integer) aCoord (2),
5041                                 aXYZ[0], aXYZ[1], aXYZ[2],
5042                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5043         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5044         return 0;
5045
5046       default:
5047         std::cerr << "Error: wrong arguments! See usage:\n";
5048         theDI.PrintHelp (theArgVec[0]);
5049         return 1;
5050     }
5051   }
5052
5053   // convert 3D coordinates from view reference space
5054   else if (aCoord.Length() == 3)
5055   {
5056     switch (aMode)
5057     {
5058       case Window :
5059         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5060         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5061         return 0;
5062
5063       case Grid :
5064         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5065         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5066         return 0;
5067
5068       default:
5069         std::cerr << "Error: wrong arguments! See usage:\n";
5070         theDI.PrintHelp (theArgVec[0]);
5071         return 1;
5072     }
5073   }
5074
5075   return 0;
5076 }
5077
5078 //==============================================================================
5079 //function : VFps
5080 //purpose  :
5081 //==============================================================================
5082
5083 static int VFps (Draw_Interpretor& theDI,
5084                  Standard_Integer  theArgNb,
5085                  const char**      theArgVec)
5086 {
5087   // get the active view
5088   Handle(V3d_View) aView = ViewerTest::CurrentView();
5089   if (aView.IsNull())
5090   {
5091     std::cerr << "No active view. Please call vinit.\n";
5092     return 1;
5093   }
5094
5095   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5096   if (aFramesNb <= 0)
5097   {
5098     std::cerr << "Incorrect arguments!\n";
5099     return 1;
5100   }
5101
5102   // the time is meaningless for first call
5103   // due to async OpenGl rendering
5104   aView->Redraw();
5105
5106   // redraw view in loop to estimate average values
5107   OSD_Timer aTimer;
5108   aTimer.Start();
5109   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5110   {
5111     aView->Redraw();
5112   }
5113   aTimer.Stop();
5114   Standard_Real aCpu;
5115   const Standard_Real aTime = aTimer.ElapsedTime();
5116   aTimer.OSD_Chronometer::Show (aCpu);
5117
5118   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5119   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5120
5121   // return statistics
5122   theDI << "FPS: " << aFpsAver << "\n"
5123         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5124
5125   // compute additional statistics in ray-tracing mode
5126   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5127
5128   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5129   {
5130     Standard_Integer aSizeX;
5131     Standard_Integer aSizeY;
5132
5133     aView->Window()->Size (aSizeX, aSizeY);
5134
5135     // 1 shadow ray and 1 secondary ray pew each bounce
5136     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5137
5138     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5139   }
5140
5141   return 0;
5142 }
5143
5144 //==============================================================================
5145 //function : VGlDebug
5146 //purpose  :
5147 //==============================================================================
5148
5149 static int VGlDebug (Draw_Interpretor& theDI,
5150                      Standard_Integer  theArgNb,
5151                      const char**      theArgVec)
5152 {
5153   Handle(OpenGl_GraphicDriver) aDriver;
5154   Handle(V3d_View) aView = ViewerTest::CurrentView();
5155   if (!aView.IsNull())
5156   {
5157     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5158   }
5159   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5160   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5161
5162   if (theArgNb < 2)
5163   {
5164     TCollection_AsciiString aDebActive, aSyncActive;
5165     if (aCaps == NULL)
5166     {
5167       aCaps = aDefCaps;
5168     }
5169     else
5170     {
5171       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5172                                                                   "GL_ARB_debug_output");
5173       aDebActive = isActive ? " (active)" : " (inactive)";
5174       if (isActive)
5175       {
5176         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5177         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5178       }
5179     }
5180
5181     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5182           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5183           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5184           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5185     return 0;
5186   }
5187
5188   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5189   {
5190     Standard_CString        anArg     = theArgVec[anArgIter];
5191     TCollection_AsciiString anArgCase (anArg);
5192     anArgCase.LowerCase();
5193     Standard_Boolean toEnableDebug = Standard_True;
5194     if (anArgCase == "-glsl"
5195      || anArgCase == "-glslwarn"
5196      || anArgCase == "-glslwarns"
5197      || anArgCase == "-glslwarnings")
5198     {
5199       Standard_Boolean toShowWarns = Standard_True;
5200       if (++anArgIter < theArgNb
5201       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5202       {
5203         --anArgIter;
5204       }
5205       aDefCaps->glslWarnings = toShowWarns;
5206       if (aCaps != NULL)
5207       {
5208         aCaps->glslWarnings = toShowWarns;
5209       }
5210     }
5211     else if (anArgCase == "-extra"
5212           || anArgCase == "-extramsg"
5213           || anArgCase == "-extramessages")
5214     {
5215       Standard_Boolean toShow = Standard_True;
5216       if (++anArgIter < theArgNb
5217       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5218       {
5219         --anArgIter;
5220       }
5221       aDefCaps->suppressExtraMsg = !toShow;
5222       if (aCaps != NULL)
5223       {
5224         aCaps->suppressExtraMsg = !toShow;
5225       }
5226     }
5227     else if (anArgCase == "-noextra"
5228           || anArgCase == "-noextramsg"
5229           || anArgCase == "-noextramessages")
5230     {
5231       Standard_Boolean toSuppress = Standard_True;
5232       if (++anArgIter < theArgNb
5233       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5234       {
5235         --anArgIter;
5236       }
5237       aDefCaps->suppressExtraMsg = toSuppress;
5238       if (aCaps != NULL)
5239       {
5240         aCaps->suppressExtraMsg = toSuppress;
5241       }
5242     }
5243     else if (anArgCase == "-sync")
5244     {
5245       Standard_Boolean toSync = Standard_True;
5246       if (++anArgIter < theArgNb
5247       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5248       {
5249         --anArgIter;
5250       }
5251       aDefCaps->contextSyncDebug = toSync;
5252       if (toSync)
5253       {
5254         aDefCaps->contextDebug = Standard_True;
5255       }
5256     }
5257     else if (anArgCase == "-debug")
5258     {
5259       if (++anArgIter < theArgNb
5260       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5261       {
5262         --anArgIter;
5263       }
5264       aDefCaps->contextDebug = toEnableDebug;
5265     }
5266     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5267           && (anArgIter + 1 == theArgNb))
5268     {
5269       // simple alias to turn on almost everything
5270       aDefCaps->contextDebug     = toEnableDebug;
5271       aDefCaps->contextSyncDebug = toEnableDebug;
5272       aDefCaps->glslWarnings     = toEnableDebug;
5273     }
5274     else
5275     {
5276       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5277       return 1;
5278     }
5279   }
5280
5281   return 0;
5282 }
5283
5284 //==============================================================================
5285 //function : VVbo
5286 //purpose  :
5287 //==============================================================================
5288
5289 static int VVbo (Draw_Interpretor& theDI,
5290                  Standard_Integer  theArgNb,
5291                  const char**      theArgVec)
5292 {
5293   const Standard_Boolean toSet    = (theArgNb > 1);
5294   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5295   if (toSet)
5296   {
5297     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5298   }
5299
5300   // get the context
5301   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5302   if (aContextAIS.IsNull())
5303   {
5304     if (!toSet)
5305     {
5306       std::cerr << "No active view!\n";
5307     }
5308     return 1;
5309   }
5310   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5311   if (!aDriver.IsNull())
5312   {
5313     if (!toSet)
5314     {
5315       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5316     }
5317     else
5318     {
5319       aDriver->ChangeOptions().vboDisable = toUseVbo;
5320     }
5321   }
5322
5323   return 0;
5324 }
5325
5326 //==============================================================================
5327 //function : VCaps
5328 //purpose  :
5329 //==============================================================================
5330
5331 static int VCaps (Draw_Interpretor& theDI,
5332                   Standard_Integer  theArgNb,
5333                   const char**      theArgVec)
5334 {
5335   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5336   Handle(OpenGl_GraphicDriver)   aDriver;
5337   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5338   if (!aContext.IsNull())
5339   {
5340     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5341     aCaps   = &aDriver->ChangeOptions();
5342   }
5343
5344   if (theArgNb < 2)
5345   {
5346     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5347     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5348     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5349     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5350     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5351     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5352     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5353     return 0;
5354   }
5355
5356   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5357   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5358   {
5359     Standard_CString        anArg     = theArgVec[anArgIter];
5360     TCollection_AsciiString anArgCase (anArg);
5361     anArgCase.LowerCase();
5362     if (anUpdateTool.parseRedrawMode (anArg))
5363     {
5364       continue;
5365     }
5366     else if (anArgCase == "-vsync"
5367           || anArgCase == "-swapinterval")
5368     {
5369       Standard_Boolean toEnable = Standard_True;
5370       if (++anArgIter < theArgNb
5371       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5372       {
5373         --anArgIter;
5374       }
5375       aCaps->swapInterval = toEnable;
5376     }
5377     else if (anArgCase == "-ffp")
5378     {
5379       Standard_Boolean toEnable = Standard_True;
5380       if (++anArgIter < theArgNb
5381       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5382       {
5383         --anArgIter;
5384       }
5385       aCaps->ffpEnable = toEnable;
5386     }
5387     else if (anArgCase == "-vbo")
5388     {
5389       Standard_Boolean toEnable = Standard_True;
5390       if (++anArgIter < theArgNb
5391       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5392       {
5393         --anArgIter;
5394       }
5395       aCaps->vboDisable = !toEnable;
5396     }
5397     else if (anArgCase == "-sprite"
5398           || anArgCase == "-sprites")
5399     {
5400       Standard_Boolean toEnable = Standard_True;
5401       if (++anArgIter < theArgNb
5402       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5403       {
5404         --anArgIter;
5405       }
5406       aCaps->pntSpritesDisable = !toEnable;
5407     }
5408     else if (anArgCase == "-softmode")
5409     {
5410       Standard_Boolean toEnable = Standard_True;
5411       if (++anArgIter < theArgNb
5412       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5413       {
5414         --anArgIter;
5415       }
5416       aCaps->contextNoAccel = toEnable;
5417     }
5418     else if (anArgCase == "-accel"
5419           || anArgCase == "-acceleration")
5420     {
5421       Standard_Boolean toEnable = Standard_True;
5422       if (++anArgIter < theArgNb
5423       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5424       {
5425         --anArgIter;
5426       }
5427       aCaps->contextNoAccel = !toEnable;
5428     }
5429     else if (anArgCase == "-compat"
5430           || anArgCase == "-compatprofile"
5431           || anArgCase == "-compatible"
5432           || anArgCase == "-compatibleprofile")
5433     {
5434       Standard_Boolean toEnable = Standard_True;
5435       if (++anArgIter < theArgNb
5436       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5437       {
5438         --anArgIter;
5439       }
5440       aCaps->contextCompatible = toEnable;
5441       if (!aCaps->contextCompatible)
5442       {
5443         aCaps->ffpEnable = Standard_False;
5444       }
5445     }
5446     else if (anArgCase == "-core"
5447           || anArgCase == "-coreprofile")
5448     {
5449       Standard_Boolean toEnable = Standard_True;
5450       if (++anArgIter < theArgNb
5451       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5452       {
5453         --anArgIter;
5454       }
5455       aCaps->contextCompatible = !toEnable;
5456       if (!aCaps->contextCompatible)
5457       {
5458         aCaps->ffpEnable = Standard_False;
5459       }
5460     }
5461     else if (anArgCase == "-stereo"
5462           || anArgCase == "-quadbuffer")
5463     {
5464       Standard_Boolean toEnable = Standard_True;
5465       if (++anArgIter < theArgNb
5466       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5467       {
5468         --anArgIter;
5469       }
5470       aCaps->contextStereo = toEnable;
5471     }
5472     else
5473     {
5474       std::cout << "Error: unknown argument '" << anArg << "'\n";
5475       return 1;
5476     }
5477   }
5478   if (aCaps != &ViewerTest_myDefaultCaps)
5479   {
5480     ViewerTest_myDefaultCaps = *aCaps;
5481   }
5482   return 0;
5483 }
5484
5485 //==============================================================================
5486 //function : VMemGpu
5487 //purpose  :
5488 //==============================================================================
5489
5490 static int VMemGpu (Draw_Interpretor& theDI,
5491                     Standard_Integer  theArgNb,
5492                     const char**      theArgVec)
5493 {
5494   // get the context
5495   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5496   if (aContextAIS.IsNull())
5497   {
5498     std::cerr << "No active view. Please call vinit.\n";
5499     return 1;
5500   }
5501
5502   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5503   if (aDriver.IsNull())
5504   {
5505     std::cerr << "Graphic driver not available.\n";
5506     return 1;
5507   }
5508
5509   Standard_Size aFreeBytes = 0;
5510   TCollection_AsciiString anInfo;
5511   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5512   {
5513     std::cerr << "Information not available.\n";
5514     return 1;
5515   }
5516
5517   if (theArgNb > 1 && *theArgVec[1] == 'f')
5518   {
5519     theDI << Standard_Real (aFreeBytes);
5520   }
5521   else
5522   {
5523     theDI << anInfo;
5524   }
5525
5526   return 0;
5527 }
5528
5529 // ==============================================================================
5530 // function : VReadPixel
5531 // purpose  :
5532 // ==============================================================================
5533 static int VReadPixel (Draw_Interpretor& theDI,
5534                        Standard_Integer  theArgNb,
5535                        const char**      theArgVec)
5536 {
5537   // get the active view
5538   Handle(V3d_View) aView = ViewerTest::CurrentView();
5539   if (aView.IsNull())
5540   {
5541     std::cerr << "No active view. Please call vinit.\n";
5542     return 1;
5543   }
5544   else if (theArgNb < 3)
5545   {
5546     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5547     return 1;
5548   }
5549
5550   Image_PixMap::ImgFormat aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
5551   Graphic3d_BufferType    aBufferType = Graphic3d_BT_RGBA;
5552
5553   Standard_Integer aWidth, aHeight;
5554   aView->Window()->Size (aWidth, aHeight);
5555   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5556   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5557   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5558   {
5559     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5560     return 1;
5561   }
5562
5563   Standard_Boolean toShowName = Standard_False;
5564   Standard_Boolean toShowHls  = Standard_False;
5565   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5566   {
5567     const char* aParam = theArgVec[anIter];
5568     if ( strcasecmp( aParam, "rgb" ) == 0 )
5569     {
5570       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
5571       aBufferType = Graphic3d_BT_RGB;
5572     }
5573     else if ( strcasecmp( aParam, "hls" ) == 0 )
5574     {
5575       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGB : Image_PixMap::ImgBGR;
5576       aBufferType = Graphic3d_BT_RGB;
5577       toShowHls   = Standard_True;
5578     }
5579     else if ( strcasecmp( aParam, "rgbf" ) == 0 )
5580     {
5581       aFormat     = Image_PixMap::ImgRGBF;
5582       aBufferType = Graphic3d_BT_RGB;
5583     }
5584     else if ( strcasecmp( aParam, "rgba" ) == 0 )
5585     {
5586       aFormat     = Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
5587       aBufferType = Graphic3d_BT_RGBA;
5588     }
5589     else if ( strcasecmp( aParam, "rgbaf" ) == 0 )
5590     {
5591       aFormat     = Image_PixMap::ImgRGBAF;
5592       aBufferType = Graphic3d_BT_RGBA;
5593     }
5594     else if ( strcasecmp( aParam, "depth" ) == 0 )
5595     {
5596       aFormat     = Image_PixMap::ImgGrayF;
5597       aBufferType = Graphic3d_BT_Depth;
5598     }
5599     else if ( strcasecmp( aParam, "name" ) == 0 )
5600     {
5601       toShowName = Standard_True;
5602     }
5603   }
5604
5605   Image_PixMap anImage;
5606   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5607   {
5608     std::cerr << "Image allocation failed\n";
5609     return 1;
5610   }
5611   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5612   {
5613     std::cerr << "Image dump failed\n";
5614     return 1;
5615   }
5616
5617   Quantity_Parameter anAlpha;
5618   Quantity_Color aColor = anImage.PixelColor (anX, anY, anAlpha);
5619   if (toShowName)
5620   {
5621     if (aBufferType == Graphic3d_BT_RGBA)
5622     {
5623       theDI << Quantity_Color::StringName (aColor.Name()) << " " << anAlpha;
5624     }
5625     else
5626     {
5627       theDI << Quantity_Color::StringName (aColor.Name());
5628     }
5629   }
5630   else
5631   {
5632     switch (aBufferType)
5633     {
5634       default:
5635       case Graphic3d_BT_RGB:
5636       {
5637         if (toShowHls)
5638         {
5639           theDI << aColor.Hue() << " " << aColor.Light() << " " << aColor.Saturation();
5640         }
5641         else
5642         {
5643           theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue();
5644         }
5645         break;
5646       }
5647       case Graphic3d_BT_RGBA:
5648       {
5649         theDI << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " " << anAlpha;
5650         break;
5651       }
5652       case Graphic3d_BT_Depth:
5653       {
5654         theDI << aColor.Red();
5655         break;
5656       }
5657     }
5658   }
5659
5660   return 0;
5661 }
5662
5663 //==============================================================================
5664 //function : VDiffImage
5665 //purpose  : The draw-command compares two images.
5666 //==============================================================================
5667
5668 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5669 {
5670   if (theArgNb < 6)
5671   {
5672     theDI << "Not enough arguments.\n";
5673     return 1;
5674   }
5675
5676   // image file names
5677   const char* anImgPathRef = theArgVec[1];
5678   const char* anImgPathNew = theArgVec[2];
5679
5680   // get string tolerance and check its validity
5681   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5682   if (aTolColor < 0.0)
5683     aTolColor = 0.0;
5684   if (aTolColor > 1.0)
5685     aTolColor = 1.0;
5686
5687   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5688   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5689
5690   // image file of difference
5691   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5692
5693   // compare the images
5694   Image_Diff aComparer;
5695   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5696   {
5697     return 1;
5698   }
5699
5700   aComparer.SetColorTolerance (aTolColor);
5701   aComparer.SetBorderFilterOn (isBorderFilterOn);
5702   Standard_Integer aDiffColorsNb = aComparer.Compare();
5703   theDI << aDiffColorsNb << "\n";
5704
5705   // save image of difference
5706   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5707   {
5708     aComparer.SaveDiffImage (aDiffImagePath);
5709   }
5710
5711   return 0;
5712 }
5713
5714 //=======================================================================
5715 //function : VSelect
5716 //purpose  : Emulates different types of selection by mouse:
5717 //           1) single click selection
5718 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5719 //           3) selection with polygon having corners at
5720 //           pixel positions (x1,y1),...,(xn,yn)
5721 //           4) any of these selections with shift button pressed
5722 //=======================================================================
5723 static Standard_Integer VSelect (Draw_Interpretor& di,
5724                                  Standard_Integer argc,
5725                                  const char ** argv)
5726 {
5727   if(argc < 3)
5728   {
5729     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5730     return 1;
5731   }
5732
5733   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5734   if(myAIScontext.IsNull())
5735   {
5736     di << "use 'vinit' command before " << argv[0] << "\n";
5737     return 1;
5738   }
5739
5740   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5741   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5742   TCollection_AsciiString anArg;
5743   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5744   anArg.LowerCase();
5745   if (anArg == "-allowoverlap")
5746   {
5747     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5748       : argc == 7;
5749     if (!isValidated)
5750     {
5751       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5752       return 1;
5753     }
5754
5755     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5756     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5757     aCoordsNb -= 2;
5758   }
5759
5760   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5761   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5762   if(aCoordsNb == 2)
5763   {
5764     if(isShiftSelection)
5765       aCurrentEventManager->ShiftSelect();
5766     else
5767       aCurrentEventManager->Select();
5768   }
5769   else if(aCoordsNb == 4)
5770   {
5771     if(isShiftSelection)
5772       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5773     else
5774       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
5775   }
5776   else
5777   {
5778     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
5779
5780     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
5781       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
5782
5783     if(isShiftSelection)
5784       aCurrentEventManager->ShiftSelect(aPolyline);
5785     else
5786       aCurrentEventManager->Select(aPolyline);
5787   }
5788   return 0;
5789 }
5790
5791 //=======================================================================
5792 //function : VMoveTo
5793 //purpose  : Emulates cursor movement to defined pixel position
5794 //=======================================================================
5795 static Standard_Integer VMoveTo (Draw_Interpretor& di,
5796                                 Standard_Integer argc,
5797                                 const char ** argv)
5798 {
5799   if(argc != 3)
5800   {
5801     di << "Usage : " << argv[0] << " x y\n";
5802     return 1;
5803   }
5804
5805   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5806   if(aContext.IsNull())
5807   {
5808     di << "use 'vinit' command before " << argv[0] << "\n";
5809     return 1;
5810   }
5811   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
5812   return 0;
5813 }
5814
5815 //=================================================================================================
5816 //function : VViewParams
5817 //purpose  : Gets or sets AIS View characteristics
5818 //=================================================================================================
5819 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
5820 {
5821   Handle(V3d_View) anAISView = ViewerTest::CurrentView();
5822   if (anAISView.IsNull())
5823   {
5824     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
5825     return 1;
5826   }
5827
5828   if (theArgsNb == 1)
5829   {
5830     // print all of the available view parameters
5831     Quantity_Factor anAISViewScale = anAISView->Scale();
5832
5833     Standard_Real anAISViewProjX = 0.0;
5834     Standard_Real anAISViewProjY = 0.0;
5835     Standard_Real anAISViewProjZ = 0.0;
5836     anAISView->Proj (anAISViewProjX, anAISViewProjY, anAISViewProjZ);
5837
5838     Standard_Real anAISViewUpX = 0.0;
5839     Standard_Real anAISViewUpY = 0.0;
5840     Standard_Real anAISViewUpZ = 0.0;
5841     anAISView->Up (anAISViewUpX, anAISViewUpY, anAISViewUpZ);
5842
5843     Standard_Real anAISViewAtX = 0.0;
5844     Standard_Real anAISViewAtY = 0.0;
5845     Standard_Real anAISViewAtZ = 0.0;
5846     anAISView->At (anAISViewAtX, anAISViewAtY, anAISViewAtZ);
5847
5848     Standard_Real anAISViewEyeX = 0.0;
5849     Standard_Real anAISViewEyeY = 0.0;
5850     Standard_Real anAISViewEyeZ = 0.0;
5851     anAISView->Eye (anAISViewEyeX, anAISViewEyeY, anAISViewEyeZ);
5852
5853     theDi << "Scale of current view: " << anAISViewScale << "\n";
5854     theDi << "Proj on X : " << anAISViewProjX << "; on Y: " << anAISViewProjY << "; on Z: " << anAISViewProjZ << "\n";
5855     theDi << "Up on X : " << anAISViewUpX << "; on Y: " << anAISViewUpY << "; on Z: " << anAISViewUpZ << "\n";
5856     theDi << "At on X : " << anAISViewAtX << "; on Y: " << anAISViewAtY << "; on Z: " << anAISViewAtZ << "\n";
5857     theDi << "Eye on X : " << anAISViewEyeX << "; on Y: " << anAISViewEyeY << "; on Z: " << anAISViewEyeZ << "\n";
5858     return 0;
5859   }
5860
5861   // -------------------------
5862   //  Parse options and values
5863   // -------------------------
5864
5865   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfKeysByValues;
5866   TCollection_AsciiString aParseKey;
5867   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
5868   {
5869     TCollection_AsciiString anArg (theArgVec [anArgIt]);
5870
5871     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
5872     {
5873       aParseKey = anArg;
5874       aParseKey.Remove (1);
5875       aParseKey.UpperCase();
5876       aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
5877       continue;
5878     }
5879
5880     if (aParseKey.IsEmpty())
5881     {
5882       std::cout << theArgVec[0] << ": values should be passed with key.\n";
5883       std::cout << "Type help for more information.\n";
5884       return 1;
5885     }
5886
5887     aMapOfKeysByValues(aParseKey)->Append (anArg);
5888   }
5889
5890   // ---------------------------------------------
5891   //  Change or print parameters, order plays role
5892   // ---------------------------------------------
5893
5894   // Check arguments for validity
5895   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfKeysByValues);
5896   for (; aMapIt.More(); aMapIt.Next())
5897   {
5898     const TCollection_AsciiString& aKey = aMapIt.Key();
5899     const Handle(TColStd_HSequenceOfAsciiString)& aValues = aMapIt.Value();
5900
5901     if (!(aKey.IsEqual ("SCALE")  && (aValues->Length() == 1 || aValues->IsEmpty()))
5902      && !(aKey.IsEqual ("SIZE")   && (aValues->Length() == 1 || aValues->IsEmpty()))
5903      && !(aKey.IsEqual ("EYE")    && (aValues->Length() == 3 || aValues->IsEmpty()))
5904      && !(aKey.IsEqual ("AT")     && (aValues->Length() == 3 || aValues->IsEmpty()))
5905      && !(aKey.IsEqual ("UP")     && (aValues->Length() == 3 || aValues->IsEmpty()))
5906      && !(aKey.IsEqual ("PROJ")   && (aValues->Length() == 3 || aValues->IsEmpty()))
5907      && !(aKey.IsEqual ("CENTER") &&  aValues->Length() == 2))
5908     {
5909       TCollection_AsciiString aLowerKey;
5910       aLowerKey  = "-";
5911       aLowerKey += aKey;
5912       aLowerKey.LowerCase();
5913       std::cout << theArgVec[0] << ": " << aLowerKey << " is unknown option, or number of arguments is invalid.\n";
5914       std::cout << "Type help for more information.\n";
5915       return 1;
5916     }
5917   }
5918
5919   Handle(TColStd_HSequenceOfAsciiString) aValues;
5920
5921   // Change view parameters in proper order
5922   if (aMapOfKeysByValues.Find ("SCALE", aValues))
5923   {
5924     if (aValues->IsEmpty())
5925     {
5926       theDi << "Scale: " << anAISView->Scale() << "\n";
5927     }
5928     else
5929     {
5930       anAISView->SetScale (aValues->Value(1).RealValue());
5931     }
5932   }
5933   if (aMapOfKeysByValues.Find ("SIZE", aValues))
5934   {
5935     if (aValues->IsEmpty())
5936     {
5937       Standard_Real aSizeX = 0.0;
5938       Standard_Real aSizeY = 0.0;
5939       anAISView->Size (aSizeX, aSizeY);
5940       theDi << "Size X: " << aSizeX << " Y: " << aSizeY << "\n";
5941     }
5942     else
5943     {
5944       anAISView->SetSize (aValues->Value(1).RealValue());
5945     }
5946   }
5947   if (aMapOfKeysByValues.Find ("EYE", aValues))
5948   {
5949     if (aValues->IsEmpty())
5950     {
5951       Standard_Real anEyeX = 0.0;
5952       Standard_Real anEyeY = 0.0;
5953       Standard_Real anEyeZ = 0.0;
5954       anAISView->Eye (anEyeX, anEyeY, anEyeZ);
5955       theDi << "Eye X: " << anEyeX << " Y: " << anEyeY << " Z: " << anEyeZ << "\n";
5956     }
5957     else
5958     {
5959       anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5960     }
5961   }
5962   if (aMapOfKeysByValues.Find ("AT", aValues))
5963   {
5964     if (aValues->IsEmpty())
5965     {
5966       Standard_Real anAtX = 0.0;
5967       Standard_Real anAtY = 0.0;
5968       Standard_Real anAtZ = 0.0;
5969       anAISView->At (anAtX, anAtY, anAtZ);
5970       theDi << "At X: " << anAtX << " Y: " << anAtY << " Z: " << anAtZ << "\n";
5971     }
5972     else
5973     {
5974       anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5975     }
5976   }
5977   if (aMapOfKeysByValues.Find ("PROJ", aValues))
5978   {
5979     if (aValues->IsEmpty())
5980     {
5981       Standard_Real aProjX = 0.0;
5982       Standard_Real aProjY = 0.0;
5983       Standard_Real aProjZ = 0.0;
5984       anAISView->Proj (aProjX, aProjY, aProjZ);
5985       theDi << "Proj X: " << aProjX << " Y: " << aProjY << " Z: " << aProjZ << "\n";
5986     }
5987     else
5988     {
5989       anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
5990     }
5991   }
5992   if (aMapOfKeysByValues.Find ("UP", aValues))
5993   {
5994     if (aValues->IsEmpty())
5995     {
5996       Standard_Real anUpX = 0.0;
5997       Standard_Real anUpY = 0.0;
5998       Standard_Real anUpZ = 0.0;
5999       anAISView->Up (anUpX, anUpY, anUpZ);
6000       theDi << "Up X: " << anUpX << " Y: " << anUpY << " Z: " << anUpZ << "\n";
6001     }
6002     else
6003     {
6004       anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue());
6005     }
6006   }
6007   if (aMapOfKeysByValues.Find ("CENTER", aValues))
6008   {
6009     anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue());
6010   }
6011
6012   return 0;
6013 }
6014
6015 //=======================================================================
6016 //function : VChangeSelected
6017 //purpose  : Adds the shape to selection or remove one from it
6018 //=======================================================================
6019 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6020                                 Standard_Integer argc,
6021                                 const char ** argv)
6022 {
6023   if(argc != 2)
6024   {
6025     di<<"Usage : " << argv[0] << " shape \n";
6026     return 1;
6027   }
6028   //get AIS_Shape:
6029   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6030   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6031   TCollection_AsciiString aName(argv[1]);
6032   Handle(AIS_InteractiveObject) anAISObject;
6033
6034   if(!aMap.IsBound2(aName))
6035   {
6036     di<<"Use 'vdisplay' before";
6037     return 1;
6038   }
6039   else
6040   {
6041     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6042     if(anAISObject.IsNull()){
6043       di<<"No interactive object \n";
6044       return 1;
6045     }
6046
6047     aContext->AddOrRemoveSelected(anAISObject);
6048   }
6049   return 0;
6050 }
6051
6052 //=======================================================================
6053 //function : VNbSelected
6054 //purpose  : Returns number of selected objects
6055 //=======================================================================
6056 static Standard_Integer VNbSelected (Draw_Interpretor& di,
6057                                 Standard_Integer argc,
6058                                 const char ** argv)
6059 {
6060   if(argc != 1)
6061   {
6062     di << "Usage : " << argv[0] << "\n";
6063     return 1;
6064   }
6065   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6066   if(aContext.IsNull())
6067   {
6068     di << "use 'vinit' command before " << argv[0] << "\n";
6069     return 1;
6070   }
6071   di << aContext->NbSelected() << "\n";
6072   return 0;
6073 }
6074
6075 //=======================================================================
6076 //function : VPurgeDisplay
6077 //purpose  : Switches altialiasing on or off
6078 //=======================================================================
6079 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
6080                                 Standard_Integer argc,
6081                                 const char ** argv)
6082 {
6083   if (argc > 1)
6084   {
6085     di << "Usage : " << argv[0] << "\n";
6086     return 1;
6087   }
6088   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6089   if (aContext.IsNull())
6090   {
6091     di << "use 'vinit' command before " << argv[0] << "\n";
6092     return 1;
6093   }
6094   aContext->CloseAllContexts(Standard_False);
6095   di << aContext->PurgeDisplay() << "\n";
6096   return 0;
6097 }
6098
6099 //=======================================================================
6100 //function : VSetViewSize
6101 //purpose  :
6102 //=======================================================================
6103 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
6104                                 Standard_Integer argc,
6105                                 const char ** argv)
6106 {
6107   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6108   if(aContext.IsNull())
6109   {
6110     di << "use 'vinit' command before " << argv[0] << "\n";
6111     return 1;
6112   }
6113   if(argc != 2)
6114   {
6115     di<<"Usage : " << argv[0] << " Size\n";
6116     return 1;
6117   }
6118   Standard_Real aSize = Draw::Atof (argv[1]);
6119   if (aSize <= 0.)
6120   {
6121     di<<"Bad Size value  : " << aSize << "\n";
6122     return 1;
6123   }
6124
6125   Handle(V3d_View) aView = ViewerTest::CurrentView();
6126   aView->SetSize(aSize);
6127   return 0;
6128 }
6129
6130 //=======================================================================
6131 //function : VMoveView
6132 //purpose  :
6133 //=======================================================================
6134 static Standard_Integer VMoveView (Draw_Interpretor& di,
6135                                 Standard_Integer argc,
6136                                 const char ** argv)
6137 {
6138   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6139   if(aContext.IsNull())
6140   {
6141     di << "use 'vinit' command before " << argv[0] << "\n";
6142     return 1;
6143   }
6144   if(argc < 4 || argc > 5)
6145   {
6146     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
6147     return 1;
6148   }
6149   Standard_Real Dx = Draw::Atof (argv[1]);
6150   Standard_Real Dy = Draw::Atof (argv[2]);
6151   Standard_Real Dz = Draw::Atof (argv[3]);
6152   Standard_Boolean aStart = Standard_True;
6153   if (argc == 5)
6154   {
6155       aStart = (Draw::Atoi (argv[4]) > 0);
6156   }
6157
6158   Handle(V3d_View) aView = ViewerTest::CurrentView();
6159   aView->Move(Dx,Dy,Dz,aStart);
6160   return 0;
6161 }
6162
6163 //=======================================================================
6164 //function : VTranslateView
6165 //purpose  :
6166 //=======================================================================
6167 static Standard_Integer VTranslateView (Draw_Interpretor& di,
6168                                 Standard_Integer argc,
6169                                 const char ** argv)
6170 {
6171   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6172   if(aContext.IsNull())
6173   {
6174     di << "use 'vinit' command before " << argv[0] << "\n";
6175     return 1;
6176   }
6177   if(argc < 4 || argc > 5)
6178   {
6179     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
6180     return 1;
6181   }
6182   Standard_Real Dx = Draw::Atof (argv[1]);
6183   Standard_Real Dy = Draw::Atof (argv[2]);
6184   Standard_Real Dz = Draw::Atof (argv[3]);
6185   Standard_Boolean aStart = Standard_True;
6186   if (argc == 5)
6187   {
6188       aStart = (Draw::Atoi (argv[4]) > 0);
6189   }
6190
6191   Handle(V3d_View) aView = ViewerTest::CurrentView();
6192   aView->Translate(Dx,Dy,Dz,aStart);
6193   return 0;
6194 }
6195
6196 //=======================================================================
6197 //function : VTurnView
6198 //purpose  :
6199 //=======================================================================
6200 static Standard_Integer VTurnView (Draw_Interpretor& di,
6201                                 Standard_Integer argc,
6202                                 const char ** argv)
6203 {
6204   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6205   if(aContext.IsNull()) {
6206     di << "use 'vinit' command before " << argv[0] << "\n";
6207     return 1;
6208   }
6209   if(argc < 4 || argc > 5){
6210     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
6211     return 1;
6212   }
6213   Standard_Real Ax = Draw::Atof (argv[1]);
6214   Standard_Real Ay = Draw::Atof (argv[2]);
6215   Standard_Real Az = Draw::Atof (argv[3]);
6216   Standard_Boolean aStart = Standard_True;
6217   if (argc == 5)
6218   {
6219       aStart = (Draw::Atoi (argv[4]) > 0);
6220   }
6221
6222   Handle(V3d_View) aView = ViewerTest::CurrentView();
6223   aView->Turn(Ax,Ay,Az,aStart);
6224   return 0;
6225 }
6226
6227 //==============================================================================
6228 //function : VTextureEnv
6229 //purpose  : ENables or disables environment mapping
6230 //==============================================================================
6231 class OCC_TextureEnv : public Graphic3d_TextureEnv
6232 {
6233 public:
6234   OCC_TextureEnv(const Standard_CString FileName);
6235   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
6236   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
6237                             const Standard_Boolean theModulateFlag,
6238                             const Graphic3d_TypeOfTextureFilter theFilter,
6239                             const Standard_ShortReal theXScale,
6240                             const Standard_ShortReal theYScale,
6241                             const Standard_ShortReal theXShift,
6242                             const Standard_ShortReal theYShift,
6243                             const Standard_ShortReal theAngle);
6244   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
6245 };
6246 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
6247
6248 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
6249   : Graphic3d_TextureEnv(theFileName)
6250 {
6251 }
6252
6253 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
6254   : Graphic3d_TextureEnv(theTexId)
6255 {
6256 }
6257
6258 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
6259                                           const Standard_Boolean theModulateFlag,
6260                                           const Graphic3d_TypeOfTextureFilter theFilter,
6261                                           const Standard_ShortReal theXScale,
6262                                           const Standard_ShortReal theYScale,
6263                                           const Standard_ShortReal theXShift,
6264                                           const Standard_ShortReal theYShift,
6265                                           const Standard_ShortReal theAngle)
6266 {
6267   myParams->SetRepeat     (theRepeatFlag);
6268   myParams->SetModulate   (theModulateFlag);
6269   myParams->SetFilter     (theFilter);
6270   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
6271   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
6272   myParams->SetRotation   (theAngle);
6273 }
6274
6275 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
6276 {
6277   // get the active view
6278   Handle(V3d_View) aView = ViewerTest::CurrentView();
6279   if (aView.IsNull())
6280   {
6281     std::cerr << "No active view. Please call vinit.\n";
6282     return 1;
6283   }
6284
6285   // Checking the input arguments
6286   Standard_Boolean anEnableFlag = Standard_False;
6287   Standard_Boolean isOk         = theArgNb >= 2;
6288   if (isOk)
6289   {
6290     TCollection_AsciiString anEnableOpt(theArgVec[1]);
6291     anEnableFlag = anEnableOpt.IsEqual("on");
6292     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
6293   }
6294   if (anEnableFlag)
6295   {
6296     isOk = (theArgNb == 3 || theArgNb == 11);
6297     if (isOk)
6298     {
6299       TCollection_AsciiString aTextureOpt(theArgVec[2]);
6300       isOk = (!aTextureOpt.IsIntegerValue() ||
6301              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
6302
6303       if (isOk && theArgNb == 11)
6304       {
6305         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
6306                                 aModulateOpt(theArgVec[4]),
6307                                 aFilterOpt  (theArgVec[5]),
6308                                 aSScaleOpt  (theArgVec[6]),
6309                                 aTScaleOpt  (theArgVec[7]),
6310                                 aSTransOpt  (theArgVec[8]),
6311                                 aTTransOpt  (theArgVec[9]),
6312                                 anAngleOpt  (theArgVec[10]);
6313         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
6314                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
6315                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
6316                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
6317                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
6318                 anAngleOpt.IsRealValue());
6319       }
6320     }
6321   }
6322
6323   if (!isOk)
6324   {
6325     std::cerr << "Usage :" << std::endl;
6326     std::cerr << theArgVec[0] << " off" << std::endl;
6327     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;
6328     return 1;
6329   }
6330
6331   if (anEnableFlag)
6332   {
6333     TCollection_AsciiString aTextureOpt(theArgVec[2]);
6334     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
6335                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
6336                                      new OCC_TextureEnv(theArgVec[2]);
6337
6338     if (theArgNb == 11)
6339     {
6340       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
6341       aTexEnv->SetTextureParameters(
6342         aRepeatOpt.  IsEqual("repeat"),
6343         aModulateOpt.IsEqual("modulate"),
6344         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
6345                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
6346                                                                            Graphic3d_TOTF_TRILINEAR,
6347         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
6348         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
6349         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
6350         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
6351         (Standard_ShortReal)Draw::Atof(theArgVec[10])
6352         );
6353     }
6354     aView->SetTextureEnv(aTexEnv);
6355   }
6356   else // Disabling environment mapping
6357   {
6358     Handle(Graphic3d_TextureEnv) aTexture;
6359     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
6360   }
6361
6362   aView->Redraw();
6363   return 0;
6364 }
6365
6366 namespace
6367 {
6368   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
6369
6370   //! Remove registered clipping plane from all views and objects.
6371   static void removePlane (MapOfPlanes& theRegPlanes,
6372                            const TCollection_AsciiString& theName)
6373   {
6374     Handle(Graphic3d_ClipPlane) aClipPlane;
6375     if (!theRegPlanes.Find (theName, aClipPlane))
6376     {
6377       std::cout << "Warning: no such plane.\n";
6378       return;
6379     }
6380
6381     theRegPlanes.UnBind (theName);
6382     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
6383          anIObjIt.More(); anIObjIt.Next())
6384     {
6385       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
6386       aPrs->RemoveClipPlane (aClipPlane);
6387     }
6388
6389     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
6390          aViewIt.More(); aViewIt.Next())
6391     {
6392       const Handle(V3d_View)& aView = aViewIt.Key2();
6393       aView->RemoveClipPlane(aClipPlane);
6394     }
6395
6396     ViewerTest::RedrawAllViews();
6397   }
6398 }
6399
6400 //===============================================================================================
6401 //function : VClipPlane
6402 //purpose  :
6403 //===============================================================================================
6404 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6405 {
6406   // use short-cut for created clip planes map of created (or "registered by name") clip planes
6407   static MapOfPlanes aRegPlanes;
6408
6409   if (theArgsNb < 2)
6410   {
6411     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
6412     {
6413       theDi << aPlaneIter.Key() << " ";
6414     }
6415     return 0;
6416   }
6417
6418   TCollection_AsciiString aCommand (theArgVec[1]);
6419   aCommand.LowerCase();
6420   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
6421   if (anActiveView.IsNull())
6422   {
6423     std::cout << "Error: no active view.\n";
6424     return 1;
6425   }
6426
6427   // print maximum number of planes for current viewer
6428   if (aCommand == "-maxplanes"
6429    || aCommand == "maxplanes")
6430   {
6431     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
6432           << " plane slots provided by driver.\n";
6433     return 0;
6434   }
6435
6436   // create / delete plane instance
6437   if (aCommand == "-create"
6438    || aCommand == "create"
6439    || aCommand == "-delete"
6440    || aCommand == "delete"
6441    || aCommand == "-clone"
6442    || aCommand == "clone")
6443   {
6444     if (theArgsNb < 3)
6445     {
6446       std::cout << "Syntax error: plane name is required.\n";
6447       return 1;
6448     }
6449
6450     Standard_Boolean toCreate = aCommand == "-create"
6451                              || aCommand == "create";
6452     Standard_Boolean toClone  = aCommand == "-clone"
6453                              || aCommand == "clone";
6454     Standard_Boolean toDelete = aCommand == "-delete"
6455                              || aCommand == "delete";
6456     TCollection_AsciiString aPlane (theArgVec[2]);
6457
6458     if (toCreate)
6459     {
6460       if (aRegPlanes.IsBound (aPlane))
6461       {
6462         std::cout << "Warning: existing plane has been overridden.\n";
6463         toDelete = true;
6464       }
6465       else
6466       {
6467         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
6468         return 0;
6469       }
6470     }
6471     else if (toClone) // toClone
6472     {
6473       if (!aRegPlanes.IsBound (aPlane))
6474       {
6475         std::cout << "Error: no such plane.\n";
6476         return 1;
6477       }
6478       else if (theArgsNb < 4)
6479       {
6480         std::cout << "Syntax error: enter name for new plane.\n";
6481         return 1;
6482       }
6483
6484       TCollection_AsciiString aClone (theArgVec[3]);
6485       if (aRegPlanes.IsBound (aClone))
6486       {
6487         std::cout << "Error: plane name is in use.\n";
6488         return 1;
6489       }
6490
6491       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
6492
6493       aRegPlanes.Bind (aClone, aClipPlane->Clone());
6494       return 0;
6495     }
6496
6497     if (toDelete)
6498     {
6499       if (aPlane == "ALL"
6500        || aPlane == "all"
6501        || aPlane == "*")
6502       {
6503         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
6504         {
6505           aPlane = aPlaneIter.Key();
6506           removePlane (aRegPlanes, aPlane);
6507           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
6508         }
6509       }
6510       else
6511       {
6512         removePlane (aRegPlanes, aPlane);
6513       }
6514     }
6515
6516     if (toCreate)
6517     {
6518       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
6519     }
6520     return 0;
6521   }
6522
6523   // set / unset plane command
6524   if (aCommand == "set"
6525    || aCommand == "unset")
6526   {
6527     if (theArgsNb < 5)
6528     {
6529       std::cout << "Syntax error: need more arguments.\n";
6530       return 1;
6531     }
6532
6533     // redirect to new syntax
6534     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
6535     anArgVec.SetValue (1, theArgVec[0]);
6536     anArgVec.SetValue (2, theArgVec[2]);
6537     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
6538     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
6539     {
6540       anArgVec.SetValue (anIt, theArgVec[anIt]);
6541     }
6542
6543     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
6544   }
6545
6546   // change plane command
6547   TCollection_AsciiString aPlaneName;
6548   Handle(Graphic3d_ClipPlane) aClipPlane;
6549   Standard_Integer anArgIter = 0;
6550   if (aCommand == "-change"
6551    || aCommand == "change")
6552   {
6553     // old syntax support
6554     if (theArgsNb < 3)
6555     {
6556       std::cout << "Syntax error: need more arguments.\n";
6557       return 1;
6558     }
6559
6560     anArgIter  = 3;
6561     aPlaneName = theArgVec[2];
6562     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
6563     {
6564       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
6565       return 1;
6566     }
6567   }
6568   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
6569   {
6570     anArgIter  = 2;
6571     aPlaneName = theArgVec[1];
6572   }
6573   else
6574   {
6575     anArgIter  = 2;
6576     aPlaneName = theArgVec[1];
6577     aClipPlane = new Graphic3d_ClipPlane();
6578     aRegPlanes.Bind (aPlaneName, aClipPlane);
6579     theDi << "Created new plane " << aPlaneName << ".\n";
6580   }
6581
6582   if (theArgsNb - anArgIter < 1)
6583   {
6584     std::cout << "Syntax error: need more arguments.\n";
6585     return 1;
6586   }
6587
6588   for (; anArgIter < theArgsNb; ++anArgIter)
6589   {
6590     const char**     aChangeArgs   = theArgVec + anArgIter;
6591     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
6592     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
6593     aChangeArg.LowerCase();
6594
6595     Standard_Boolean toEnable = Standard_True;
6596     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
6597     {
6598       aClipPlane->SetOn (toEnable);
6599     }
6600     else if (aChangeArg == "-equation"
6601           || aChangeArg == "equation")
6602     {
6603       if (aNbChangeArgs < 5)
6604       {
6605         std::cout << "Syntax error: need more arguments.\n";
6606         return 1;
6607       }
6608
6609       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
6610       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
6611       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
6612       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
6613       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
6614       anArgIter += 4;
6615     }
6616     else if (aChangeArg == "-capping"
6617           || aChangeArg == "capping")
6618     {
6619       if (aNbChangeArgs < 2)
6620       {
6621         std::cout << "Syntax error: need more arguments.\n";
6622         return 1;
6623       }
6624
6625       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6626       {
6627         aClipPlane->SetCapping (toEnable);
6628         anArgIter += 1;
6629       }
6630       else
6631       {
6632         // just skip otherwise (old syntax)
6633       }
6634     }
6635     else if (aChangeArg == "-useobjectmaterial"
6636           || aChangeArg == "-useobjectmat"
6637           || aChangeArg == "-useobjmat"
6638           || aChangeArg == "-useobjmaterial")
6639     {
6640       if (aNbChangeArgs < 2)
6641       {
6642         std::cout << "Syntax error: need more arguments.\n";
6643         return 1;
6644       }
6645
6646       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6647       {
6648         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
6649         anArgIter += 1;
6650       }
6651     }
6652     else if (aChangeArg == "-useobjecttexture"
6653           || aChangeArg == "-useobjecttex"
6654           || aChangeArg == "-useobjtexture"
6655           || aChangeArg == "-useobjtex")
6656     {
6657       if (aNbChangeArgs < 2)
6658       {
6659         std::cout << "Syntax error: need more arguments.\n";
6660         return 1;
6661       }
6662
6663       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6664       {
6665         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
6666         anArgIter += 1;
6667       }
6668     }
6669     else if (aChangeArg == "-useobjectshader"
6670           || aChangeArg == "-useobjshader")
6671     {
6672       if (aNbChangeArgs < 2)
6673       {
6674         std::cout << "Syntax error: need more arguments.\n";
6675         return 1;
6676       }
6677
6678       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
6679       {
6680         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
6681         anArgIter += 1;
6682       }
6683     }
6684     else if (aChangeArg == "-color"
6685           || aChangeArg == "color")
6686     {
6687       Quantity_Color aColor;
6688       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
6689                                                            aChangeArgs + 1,
6690                                                            aColor);
6691       if (aNbParsed == 0)
6692       {
6693         std::cout << "Syntax error: need more arguments.\n";
6694         return 1;
6695       }
6696
6697       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
6698       aMat.SetAmbientColor (aColor);
6699       aMat.SetDiffuseColor (aColor);
6700       aClipPlane->SetCappingMaterial (aMat);
6701       anArgIter += aNbParsed;
6702     }
6703     else if (aChangeArg == "-texname"
6704           || aChangeArg == "texname")
6705     {
6706       if (aNbChangeArgs < 2)
6707       {
6708         std::cout << "Syntax error: need more arguments.\n";
6709         return 1;
6710       }
6711
6712       TCollection_AsciiString aTextureName (aChangeArgs[1]);
6713       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
6714       if (!aTexture->IsDone())
6715       {
6716         aClipPlane->SetCappingTexture (NULL);
6717       }
6718       else
6719       {
6720         aTexture->EnableModulate();
6721         aTexture->EnableRepeat();
6722         aClipPlane->SetCappingTexture (aTexture);
6723       }
6724       anArgIter += 1;
6725     }
6726     else if (aChangeArg == "-texscale"
6727           || aChangeArg == "texscale")
6728     {
6729       if (aClipPlane->CappingTexture().IsNull())
6730       {
6731         std::cout << "Error: no texture is set.\n";
6732         return 1;
6733       }
6734
6735       if (aNbChangeArgs < 3)
6736       {
6737         std::cout << "Syntax error: need more arguments.\n";
6738         return 1;
6739       }
6740
6741       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
6742       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
6743       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
6744       anArgIter += 2;
6745     }
6746     else if (aChangeArg == "-texorigin"
6747           || aChangeArg == "texorigin") // texture origin
6748     {
6749       if (aClipPlane->CappingTexture().IsNull())
6750       {
6751         std::cout << "Error: no texture is set.\n";
6752         return 1;
6753       }
6754
6755       if (aNbChangeArgs < 3)
6756       {
6757         std::cout << "Syntax error: need more arguments.\n";
6758         return 1;
6759       }
6760
6761       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
6762       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
6763
6764       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
6765       anArgIter += 2;
6766     }
6767     else if (aChangeArg == "-texrotate"
6768           || aChangeArg == "texrotate") // texture rotation
6769     {
6770       if (aClipPlane->CappingTexture().IsNull())
6771       {
6772         std::cout << "Error: no texture is set.\n";
6773         return 1;
6774       }
6775
6776       if (aNbChangeArgs < 2)
6777       {
6778         std::cout << "Syntax error: need more arguments.\n";
6779         return 1;
6780       }
6781
6782       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
6783       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
6784       anArgIter += 1;
6785     }
6786     else if (aChangeArg == "-hatch"
6787           || aChangeArg == "hatch")
6788     {
6789       if (aNbChangeArgs < 2)
6790       {
6791         std::cout << "Syntax error: need more arguments.\n";
6792         return 1;
6793       }
6794
6795       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
6796       aHatchStr.LowerCase();
6797       if (aHatchStr == "on")
6798       {
6799         aClipPlane->SetCappingHatchOn();
6800       }
6801       else if (aHatchStr == "off")
6802       {
6803         aClipPlane->SetCappingHatchOff();
6804       }
6805       else
6806       {
6807         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
6808       }
6809       anArgIter += 1;
6810     }
6811     else if (aChangeArg == "-delete"
6812           || aChangeArg == "delete")
6813     {
6814       removePlane (aRegPlanes, aPlaneName);
6815       return 0;
6816     }
6817     else if (aChangeArg == "-set"
6818           || aChangeArg == "-unset")
6819     {
6820       // set / unset plane command
6821       Standard_Boolean toSet = aChangeArg == "-set";
6822       Standard_Integer anIt = 1;
6823       for (; anIt < aNbChangeArgs; ++anIt)
6824       {
6825         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
6826         if (anEntityName.IsEmpty()
6827          || anEntityName.Value (1) == '-')
6828         {
6829           break;
6830         }
6831         else if (ViewerTest_myViews.IsBound1 (anEntityName))
6832         {
6833           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
6834           if (toSet)
6835           {
6836             aView->AddClipPlane (aClipPlane);
6837           }
6838           else
6839           {
6840             aView->RemoveClipPlane (aClipPlane);
6841           }
6842           continue;
6843         }
6844         else if (GetMapOfAIS().IsBound2 (anEntityName))
6845         {
6846           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
6847           if (toSet)
6848           {
6849             aIObj->AddClipPlane (aClipPlane);
6850           }
6851           else
6852           {
6853             aIObj->RemoveClipPlane (aClipPlane);
6854           }
6855         }
6856         else
6857         {
6858           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
6859           return 1;
6860         }
6861       }
6862
6863       if (anIt == 1)
6864       {
6865         // apply to active view
6866         if (toSet)
6867         {
6868           anActiveView->AddClipPlane (aClipPlane);
6869         }
6870         else
6871         {
6872           anActiveView->RemoveClipPlane (aClipPlane);
6873         }
6874       }
6875       else
6876       {
6877         anArgIter = anArgIter + anIt - 1;
6878       }
6879     }
6880     else
6881     {
6882       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
6883       return 1;
6884     }
6885   }
6886
6887   ViewerTest::RedrawAllViews();
6888   return 0;
6889 }
6890
6891 //===============================================================================================
6892 //function : VZRange
6893 //purpose  :
6894 //===============================================================================================
6895 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6896 {
6897   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
6898
6899   if (aCurrentView.IsNull())
6900   {
6901     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
6902     return 1;
6903   }
6904
6905   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
6906
6907   if (theArgsNb < 2)
6908   {
6909     theDi << "ZNear: " << aCamera->ZNear() << "\n";
6910     theDi << "ZFar: " << aCamera->ZFar() << "\n";
6911     return 0;
6912   }
6913
6914   if (theArgsNb == 3)
6915   {
6916     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
6917     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
6918
6919     if (aNewZNear >= aNewZFar)
6920     {
6921       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
6922       return 1;
6923     }
6924
6925     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
6926     {
6927       std::cout << theArgVec[0] << ": invalid arguments: ";
6928       std::cout << "znear, zfar should be positive for perspective camera.\n";
6929       return 1;
6930     }
6931
6932     aCamera->SetZRange (aNewZNear, aNewZFar);
6933   }
6934   else
6935   {
6936     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
6937     return 1;
6938   }
6939
6940   aCurrentView->Redraw();
6941
6942   return 0;
6943 }
6944
6945 //===============================================================================================
6946 //function : VAutoZFit
6947 //purpose  :
6948 //===============================================================================================
6949 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6950 {
6951   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
6952
6953   if (aCurrentView.IsNull())
6954   {
6955     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
6956     return 1;
6957   }
6958
6959   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
6960
6961   if (theArgsNb > 3)
6962   {
6963     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
6964     return 1;
6965   }
6966
6967   if (theArgsNb < 2)
6968   {
6969     theDi << "Auto z-fit mode: \n"
6970           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
6971           << "Scale: " << aScale << "\n";
6972     return 0;
6973   }
6974
6975   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
6976
6977   if (theArgsNb >= 3)
6978   {
6979     aScale = Draw::Atoi (theArgVec[2]);
6980   }
6981
6982   aCurrentView->SetAutoZFitMode (isOn, aScale);
6983   aCurrentView->AutoZFit();
6984   aCurrentView->Redraw();
6985
6986   return 0;
6987 }
6988
6989 //! Auxiliary function to print projection type
6990 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
6991 {
6992   switch (theProjType)
6993   {
6994     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
6995     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
6996     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
6997     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
6998     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
6999   }
7000   return "UNKNOWN";
7001 }
7002
7003 //===============================================================================================
7004 //function : VCamera
7005 //purpose  :
7006 //===============================================================================================
7007 static int VCamera (Draw_Interpretor& theDI,
7008                     Standard_Integer  theArgsNb,
7009                     const char**      theArgVec)
7010 {
7011   Handle(V3d_View) aView = ViewerTest::CurrentView();
7012   if (aView.IsNull())
7013   {
7014     std::cout << "Error: no active view.\n";
7015     return 1;
7016   }
7017
7018   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7019   if (theArgsNb < 2)
7020   {
7021     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7022     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7023     theDI << "Distance:   " << aCamera->Distance() << "\n";
7024     theDI << "IOD:        " << aCamera->IOD() << "\n";
7025     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7026     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7027     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7028     return 0;
7029   }
7030
7031   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7032   {
7033     Standard_CString        anArg = theArgVec[anArgIter];
7034     TCollection_AsciiString anArgCase (anArg);
7035     anArgCase.LowerCase();
7036     if (anArgCase == "-proj"
7037      || anArgCase == "-projection"
7038      || anArgCase == "-projtype"
7039      || anArgCase == "-projectiontype")
7040     {
7041       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7042     }
7043     else if (anArgCase == "-ortho"
7044           || anArgCase == "-orthographic")
7045     {
7046       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
7047     }
7048     else if (anArgCase == "-persp"
7049           || anArgCase == "-perspective"
7050           || anArgCase == "-perspmono"
7051           || anArgCase == "-perspectivemono"
7052           || anArgCase == "-mono")
7053     {
7054       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7055     }
7056     else if (anArgCase == "-stereo"
7057           || anArgCase == "-stereoscopic"
7058           || anArgCase == "-perspstereo"
7059           || anArgCase == "-perspectivestereo")
7060     {
7061       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7062     }
7063     else if (anArgCase == "-left"
7064           || anArgCase == "-lefteye"
7065           || anArgCase == "-monoleft"
7066           || anArgCase == "-monolefteye"
7067           || anArgCase == "-perpsleft"
7068           || anArgCase == "-perpslefteye")
7069     {
7070       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
7071     }
7072     else if (anArgCase == "-right"
7073           || anArgCase == "-righteye"
7074           || anArgCase == "-monoright"
7075           || anArgCase == "-monorighteye"
7076           || anArgCase == "-perpsright")
7077     {
7078       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
7079     }
7080     else if (anArgCase == "-dist"
7081           || anArgCase == "-distance")
7082     {
7083       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7084       if (anArgValue != NULL
7085       && *anArgValue != '-')
7086       {
7087         ++anArgIter;
7088         aCamera->SetDistance (Draw::Atof (anArgValue));
7089         continue;
7090       }
7091       theDI << aCamera->Distance() << " ";
7092     }
7093     else if (anArgCase == "-iod")
7094     {
7095       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7096       if (anArgValue != NULL
7097       && *anArgValue != '-')
7098       {
7099         ++anArgIter;
7100         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
7101         continue;
7102       }
7103       theDI << aCamera->IOD() << " ";
7104     }
7105     else if (anArgCase == "-iodtype")
7106     {
7107       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
7108       TCollection_AsciiString anValueCase (anArgValue);
7109       anValueCase.LowerCase();
7110       if (anValueCase == "abs"
7111        || anValueCase == "absolute")
7112       {
7113         ++anArgIter;
7114         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
7115         continue;
7116       }
7117       else if (anValueCase == "rel"
7118             || anValueCase == "relative")
7119       {
7120         ++anArgIter;
7121         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
7122         continue;
7123       }
7124       else if (*anArgValue != '-')
7125       {
7126         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
7127         return 1;
7128       }
7129       switch (aCamera->GetIODType())
7130       {
7131         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
7132         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
7133       }
7134     }
7135     else if (anArgCase == "-zfocus")
7136     {
7137       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7138       if (anArgValue != NULL
7139       && *anArgValue != '-')
7140       {
7141         ++anArgIter;
7142         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
7143         continue;
7144       }
7145       theDI << aCamera->ZFocus() << " ";
7146     }
7147     else if (anArgCase == "-zfocustype")
7148     {
7149       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
7150       TCollection_AsciiString anValueCase (anArgValue);
7151       anValueCase.LowerCase();
7152       if (anValueCase == "abs"
7153        || anValueCase == "absolute")
7154       {
7155         ++anArgIter;
7156         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
7157         continue;
7158       }
7159       else if (anValueCase == "rel"
7160             || anValueCase == "relative")
7161       {
7162         ++anArgIter;
7163         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
7164         continue;
7165       }
7166       else if (*anArgValue != '-')
7167       {
7168         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
7169         return 1;
7170       }
7171       switch (aCamera->ZFocusType())
7172       {
7173         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
7174         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
7175       }
7176     }
7177     else if (anArgCase == "-fov"
7178           || anArgCase == "-fovy")
7179     {
7180       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
7181       if (anArgValue != NULL
7182       && *anArgValue != '-')
7183       {
7184         ++anArgIter;
7185         aCamera->SetFOVy (Draw::Atof (anArgValue));
7186         continue;
7187       }
7188       theDI << aCamera->FOVy() << " ";
7189     }
7190     else
7191     {
7192       std::cout << "Error: unknown argument '" << anArg << "'\n";
7193       return 1;
7194     }
7195   }
7196
7197   aView->AutoZFit();
7198   aView->Redraw();
7199
7200   return 0;
7201 }
7202
7203 //! Parse stereo output mode
7204 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
7205                                          Graphic3d_StereoMode& theMode)
7206 {
7207   TCollection_AsciiString aFlag (theArg);
7208   aFlag.LowerCase();
7209   if (aFlag == "quadbuffer")
7210   {
7211     theMode = Graphic3d_StereoMode_QuadBuffer;
7212   }
7213   else if (aFlag == "anaglyph")
7214   {
7215     theMode = Graphic3d_StereoMode_Anaglyph;
7216   }
7217   else if (aFlag == "row"
7218         || aFlag == "rowinterlaced")
7219   {
7220     theMode = Graphic3d_StereoMode_RowInterlaced;
7221   }
7222   else if (aFlag == "col"
7223         || aFlag == "colinterlaced"
7224         || aFlag == "columninterlaced")
7225   {
7226     theMode = Graphic3d_StereoMode_ColumnInterlaced;
7227   }
7228   else if (aFlag == "chess"
7229         || aFlag == "chessboard")
7230   {
7231     theMode = Graphic3d_StereoMode_ChessBoard;
7232   }
7233   else if (aFlag == "sbs"
7234         || aFlag == "sidebyside")
7235   {
7236     theMode = Graphic3d_StereoMode_SideBySide;
7237   }
7238   else if (aFlag == "ou"
7239         || aFlag == "overunder")
7240   {
7241     theMode = Graphic3d_StereoMode_OverUnder;
7242   }
7243   else if (aFlag == "pageflip"
7244         || aFlag == "softpageflip")
7245   {
7246     theMode = Graphic3d_StereoMode_SoftPageFlip;
7247   }
7248   else
7249   {
7250     return Standard_False;
7251   }
7252   return Standard_True;
7253 }
7254
7255 //! Parse anaglyph filter
7256 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
7257                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
7258 {
7259   TCollection_AsciiString aFlag (theArg);
7260   aFlag.LowerCase();
7261   if (aFlag == "redcyansimple")
7262   {
7263     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
7264   }
7265   else if (aFlag == "redcyan"
7266         || aFlag == "redcyanoptimized")
7267   {
7268     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
7269   }
7270   else if (aFlag == "yellowbluesimple")
7271   {
7272     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
7273   }
7274   else if (aFlag == "yellowblue"
7275         || aFlag == "yellowblueoptimized")
7276   {
7277     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
7278   }
7279   else if (aFlag == "greenmagenta"
7280         || aFlag == "greenmagentasimple")
7281   {
7282     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
7283   }
7284   else
7285   {
7286     return Standard_False;
7287   }
7288   return Standard_True;
7289 }
7290
7291 //==============================================================================
7292 //function : VStereo
7293 //purpose  :
7294 //==============================================================================
7295
7296 static int VStereo (Draw_Interpretor& theDI,
7297                     Standard_Integer  theArgNb,
7298                     const char**      theArgVec)
7299 {
7300   Handle(V3d_View) aView = ViewerTest::CurrentView();
7301   if (theArgNb < 2)
7302   {
7303     if (aView.IsNull())
7304     {
7305       std::cout << "Error: no active viewer!\n";
7306       return 0;
7307     }
7308
7309     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
7310     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
7311     if (isActive)
7312     {
7313       TCollection_AsciiString aMode;
7314       switch (aView->RenderingParams().StereoMode)
7315       {
7316         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
7317         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
7318         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
7319         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
7320         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
7321         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
7322         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
7323         case Graphic3d_StereoMode_Anaglyph  :
7324           aMode = "anaglyph";
7325           switch (aView->RenderingParams().AnaglyphFilter)
7326           {
7327             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
7328             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
7329             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
7330             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
7331             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
7332             default: break;
7333           }
7334         default: break;
7335       }
7336       theDI << "Mode " << aMode << "\n";
7337     }
7338     return 0;
7339   }
7340
7341   Handle(Graphic3d_Camera) aCamera;
7342   Graphic3d_RenderingParams*   aParams   = NULL;
7343   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
7344   if (!aView.IsNull())
7345   {
7346     aParams   = &aView->ChangeRenderingParams();
7347     aMode     = aParams->StereoMode;
7348     aCamera   = aView->Camera();
7349   }
7350
7351   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7352   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7353   {
7354     Standard_CString        anArg = theArgVec[anArgIter];
7355     TCollection_AsciiString aFlag (anArg);
7356     aFlag.LowerCase();
7357     if (anUpdateTool.parseRedrawMode (aFlag))
7358     {
7359       continue;
7360     }
7361     else if (aFlag == "0"
7362           || aFlag == "off")
7363     {
7364       if (++anArgIter < theArgNb)
7365       {
7366         std::cout << "Error: wrong number of arguments!\n";
7367         return 1;
7368       }
7369
7370       if (!aCamera.IsNull()
7371        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
7372       {
7373         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
7374       }
7375       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
7376       return 0;
7377     }
7378     else if (aFlag == "1"
7379           || aFlag == "on")
7380     {
7381       if (++anArgIter < theArgNb)
7382       {
7383         std::cout << "Error: wrong number of arguments!\n";
7384         return 1;
7385       }
7386
7387       if (!aCamera.IsNull())
7388       {
7389         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7390       }
7391       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7392       return 0;
7393     }
7394     else if (aFlag == "-reverse"
7395           || aFlag == "-reversed"
7396           || aFlag == "-swap")
7397     {
7398       Standard_Boolean toEnable = Standard_True;
7399       if (++anArgIter < theArgNb
7400       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
7401       {
7402         --anArgIter;
7403       }
7404       aParams->ToReverseStereo = toEnable;
7405     }
7406     else if (aFlag == "-noreverse"
7407           || aFlag == "-noswap")
7408     {
7409       Standard_Boolean toDisable = Standard_True;
7410       if (++anArgIter < theArgNb
7411       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
7412       {
7413         --anArgIter;
7414       }
7415       aParams->ToReverseStereo = !toDisable;
7416     }
7417     else if (aFlag == "-mode"
7418           || aFlag == "-stereomode")
7419     {
7420       if (++anArgIter >= theArgNb
7421       || !parseStereoMode (theArgVec[anArgIter], aMode))
7422       {
7423         std::cout << "Error: syntax error at '" << anArg << "'\n";
7424         return 1;
7425       }
7426
7427       if (aMode == Graphic3d_StereoMode_QuadBuffer)
7428       {
7429         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7430       }
7431     }
7432     else if (aFlag == "-anaglyph"
7433           || aFlag == "-anaglyphfilter")
7434     {
7435       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
7436       if (++anArgIter >= theArgNb
7437       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
7438       {
7439         std::cout << "Error: syntax error at '" << anArg << "'\n";
7440         return 1;
7441       }
7442
7443       aMode = Graphic3d_StereoMode_Anaglyph;
7444       aParams->AnaglyphFilter = aFilter;
7445     }
7446     else if (parseStereoMode (anArg, aMode)) // short syntax
7447     {
7448       if (aMode == Graphic3d_StereoMode_QuadBuffer)
7449       {
7450         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
7451       }
7452     }
7453     else
7454     {
7455       std::cout << "Error: syntax error at '" << anArg << "'\n";
7456       return 1;
7457     }
7458   }
7459
7460   if (!aView.IsNull())
7461   {
7462     aParams->StereoMode = aMode;
7463     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
7464   }
7465   return 0;
7466 }
7467
7468 //===============================================================================================
7469 //function : VDefaults
7470 //purpose  :
7471 //===============================================================================================
7472 static int VDefaults (Draw_Interpretor& theDi,
7473                       Standard_Integer  theArgsNb,
7474                       const char**      theArgVec)
7475 {
7476   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7477   if (aCtx.IsNull())
7478   {
7479     std::cerr << "No active viewer!\n";
7480     return 1;
7481   }
7482
7483   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
7484   if (theArgsNb < 2)
7485   {
7486     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
7487     {
7488       theDi << "DeflType:           relative\n"
7489             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
7490     }
7491     else
7492     {
7493       theDi << "DeflType:           absolute\n"
7494             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
7495     }
7496     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
7497     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
7498     return 0;
7499   }
7500
7501   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7502   {
7503     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7504     anArg.UpperCase();
7505     if (anArg == "-ABSDEFL"
7506      || anArg == "-ABSOLUTEDEFLECTION"
7507      || anArg == "-DEFL"
7508      || anArg == "-DEFLECTION")
7509     {
7510       if (++anArgIter >= theArgsNb)
7511       {
7512         std::cout << "Error: wrong syntax at " << anArg << "\n";
7513         return 1;
7514       }
7515       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
7516       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
7517     }
7518     else if (anArg == "-RELDEFL"
7519           || anArg == "-RELATIVEDEFLECTION"
7520           || anArg == "-DEVCOEFF"
7521           || anArg == "-DEVIATIONCOEFF"
7522           || anArg == "-DEVIATIONCOEFFICIENT")
7523     {
7524       if (++anArgIter >= theArgsNb)
7525       {
7526         std::cout << "Error: wrong syntax at " << anArg << "\n";
7527         return 1;
7528       }
7529       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
7530       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
7531     }
7532     else if (anArg == "-ANGDEFL"
7533           || anArg == "-ANGULARDEFL"
7534           || anArg == "-ANGULARDEFLECTION")
7535     {
7536       if (++anArgIter >= theArgsNb)
7537       {
7538         std::cout << "Error: wrong syntax at " << anArg << "\n";
7539         return 1;
7540       }
7541       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
7542       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
7543     }
7544     else if (anArg == "-AUTOTR"
7545           || anArg == "-AUTOTRIANG"
7546           || anArg == "-AUTOTRIANGULATION")
7547     {
7548       if (++anArgIter >= theArgsNb)
7549       {
7550         std::cout << "Error: wrong syntax at " << anArg << "\n";
7551         return 1;
7552       }
7553       TCollection_AsciiString aValue (theArgVec[anArgIter]);
7554       aValue.LowerCase();
7555       if (aValue == "on"
7556        || aValue == "1")
7557       {
7558         aDefParams->SetAutoTriangulation (Standard_True);
7559       }
7560       else if (aValue == "off"
7561             || aValue == "0")
7562       {
7563         aDefParams->SetAutoTriangulation (Standard_False);
7564       }
7565     }
7566     else
7567     {
7568       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
7569     }
7570   }
7571
7572   return 0;
7573 }
7574
7575 //! Auxiliary method
7576 inline void addLight (const Handle(V3d_Light)& theLightNew,
7577                       const Standard_Boolean   theIsGlobal)
7578 {
7579   if (theLightNew.IsNull())
7580   {
7581     return;
7582   }
7583
7584   if (theIsGlobal)
7585   {
7586     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
7587   }
7588   else
7589   {
7590     ViewerTest::CurrentView()->SetLightOn (theLightNew);
7591   }
7592 }
7593
7594 //! Auxiliary method
7595 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
7596 {
7597   TCollection_AsciiString anArgNextCase (theArgNext);
7598   anArgNextCase.UpperCase();
7599   if (anArgNextCase.Length() > 5
7600    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
7601   {
7602     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
7603   }
7604   else
7605   {
7606     return theArgNext.IntegerValue();
7607   }
7608 }
7609
7610 //===============================================================================================
7611 //function : VLight
7612 //purpose  :
7613 //===============================================================================================
7614 static int VLight (Draw_Interpretor& theDi,
7615                    Standard_Integer  theArgsNb,
7616                    const char**      theArgVec)
7617 {
7618   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
7619   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
7620   if (aView.IsNull()
7621    || aViewer.IsNull())
7622   {
7623     std::cerr << "No active viewer!\n";
7624     return 1;
7625   }
7626
7627   Standard_Real        anXYZ[3];
7628   Quantity_Coefficient anAtten[2];
7629   if (theArgsNb < 2)
7630   {
7631     // print lights info
7632     Standard_Integer aLightId = 0;
7633     for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightId)
7634     {
7635       Handle(V3d_Light) aLight = aView->ActiveLight();
7636       const Quantity_Color aColor = aLight->Color();
7637       theDi << "Light" << aLightId << "\n";
7638       switch (aLight->Type())
7639       {
7640         case V3d_AMBIENT:
7641         {
7642           theDi << "  Type:       Ambient\n";
7643           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7644           break;
7645         }
7646         case V3d_DIRECTIONAL:
7647         {
7648           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
7649           theDi << "  Type:       Directional\n";
7650           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7651           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7652           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
7653           if (!aLightDir.IsNull())
7654           {
7655             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7656             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7657             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
7658             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7659           }
7660           break;
7661         }
7662         case V3d_POSITIONAL:
7663         {
7664           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
7665           theDi << "  Type:       Positional\n";
7666           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7667           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7668           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
7669           if (!aLightPos.IsNull())
7670           {
7671             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7672             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7673             aLightPos->Attenuation (anAtten[0], anAtten[1]);
7674             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
7675           }
7676           break;
7677         }
7678         case V3d_SPOT:
7679         {
7680           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
7681           theDi << "  Type:       Spot\n";
7682           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
7683           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
7684           if (!aLightSpot.IsNull())
7685           {
7686             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
7687             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7688             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
7689             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
7690             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
7691             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
7692             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
7693             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
7694           }
7695           break;
7696         }
7697         default:
7698         {
7699           theDi << "  Type:       UNKNOWN\n";
7700           break;
7701         }
7702       }
7703       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
7704     }
7705   }
7706
7707   Handle(V3d_Light) aLightNew;
7708   Handle(V3d_Light) aLightOld;
7709   Standard_Boolean  isGlobal = Standard_True;
7710   Standard_Boolean  toCreate = Standard_False;
7711   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7712   {
7713     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
7714     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
7715     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
7716     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
7717     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
7718
7719     TCollection_AsciiString aName, aValue;
7720     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
7721     TCollection_AsciiString anArgCase (anArg);
7722     anArgCase.UpperCase();
7723     if (anArgCase.IsEqual ("NEW")
7724      || anArgCase.IsEqual ("ADD")
7725      || anArgCase.IsEqual ("CREATE"))
7726     {
7727       toCreate = Standard_True;
7728     }
7729     else if (anArgCase.IsEqual ("GLOB")
7730           || anArgCase.IsEqual ("GLOBAL"))
7731     {
7732       isGlobal = Standard_True;
7733     }
7734     else if (anArgCase.IsEqual ("LOC")
7735           || anArgCase.IsEqual ("LOCAL"))
7736     {
7737       isGlobal = Standard_False;
7738     }
7739     else if (anArgCase.IsEqual ("DEF")
7740           || anArgCase.IsEqual ("DEFAULTS"))
7741     {
7742       toCreate = Standard_False;
7743       aViewer->SetDefaultLights();
7744     }
7745     else if (anArgCase.IsEqual ("CLR")
7746           || anArgCase.IsEqual ("CLEAR"))
7747     {
7748       toCreate = Standard_False;
7749       aView->InitActiveLights();
7750       while (aView->MoreActiveLights())
7751       {
7752         aViewer->DelLight (aView->ActiveLight());
7753         aView->InitActiveLights();
7754       }
7755     }
7756     else if (anArgCase.IsEqual ("AMB")
7757           || anArgCase.IsEqual ("AMBIENT")
7758           || anArgCase.IsEqual ("AMBLIGHT"))
7759     {
7760       addLight (aLightNew, isGlobal);
7761       if (!toCreate)
7762       {
7763         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7764         return 1;
7765       }
7766       toCreate  = Standard_False;
7767       aLightNew = new V3d_AmbientLight (aViewer);
7768     }
7769     else if (anArgCase.IsEqual ("DIRECTIONAL")
7770           || anArgCase.IsEqual ("DIRLIGHT"))
7771     {
7772       addLight (aLightNew, isGlobal);
7773       if (!toCreate)
7774       {
7775         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7776         return 1;
7777       }
7778       toCreate  = Standard_False;
7779       aLightNew = new V3d_DirectionalLight (aViewer);
7780     }
7781     else if (anArgCase.IsEqual ("SPOT")
7782           || anArgCase.IsEqual ("SPOTLIGHT"))
7783     {
7784       addLight (aLightNew, isGlobal);
7785       if (!toCreate)
7786       {
7787         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7788         return 1;
7789       }
7790       toCreate  = Standard_False;
7791       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
7792     }
7793     else if (anArgCase.IsEqual ("POSLIGHT")
7794           || anArgCase.IsEqual ("POSITIONAL"))
7795     {
7796       addLight (aLightNew, isGlobal);
7797       if (!toCreate)
7798       {
7799         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7800         return 1;
7801       }
7802       toCreate  = Standard_False;
7803       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
7804     }
7805     else if (anArgCase.IsEqual ("CHANGE"))
7806     {
7807       addLight (aLightNew, isGlobal);
7808       aLightNew.Nullify();
7809       if (++anArgIt >= theArgsNb)
7810       {
7811         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7812         return 1;
7813       }
7814
7815       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
7816       Standard_Integer aLightIt = 0;
7817       for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
7818       {
7819         if (aLightIt == aLightId)
7820         {
7821           aLightOld = aView->ActiveLight();
7822           break;
7823         }
7824       }
7825
7826       if (aLightOld.IsNull())
7827       {
7828         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
7829         return 1;
7830       }
7831     }
7832     else if (anArgCase.IsEqual ("DEL")
7833           || anArgCase.IsEqual ("DELETE"))
7834     {
7835       Handle(V3d_Light) aLightDel;
7836       if (++anArgIt >= theArgsNb)
7837       {
7838         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7839         return 1;
7840       }
7841
7842       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
7843       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
7844       Standard_Integer aLightIt = 0;
7845       for (aView->InitActiveLights(); aView->MoreActiveLights(); aView->NextActiveLights(), ++aLightIt)
7846       {
7847         aLightDel = aView->ActiveLight();
7848         if (aLightIt == aLightDelId)
7849         {
7850           break;
7851         }
7852       }
7853       if (!aLightDel.IsNull())
7854       {
7855         aViewer->DelLight (aLightDel);
7856       }
7857     }
7858     else if (anArgCase.IsEqual ("COLOR")
7859           || anArgCase.IsEqual ("COLOUR"))
7860     {
7861       if (++anArgIt >= theArgsNb)
7862       {
7863         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7864         return 1;
7865       }
7866
7867       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
7868       anArgNext.UpperCase();
7869       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
7870       if (!aLightCurr.IsNull())
7871       {
7872         aLightCurr->SetColor (aColor);
7873       }
7874     }
7875     else if (anArgCase.IsEqual ("POS")
7876           || anArgCase.IsEqual ("POSITION"))
7877     {
7878       if ((anArgIt + 3) >= theArgsNb)
7879       {
7880         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7881         return 1;
7882       }
7883
7884       anXYZ[0] = Atof (theArgVec[++anArgIt]);
7885       anXYZ[1] = Atof (theArgVec[++anArgIt]);
7886       anXYZ[2] = Atof (theArgVec[++anArgIt]);
7887       if (!aLightDir.IsNull())
7888       {
7889         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
7890       }
7891       else if (!aLightPos.IsNull())
7892       {
7893         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
7894       }
7895       else if (!aLightSpot.IsNull())
7896       {
7897         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
7898       }
7899       else
7900       {
7901         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7902         return 1;
7903       }
7904     }
7905     else if (anArgCase.IsEqual ("DIR")
7906           || anArgCase.IsEqual ("DIRECTION"))
7907     {
7908       if ((anArgIt + 3) >= theArgsNb)
7909       {
7910         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7911         return 1;
7912       }
7913
7914       anXYZ[0] = Atof (theArgVec[++anArgIt]);
7915       anXYZ[1] = Atof (theArgVec[++anArgIt]);
7916       anXYZ[2] = Atof (theArgVec[++anArgIt]);
7917       if (!aLightDir.IsNull())
7918       {
7919         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
7920       }
7921       else if (!aLightSpot.IsNull())
7922       {
7923         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
7924       }
7925       else
7926       {
7927         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7928         return 1;
7929       }
7930     }
7931     else if (anArgCase.IsEqual ("SM")
7932           || anArgCase.IsEqual ("SMOOTHNESS"))
7933     {
7934       if (++anArgIt >= theArgsNb)
7935       {
7936         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7937         return 1;
7938       }
7939
7940       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
7941
7942       if (fabs (aSmoothness) < Precision::Confusion())
7943       {
7944         aLightCurr->SetIntensity (1.f);
7945       }
7946       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
7947       {
7948         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
7949       }
7950       else
7951       {
7952         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
7953         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
7954       }
7955
7956       if (!aLightPos.IsNull())
7957       {
7958         aLightPos->SetSmoothRadius (aSmoothness);
7959       }
7960       else if (!aLightDir.IsNull())
7961       {
7962         aLightDir->SetSmoothAngle (aSmoothness);
7963       }
7964     }
7965     else if (anArgCase.IsEqual ("INT")
7966           || anArgCase.IsEqual ("INTENSITY"))
7967     {
7968       if (++anArgIt >= theArgsNb)
7969       {
7970         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7971         return 1;
7972       }
7973
7974       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
7975
7976       if (!aLightCurr.IsNull())
7977       {
7978         aLightCurr->SetIntensity (aIntensity);
7979       }
7980     }
7981     else if (anArgCase.IsEqual ("ANG")
7982           || anArgCase.IsEqual ("ANGLE"))
7983     {
7984       if (++anArgIt >= theArgsNb)
7985       {
7986         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
7987         return 1;
7988       }
7989
7990       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
7991
7992       if (!aLightSpot.IsNull())
7993       {
7994         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
7995       }
7996     }
7997     else if (anArgCase.IsEqual ("CONSTATTEN")
7998           || anArgCase.IsEqual ("CONSTATTENUATION"))
7999     {
8000       if (++anArgIt >= theArgsNb)
8001       {
8002         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8003         return 1;
8004       }
8005
8006       if (!aLightPos.IsNull())
8007       {
8008         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8009         anAtten[0] = Atof (theArgVec[anArgIt]);
8010         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8011       }
8012       else if (!aLightSpot.IsNull())
8013       {
8014         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8015         anAtten[0] = Atof (theArgVec[anArgIt]);
8016         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8017       }
8018       else
8019       {
8020         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8021         return 1;
8022       }
8023     }
8024     else if (anArgCase.IsEqual ("LINATTEN")
8025           || anArgCase.IsEqual ("LINEARATTEN")
8026           || anArgCase.IsEqual ("LINEARATTENUATION"))
8027     {
8028       if (++anArgIt >= theArgsNb)
8029       {
8030         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8031         return 1;
8032       }
8033
8034       if (!aLightPos.IsNull())
8035       {
8036         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8037         anAtten[1] = Atof (theArgVec[anArgIt]);
8038         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8039       }
8040       else if (!aLightSpot.IsNull())
8041       {
8042         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8043         anAtten[1] = Atof (theArgVec[anArgIt]);
8044         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8045       }
8046       else
8047       {
8048         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8049         return 1;
8050       }
8051     }
8052     else if (anArgCase.IsEqual ("EXP")
8053           || anArgCase.IsEqual ("EXPONENT")
8054           || anArgCase.IsEqual ("SPOTEXP")
8055           || anArgCase.IsEqual ("SPOTEXPONENT"))
8056     {
8057       if (++anArgIt >= theArgsNb)
8058       {
8059         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8060         return 1;
8061       }
8062
8063       if (!aLightSpot.IsNull())
8064       {
8065         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
8066       }
8067       else
8068       {
8069         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8070         return 1;
8071       }
8072     }
8073     else if (anArgCase.IsEqual ("HEAD")
8074           || anArgCase.IsEqual ("HEADLIGHT"))
8075     {
8076       if (++anArgIt >= theArgsNb)
8077       {
8078         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8079         return 1;
8080       }
8081
8082       if (aLightAmb.IsNull()
8083        && !aLightCurr.IsNull())
8084       {
8085         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
8086       }
8087       else
8088       {
8089         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8090         return 1;
8091       }
8092     }
8093     else
8094     {
8095       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
8096     }
8097   }
8098
8099   addLight (aLightNew, isGlobal);
8100   aViewer->UpdateLights();
8101
8102   return 0;
8103 }
8104
8105 //=======================================================================
8106 //function : VRenderParams
8107 //purpose  : Enables/disables rendering features
8108 //=======================================================================
8109
8110 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
8111                                        Standard_Integer  theArgNb,
8112                                        const char**      theArgVec)
8113 {
8114   Handle(V3d_View) aView = ViewerTest::CurrentView();
8115   if (aView.IsNull())
8116   {
8117     std::cerr << "Error: no active viewer!\n";
8118     return 1;
8119   }
8120
8121   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
8122   TCollection_AsciiString aCmdName (theArgVec[0]);
8123   aCmdName.LowerCase();
8124   if (aCmdName == "vraytrace")
8125   {
8126     if (theArgNb == 1)
8127     {
8128       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
8129       return 0;
8130     }
8131     else if (theArgNb == 2)
8132     {
8133       TCollection_AsciiString aValue (theArgVec[1]);
8134       aValue.LowerCase();
8135       if (aValue == "on"
8136        || aValue == "1")
8137       {
8138         aParams.Method = Graphic3d_RM_RAYTRACING;
8139         aView->Redraw();
8140         return 0;
8141       }
8142       else if (aValue == "off"
8143             || aValue == "0")
8144       {
8145         aParams.Method = Graphic3d_RM_RASTERIZATION;
8146         aView->Redraw();
8147         return 0;
8148       }
8149       else
8150       {
8151         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
8152         return 1;
8153       }
8154     }
8155     else
8156     {
8157       std::cout << "Error: wrong number of arguments\n";
8158       return 1;
8159     }
8160   }
8161
8162   if (theArgNb < 2)
8163   {
8164     theDI << "renderMode:  ";
8165     switch (aParams.Method)
8166     {
8167       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
8168       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
8169     }
8170     theDI << "\n";
8171     theDI << "msaa:         " <<  aParams.NbMsaaSamples << "\n";
8172     theDI << "rayDepth:     " <<  aParams.RaytracingDepth                             << "\n";
8173     theDI << "fsaa:         " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
8174     theDI << "shadows:      " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
8175     theDI << "reflections:  " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
8176     theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
8177     theDI << "GI:           " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
8178     theDI << "blocked RNG:  " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
8179     theDI << "shadingModel: ";
8180     switch (aView->ShadingModel())
8181     {
8182       case V3d_COLOR:   theDI << "color";   break;
8183       case V3d_FLAT:    theDI << "flat";    break;
8184       case V3d_GOURAUD: theDI << "gouraud"; break;
8185       case V3d_PHONG:   theDI << "phong";   break;
8186     }
8187     theDI << "\n";
8188     return 0;
8189   }
8190
8191   Standard_Boolean toPrint = Standard_False;
8192   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8193   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8194   {
8195     Standard_CString        anArg (theArgVec[anArgIter]);
8196     TCollection_AsciiString aFlag (anArg);
8197     aFlag.LowerCase();
8198     if (anUpdateTool.parseRedrawMode (aFlag))
8199     {
8200       continue;
8201     }
8202     else if (aFlag == "-echo"
8203           || aFlag == "-print")
8204     {
8205       toPrint = Standard_True;
8206       anUpdateTool.Invalidate();
8207     }
8208     else if (aFlag == "-mode"
8209           || aFlag == "-rendermode"
8210           || aFlag == "-render_mode")
8211     {
8212       if (toPrint)
8213       {
8214         switch (aParams.Method)
8215         {
8216           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
8217           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
8218         }
8219         continue;
8220       }
8221       else
8222       {
8223         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8224         return 1;
8225       }
8226     }
8227     else if (aFlag == "-ray"
8228           || aFlag == "-raytrace")
8229     {
8230       if (toPrint)
8231       {
8232         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
8233         continue;
8234       }
8235
8236       aParams.Method = Graphic3d_RM_RAYTRACING;
8237     }
8238     else if (aFlag == "-rast"
8239           || aFlag == "-raster"
8240           || aFlag == "-rasterization")
8241     {
8242       if (toPrint)
8243       {
8244         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
8245         continue;
8246       }
8247
8248       aParams.Method = Graphic3d_RM_RASTERIZATION;
8249     }
8250     else if (aFlag == "-msaa")
8251     {
8252       if (toPrint)
8253       {
8254         theDI << aParams.NbMsaaSamples << " ";
8255         continue;
8256       }
8257       else if (++anArgIter >= theArgNb)
8258       {
8259         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8260         return 1;
8261       }
8262
8263       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
8264       if (aNbSamples < 0)
8265       {
8266         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
8267         return 1;
8268       }
8269       else
8270       {
8271         aParams.NbMsaaSamples = aNbSamples;
8272       }
8273     }
8274     else if (aFlag == "-raydepth"
8275           || aFlag == "-ray_depth")
8276     {
8277       if (toPrint)
8278       {
8279         theDI << aParams.RaytracingDepth << " ";
8280         continue;
8281       }
8282       else if (++anArgIter >= theArgNb)
8283       {
8284         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8285         return 1;
8286       }
8287
8288       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
8289
8290       // We allow RaytracingDepth be more than 10 in case of GI enabled
8291       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
8292       {
8293         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
8294         return 1;
8295       }
8296       else
8297       {
8298         aParams.RaytracingDepth = aDepth;
8299       }
8300     }
8301     else if (aFlag == "-shad"
8302           || aFlag == "-shadows")
8303     {
8304       if (toPrint)
8305       {
8306         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
8307         continue;
8308       }
8309
8310       Standard_Boolean toEnable = Standard_True;
8311       if (++anArgIter < theArgNb
8312       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8313       {
8314         --anArgIter;
8315       }
8316       aParams.IsShadowEnabled = toEnable;
8317     }
8318     else if (aFlag == "-refl"
8319           || aFlag == "-reflections")
8320     {
8321       if (toPrint)
8322       {
8323         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
8324         continue;
8325       }
8326
8327       Standard_Boolean toEnable = Standard_True;
8328       if (++anArgIter < theArgNb
8329       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8330       {
8331         --anArgIter;
8332       }
8333       aParams.IsReflectionEnabled = toEnable;
8334     }
8335     else if (aFlag == "-fsaa")
8336     {
8337       if (toPrint)
8338       {
8339         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
8340         continue;
8341       }
8342
8343       Standard_Boolean toEnable = Standard_True;
8344       if (++anArgIter < theArgNb
8345       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8346       {
8347         --anArgIter;
8348       }
8349       aParams.IsAntialiasingEnabled = toEnable;
8350     }
8351     else if (aFlag == "-gleam")
8352     {
8353       if (toPrint)
8354       {
8355         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
8356         continue;
8357       }
8358
8359       Standard_Boolean toEnable = Standard_True;
8360       if (++anArgIter < theArgNb
8361       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8362       {
8363         --anArgIter;
8364       }
8365       aParams.IsTransparentShadowEnabled = toEnable;
8366     }
8367     else if (aFlag == "-gi")
8368     {
8369       if (toPrint)
8370       {
8371         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
8372         continue;
8373       }
8374
8375       Standard_Boolean toEnable = Standard_True;
8376       if (++anArgIter < theArgNb
8377       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8378       {
8379         --anArgIter;
8380       }
8381       aParams.IsGlobalIlluminationEnabled = toEnable;
8382       if (!toEnable)
8383       {
8384         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
8385       }
8386     }
8387     else if (aFlag == "-blockedrng"
8388           || aFlag == "-brng")
8389     {
8390       if (toPrint)
8391       {
8392         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
8393         continue;
8394       }
8395
8396       Standard_Boolean toEnable = Standard_True;
8397       if (++anArgIter < theArgNb
8398         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8399       {
8400         --anArgIter;
8401       }
8402       aParams.CoherentPathTracingMode = toEnable;
8403     }
8404     else if (aFlag == "-env")
8405     {
8406       if (toPrint)
8407       {
8408         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
8409         continue;
8410       }
8411
8412       Standard_Boolean toEnable = Standard_True;
8413       if (++anArgIter < theArgNb
8414         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8415       {
8416         --anArgIter;
8417       }
8418       aParams.UseEnvironmentMapBackground = toEnable;
8419     }
8420     else if (aFlag == "-shademodel"
8421           || aFlag == "-shadingmodel"
8422           || aFlag == "-shading")
8423     {
8424       if (toPrint)
8425       {
8426         switch (aView->ShadingModel())
8427         {
8428           case V3d_COLOR:   theDI << "color ";   break;
8429           case V3d_FLAT:    theDI << "flat ";    break;
8430           case V3d_GOURAUD: theDI << "gouraud "; break;
8431           case V3d_PHONG:   theDI << "phong ";   break;
8432         }
8433         continue;
8434       }
8435
8436       if (++anArgIter >= theArgNb)
8437       {
8438         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8439       }
8440
8441       TCollection_AsciiString aMode (theArgVec[anArgIter]);
8442       aMode.LowerCase();
8443       if (aMode == "color"
8444        || aMode == "none")
8445       {
8446         aView->SetShadingModel (V3d_COLOR);
8447       }
8448       else if (aMode == "flat"
8449             || aMode == "facet")
8450       {
8451         aView->SetShadingModel (V3d_FLAT);
8452       }
8453       else if (aMode == "gouraud"
8454             || aMode == "vertex"
8455             || aMode == "vert")
8456       {
8457         aView->SetShadingModel (V3d_GOURAUD);
8458       }
8459       else if (aMode == "phong"
8460             || aMode == "fragment"
8461             || aMode == "frag"
8462             || aMode == "pixel")
8463       {
8464         aView->SetShadingModel (V3d_PHONG);
8465       }
8466       else
8467       {
8468         std::cout << "Error: unknown shading model '" << aMode << "'\n";
8469         return 1;
8470       }
8471     }
8472     else if (aFlag == "-resolution")
8473     {
8474       if (++anArgIter >= theArgNb)
8475       {
8476         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
8477         return 1;
8478       }
8479
8480       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
8481       if (aResolution.IsIntegerValue())
8482       {
8483         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
8484       }
8485       else
8486       {
8487         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
8488         return 1;
8489       }
8490     }
8491     else
8492     {
8493       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
8494       return 1;
8495     }
8496   }
8497
8498   return 0;
8499 }
8500
8501 //=======================================================================
8502 //function : VProgressiveMode
8503 //purpose  :
8504 //=======================================================================
8505 #if defined(_WIN32)
8506 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
8507                                           Standard_Integer  /*theNbArgs*/,
8508                                           const char**      /*theArgs*/)
8509 {
8510   Handle(V3d_View) aView = ViewerTest::CurrentView();
8511   if (aView.IsNull())
8512   {
8513     std::cerr << "Error: no active viewer!\n";
8514     return 1;
8515   }
8516
8517   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
8518
8519   for (;;)
8520   {
8521     aView->Redraw();
8522
8523     Standard_Boolean toExit = Standard_False;
8524
8525     MSG aMsg;
8526     while (PeekMessage (&aMsg, NULL, 0, 0, PM_REMOVE))
8527     {
8528       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
8529       {
8530         toExit = Standard_True;
8531       }
8532
8533       TranslateMessage (&aMsg);
8534       DispatchMessage  (&aMsg);
8535     }
8536
8537     if (toExit)
8538     {
8539       break;
8540     }
8541   }
8542
8543   return 0;
8544 }
8545 #endif
8546
8547 //=======================================================================
8548 //function : VFrustumCulling
8549 //purpose  : enables/disables view volume's culling.
8550 //=======================================================================
8551 static int VFrustumCulling (Draw_Interpretor& theDI,
8552                             Standard_Integer  theArgNb,
8553                             const char**      theArgVec)
8554 {
8555   Handle(V3d_View) aView = ViewerTest::CurrentView();
8556   if (aView.IsNull())
8557   {
8558     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
8559     return 1;
8560   }
8561
8562   if (theArgNb < 2)
8563   {
8564     theDI << (aView->IsCullingEnabled() ? "on" : "off");
8565     return 0;
8566   }
8567   else if (theArgNb != 2)
8568   {
8569     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
8570     return 1;
8571   }
8572
8573   TCollection_AsciiString aModeStr (theArgVec[1]);
8574   aModeStr.LowerCase();
8575   Standard_Boolean toEnable = 0;
8576   if (aModeStr == "on")
8577   {
8578     toEnable = 1;
8579   }
8580   else if (aModeStr == "off")
8581   {
8582     toEnable = 0;
8583   }
8584   else
8585   {
8586     toEnable = Draw::Atoi (theArgVec[1]) != 0;
8587   }
8588
8589   aView->SetFrustumCulling (toEnable);
8590   aView->Redraw();
8591   return 0;
8592 }
8593
8594 //=======================================================================
8595 //function : VHighlightSelected
8596 //purpose  : 
8597 //=======================================================================
8598 static int VHighlightSelected (Draw_Interpretor& theDI,
8599                                Standard_Integer  theArgNb,
8600                                const char**      theArgVec)
8601 {
8602   if (ViewerTest::GetAISContext().IsNull())
8603   {
8604     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
8605     return 1;
8606   }
8607
8608   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8609
8610   if (theArgNb < 2)
8611   {
8612     theDI << (aContext->ToHilightSelected() ? "on" : "off");
8613     return 0;
8614   }
8615
8616   if (theArgNb != 2)
8617   {
8618     std::cout  << theArgVec[0] << " error : wrong number of parameters."
8619           << "Type 'help" << theArgVec[0] << "' for more information.";
8620     return 1;
8621   }
8622
8623   // Parse parameter
8624   TCollection_AsciiString aMode (theArgVec[1]);
8625   aMode.LowerCase();
8626   Standard_Boolean toEnable = Standard_False;
8627   if (aMode.IsEqual ("on"))
8628   {
8629     toEnable = Standard_True;
8630   }
8631   else if (aMode.IsEqual ("off"))
8632   {
8633     toEnable = Standard_False;
8634   }
8635   else
8636   {
8637     toEnable = Draw::Atoi (theArgVec[1]) != 0;
8638   }
8639
8640   if (toEnable != aContext->ToHilightSelected())
8641   {
8642     aContext->SetToHilightSelected (toEnable);
8643
8644     // Move cursor to null position and  back to process updating of detection
8645     // and highlighting of selected object immediatly.
8646     Standard_Integer aPixX = 0;
8647     Standard_Integer aPixY = 0;
8648     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
8649
8650     anEventManager->GetCurrentPosition (aPixX, aPixY);
8651     anEventManager->MoveTo (0, 0);
8652     anEventManager->MoveTo (aPixX, aPixY);
8653   }
8654
8655   return 0;
8656 }
8657
8658 //=======================================================================
8659 //function : VXRotate
8660 //purpose  :
8661 //=======================================================================
8662 static Standard_Integer VXRotate (Draw_Interpretor& di,
8663                                    Standard_Integer argc,
8664                                    const char ** argv)
8665 {
8666   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8667   if (aContext.IsNull())
8668   {
8669     di << argv[0] << "ERROR : use 'vinit' command before \n";
8670     return 1;
8671   }
8672   
8673   if (argc != 3)
8674   {
8675     di << "ERROR : Usage : " << argv[0] << " name angle\n";
8676     return 1;
8677   }
8678
8679   TCollection_AsciiString aName (argv[1]);
8680   Standard_Real anAngle = Draw::Atof (argv[2]);
8681
8682   // find object
8683   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
8684   Handle(AIS_InteractiveObject) anIObj;
8685   if (!aMap.IsBound2 (aName) )
8686   {
8687     di << "Use 'vdisplay' before\n";
8688     return 1;
8689   }
8690   else
8691   {
8692     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
8693
8694     gp_Trsf aTransform;
8695     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
8696     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
8697
8698     aContext->SetLocation (anIObj, aTransform);
8699     aContext->UpdateCurrentViewer();
8700   }
8701
8702   return 0;
8703 }
8704
8705 //===============================================================================================
8706 //class   : ViewerTest_AISManipulator
8707 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
8708 //===============================================================================================
8709 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
8710
8711 class ViewerTest_AISManipulator : public AIS_Manipulator
8712 {
8713 public:
8714
8715   ViewerTest_AISManipulator() : AIS_Manipulator()
8716   {
8717     GetMapOfAISManipulators().Add (this);
8718   }
8719
8720   virtual ~ViewerTest_AISManipulator()
8721   {
8722     GetMapOfAISManipulators().Remove (this);
8723   }
8724
8725   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
8726 };
8727
8728 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
8729 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
8730
8731 //===============================================================================================
8732 //function : VManipulator
8733 //purpose  :
8734 //===============================================================================================
8735 static int VManipulator (Draw_Interpretor& theDi,
8736                          Standard_Integer  theArgsNb,
8737                          const char**      theArgVec)
8738 {
8739   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8740   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8741   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
8742   if (aView.IsNull()
8743    || aViewer.IsNull())
8744   {
8745     std::cerr << "No active viewer!\n";
8746     return 1;
8747   }
8748
8749   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
8750   Standard_Integer anArgIter = 1;
8751   for (; anArgIter < theArgsNb; ++anArgIter)
8752   {
8753     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
8754   }
8755
8756   ViewerTest_CmdParser aCmd;
8757   aCmd.AddDescription ("Manages manipulator for interactive objects:");
8758   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
8759   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
8760   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
8761   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
8762   aCmd.AddOption ("detach",         "...       - detach manipulator");
8763
8764   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
8765   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
8766   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
8767
8768   aCmd.AddOption ("move",   "... x y z - move object");
8769   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
8770   aCmd.AddOption ("scale",  "... factor - scale object");
8771
8772   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
8773   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
8774   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
8775   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
8776   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
8777   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
8778   aCmd.AddOption ("size",              "... size - set size of manipulator");
8779   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
8780
8781   aCmd.Parse (theArgsNb, theArgVec);
8782
8783   if (aCmd.HasOption ("help"))
8784   {
8785     theDi.PrintHelp (theArgVec[0]);
8786     return 0;
8787   }
8788
8789   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
8790
8791   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
8792
8793   if (aName.IsEmpty())
8794   {
8795     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
8796     return 1;
8797   }
8798
8799   // ----------------------------------
8800   // detach existing manipulator object
8801   // ----------------------------------
8802
8803   if (aCmd.HasOption ("detach"))
8804   {
8805     if (!aMapAIS.IsBound2 (aName))
8806     {
8807       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
8808       return 1;
8809     }
8810
8811     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
8812     if (aManipulator.IsNull())
8813     {
8814       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
8815       return 1;
8816     }
8817
8818     aManipulator->Detach();
8819     aMapAIS.UnBind2 (aName);
8820     ViewerTest::GetAISContext()->Remove (aManipulator);
8821
8822     return 0;
8823   }
8824
8825   // -----------------------------------------------
8826   // find or create manipulator if it does not exist
8827   // -----------------------------------------------
8828
8829   Handle(AIS_Manipulator) aManipulator;
8830   if (!aMapAIS.IsBound2 (aName))
8831   {
8832     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
8833
8834     aManipulator = new ViewerTest_AISManipulator();
8835     aMapAIS.Bind (aManipulator, aName);
8836   }
8837   else
8838   {
8839     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
8840     if (aManipulator.IsNull())
8841     {
8842       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
8843       return 1;
8844     }
8845   }
8846
8847   // -----------------------------------------
8848   // change properties of manipulator instance
8849   // -----------------------------------------
8850
8851   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
8852   {
8853     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
8854   }
8855   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
8856   {
8857     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
8858   }
8859   if (aCmd.HasOption ("followRotation", 1, Standard_True))
8860   {
8861     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
8862   }
8863   if (aCmd.HasOption ("gap", 1, Standard_True))
8864   {
8865     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
8866   }
8867   if (aCmd.HasOption ("part", 3, Standard_True))
8868   {
8869     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
8870     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
8871     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
8872     if (aMode < 1 || aMode > 3)
8873     {
8874       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
8875       return 1;
8876     }
8877
8878     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
8879   }
8880   if (aCmd.HasOption ("pos", 3, Standard_True))
8881   {
8882     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
8883     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
8884     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
8885
8886     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
8887   }
8888   if (aCmd.HasOption ("size", 1, Standard_True))
8889   {
8890     aManipulator->SetSize (aCmd.ArgFloat ("size"));
8891   }
8892   if (aCmd.HasOption ("zoomable", 1, Standard_True))
8893   {
8894     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
8895
8896     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
8897     {
8898       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
8899       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
8900     }
8901   }
8902
8903   // ---------------------------------------------------
8904   // attach, detach or access manipulator from an object
8905   // ---------------------------------------------------
8906
8907   if (aCmd.HasOption ("attach"))
8908   {
8909     // Find an object and attach manipulator to it
8910     if (!aCmd.HasOption ("attach", 1, Standard_True))
8911     {
8912       return 1;
8913     }
8914
8915     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
8916     if (!aMapAIS.IsBound2 (anObjName))
8917     {
8918       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
8919       return 1;
8920     }
8921
8922     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
8923     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
8924     for (; anIt.More(); anIt.Next())
8925     {
8926       if (anIt.Value()->IsAttached()
8927        && anIt.Value()->Object() == anObject)
8928       {
8929         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
8930         return 1;
8931       }
8932     }
8933
8934     AIS_Manipulator::OptionsForAttach anOptions;
8935     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
8936     {
8937       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
8938     }
8939     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
8940     {
8941       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
8942     }
8943     if (aCmd.HasOption ("enableModes", 1, Standard_True))
8944     {
8945       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
8946     }
8947
8948     aManipulator->Attach (anObject, anOptions);
8949   }
8950
8951   // --------------------------------------
8952   // apply transformation using manipulator
8953   // --------------------------------------
8954
8955   if (aCmd.HasOption ("startTransform", 2, Standard_True))
8956   {
8957     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
8958   }
8959   if (aCmd.HasOption ("transform", 2, Standard_True))
8960   {
8961     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
8962   }
8963   if (aCmd.HasOption ("stopTransform"))
8964   {
8965     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
8966
8967     aManipulator->StopTransform (toApply);
8968   }
8969
8970   gp_Trsf aT;
8971   if (aCmd.HasOption ("move", 3, Standard_True))
8972   {
8973     aT.SetTranslationPart (aCmd.ArgVec ("move"));
8974   }
8975   if (aCmd.HasOption ("rotate", 7, Standard_True))
8976   {
8977     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
8978   }
8979   if (aCmd.HasOption ("scale", 1))
8980   {
8981     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
8982   }
8983
8984   if (aT.Form() != gp_Identity)
8985   {
8986     aManipulator->Transform (aT);
8987   }
8988
8989   ViewerTest::GetAISContext()->Redisplay (aManipulator);
8990
8991   return 0;
8992 }
8993
8994 //=======================================================================
8995 //function : ViewerCommands
8996 //purpose  :
8997 //=======================================================================
8998
8999 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
9000 {
9001
9002   const char *group = "ZeViewer";
9003   theCommands.Add("vinit",
9004 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
9005     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
9006 #else
9007     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
9008 #endif
9009     " - Creates new View window with specified name view_name.\n"
9010     "By default the new view is created in the viewer and in"
9011     " graphic driver shared with active view.\n"
9012     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
9013     "If driverName isn't specified the driver will be shared with active view.\n"
9014     "If viewerName isn't specified the viewer will be shared with active view.\n"
9015 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
9016     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
9017     "is used in creation of graphic driver\n"
9018 #endif
9019     " - l, t: pixel position of left top corner of the window\n"
9020     " - w,h: width and heigth of window respectively.\n"
9021     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
9022     __FILE__,VInit,group);
9023   theCommands.Add("vclose" ,
9024     "[view_id [keep_context=0|1]]\n"
9025     "or vclose ALL - to remove all created views\n"
9026     " - removes view(viewer window) defined by its view_id.\n"
9027     " - keep_context: by default 0; if 1 and the last view is deleted"
9028     " the current context is not removed.",
9029     __FILE__,VClose,group);
9030   theCommands.Add("vactivate" ,
9031     "view_id"
9032     " - activates view(viewer window) defined by its view_id",
9033     __FILE__,VActivate,group);
9034   theCommands.Add("vviewlist",
9035     "vviewlist [format={tree, long}]"
9036     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
9037     " - format: format of result output, if tree the output is a tree view;"
9038     "otherwise it's a list of full view names. By default format = tree",
9039     __FILE__,VViewList,group);
9040   theCommands.Add("vhelp" ,
9041     "vhelp            : display help on the viewer commands",
9042     __FILE__,VHelp,group);
9043   theCommands.Add("vtop" ,
9044     "vtop or <T>      : Top view. Orientation +X+Y" ,
9045     __FILE__,VTop,group);
9046   theCommands.Add("vbottom" ,
9047     "vbottom          : Bottom view. Orientation +X-Y" ,
9048     __FILE__,VBottom,group);
9049   theCommands.Add("vleft" ,
9050     "vleft            : Left view. Orientation -Y+Z" ,
9051     __FILE__,VLeft,group);
9052   theCommands.Add("vright" ,
9053     "vright           : Right view. Orientation +Y+Z" ,
9054     __FILE__,VRight,group);
9055   theCommands.Add("vaxo" ,
9056     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
9057     __FILE__,VAxo,group);
9058   theCommands.Add("vfront" ,
9059     "vfront           : Front view. Orientation +X+Z" ,
9060     __FILE__,VFront,group);
9061   theCommands.Add("vback" ,
9062     "vback            : Back view. Orientation -X+Z" ,
9063     __FILE__,VBack,group);
9064   theCommands.Add("vpick" ,
9065     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
9066     VPick,group);
9067   theCommands.Add("vfit"    ,
9068     "vfit or <F> [-selected]"
9069     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
9070     __FILE__,VFit,group);
9071   theCommands.Add ("vfitarea",
9072     "vfitarea x1 y1 x2 y2"
9073     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
9074     "\n\t\t: Fit view to show area located between two points"
9075     "\n\t\t: given in world 2D or 3D corrdinates.",
9076     __FILE__, VFitArea, group);
9077   theCommands.Add ("vzfit", "vzfit [scale]\n"
9078     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
9079     "   \"scale\" - specifies factor to scale computed z range.\n",
9080     __FILE__, VZFit, group);
9081   theCommands.Add("vrepaint",
9082     "vrepaint        : vrepaint, force redraw",
9083     __FILE__,VRepaint,group);
9084   theCommands.Add("vclear",
9085     "vclear          : vclear"
9086     "\n\t\t: remove all the object from the viewer",
9087     __FILE__,VClear,group);
9088   theCommands.Add("vsetbg",
9089     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
9090     __FILE__,VSetBg,group);
9091   theCommands.Add("vsetbgmode",
9092     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
9093     __FILE__,VSetBgMode,group);
9094   theCommands.Add("vsetgradientbg",
9095     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
9096     __FILE__,VSetGradientBg,group);
9097   theCommands.Add("vsetgrbgmode",
9098     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
9099     __FILE__,VSetGradientBgMode,group);
9100   theCommands.Add("vsetcolorbg",
9101     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
9102     __FILE__,VSetColorBg,group);
9103   theCommands.Add("vsetdefaultbg",
9104     "vsetdefaultbg r g b\n"
9105     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
9106     "\n\t\t: Set default viewer background fill color (flat/gradient).",
9107     __FILE__,VSetDefaultBg,group);
9108   theCommands.Add("vscale",
9109     "vscale          : vscale X Y Z",
9110     __FILE__,VScale,group);
9111   theCommands.Add("vzbufftrihedron",
9112             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
9113     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
9114     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
9115     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
9116     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
9117     "\n\t\t: Displays a trihedron",
9118     __FILE__,VZBuffTrihedron,group);
9119   theCommands.Add("vrotate",
9120     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
9121     "\n                : Option -mouseStart starts rotation according to the mouse position"
9122     "\n                : Option -mouseMove continues rotation with angle computed"
9123     "\n                : from last and new mouse position."
9124     "\n                : vrotate AX AY AZ [X Y Z]",
9125     __FILE__,VRotate,group);
9126   theCommands.Add("vzoom",
9127     "vzoom           : vzoom coef",
9128     __FILE__,VZoom,group);
9129   theCommands.Add("vpan",
9130     "vpan            : vpan dx dy",
9131     __FILE__,VPan,group);
9132   theCommands.Add("vexport",
9133     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
9134     " : exports the view to a vector file of a given format"
9135     " : notice that EMF format requires patched gl2ps",
9136     __FILE__,VExport,group);
9137   theCommands.Add("vcolorscale",
9138     "vcolorscale     : vcolorscale name [-range RangeMin = 0 RangeMax = 100 Intervals = 10 -font HeightFont = 16  -textpos "
9139     "Position = left -xy X = 0 Y = 0] [-noupdate|-update]: draw color scale\n"
9140     "-demo/-demoversion draw a demoversion of color scale.\n"
9141     "-show/display display color scale.\n"
9142     "-hide/erase erase color scale.\n"
9143     "Please note that -show/-hide option must be the first argument!\n"
9144     "-color Index R G B: set color for indexed interval\n"
9145     "-color Index ColorName: set color for indexed interval\n"
9146     "-colors R G B R G B ...: set colors for all intervals\n"
9147     "-colors ColorName1 ColorName2 ...: set colors for all intervals\n"
9148     "-colors supports both color names and rgb values in one call\n"
9149     "-label Index Text: set label for indexed interval\n"
9150     "-labels Text Text Text ...: set labels for all intervals\n"
9151     "-title Title [Position]: set the title for color scale with certain position. Default position = center;\n"
9152     "Available text positions: left, right, center, none;\n",
9153     __FILE__,VColorScale,group);
9154   theCommands.Add("vgraduatedtrihedron",
9155     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
9156     "\t[-namefont Name] [-valuesfont Name]\n"
9157     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
9158     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
9159     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
9160     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
9161     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
9162     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
9163     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
9164     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
9165     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
9166     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
9167     " - Displays or erases graduated trihedron"
9168     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
9169     " - namefont - font of axes names. Default: Arial\n"
9170     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
9171     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
9172     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
9173     " - valuesfont - font of axes values. Default: Arial\n"
9174     " - xcolor, ycolor, zcolor - color of axis and values\n"
9175     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
9176     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
9177     __FILE__,VGraduatedTrihedron,group);
9178   theCommands.Add("vtile" ,
9179             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
9180     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
9181     "\n\t\t:  -totalSize the size of virtual bigger viewport"
9182     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
9183     "\n\t\t:  -lowerLeft tile offset as lower left corner"
9184     "\n\t\t:  -upperLeft tile offset as upper left corner",
9185     __FILE__, VTile, group);
9186   theCommands.Add("vzlayer",
9187     "vzlayer add/del/get/settings/enable/disable [id]\n"
9188     " add - add new z layer to viewer and print its id\n"
9189     " del - del z layer by its id\n"
9190     " get - print sequence of z layers in increasing order of their overlay level\n"
9191     " settings - print status of z layer settings\n"
9192     " enable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    enables given setting for the z layer\n"
9193     " enable (p[ositive]offset/n[egative]offset) \n    enables given setting for the z layer\n"
9194     " enable textureenv \n    enables environment texture mapping\n"
9195     " disable ([depth]test/[depth]write/[depth]clear/[depth]offset) \n    disables given setting for the z layer\n"
9196     " disable textureenv \n    disables environment texture mapping\n"
9197     "\nWhere id is the layer identificator\n"
9198     "\nExamples:\n"
9199     "   vzlayer add\n"
9200     "   vzlayer enable poffset 1\n"
9201     "   vzlayer disable depthtest 1\n"
9202     "   vzlayer del 1\n",
9203     __FILE__,VZLayer,group);
9204   theCommands.Add("vlayerline",
9205     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
9206     __FILE__,VLayerLine,group);
9207   theCommands.Add ("vgrid",
9208     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
9209     " : Mode - rectangular or circular"
9210     " : Type - lines or points",
9211     __FILE__, VGrid, group);
9212   theCommands.Add ("vpriviledgedplane",
9213     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
9214     "\n\t\t:   Ox, Oy, Oz - plane origin"
9215     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
9216     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
9217     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
9218     __FILE__, VPriviledgedPlane, group);
9219   theCommands.Add ("vconvert",
9220     "vconvert v [Mode={window|view}]"
9221     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
9222     "\n\t\t: vconvert x y z [Mode={window|grid}]"
9223     "\n\t\t:   window - convert to window coordinates, pixels"
9224     "\n\t\t:   view   - convert to view projection plane"
9225     "\n\t\t:   grid   - convert to model coordinates, given on grid"
9226     "\n\t\t:   ray    - convert projection ray to model coordiantes"
9227     "\n\t\t: - vconvert v window : convert view to window;"
9228     "\n\t\t: - vconvert v view   : convert window to view;"
9229     "\n\t\t: - vconvert x y window : convert view to window;"
9230     "\n\t\t: - vconvert x y view : convert window to view;"
9231     "\n\t\t: - vconvert x y : convert window to model;"
9232     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
9233     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
9234     "\n\t\t: - vconvert x y z window : convert model to window;"
9235     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
9236     "\n\t\t: Converts the given coordinates to window/view/model space.",
9237     __FILE__, VConvert, group);
9238   theCommands.Add ("vfps",
9239     "vfps [framesNb=100] : estimate average frame rate for active view",
9240     __FILE__, VFps, group);
9241   theCommands.Add ("vgldebug",
9242             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
9243     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
9244     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
9245     "\n\t\t: Debug context can be requested only on Windows"
9246     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
9247     "\n\t\t:  -sync     - request synchronized debug GL context"
9248     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
9249     "\n\t\t:              which are suppressed by default,"
9250     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
9251     "\n\t\t:              which are suppressed by default",
9252     __FILE__, VGlDebug, group);
9253   theCommands.Add ("vvbo",
9254     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
9255     __FILE__, VVbo, group);
9256   theCommands.Add ("vstereo",
9257             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
9258     "\n\t\t:         [-anaglyph Filter]"
9259     "\n\t\t: Control stereo output mode. Available modes for -mode:"
9260     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
9261     "\n\t\t:                     requires driver support."
9262     "\n\t\t:                     Should be called BEFORE vinit!"
9263     "\n\t\t:  anaglyph         - Anaglyph glasses"
9264     "\n\t\t:  rowInterlaced    - row-interlaced display"
9265     "\n\t\t:  columnInterlaced - column-interlaced display"
9266     "\n\t\t:  chessBoard       - chess-board output"
9267     "\n\t\t:  sideBySide       - horizontal pair"
9268     "\n\t\t:  overUnder        - vertical   pair"
9269     "\n\t\t: Available Anaglyph filters for -anaglyph:"
9270     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
9271     "\n\t\t:  greenMagentaSimple",
9272     __FILE__, VStereo, group);
9273   theCommands.Add ("vcaps",
9274             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
9275     "\n\t\t:       [-compatibleProfile {0|1}]"
9276     "\n\t\t:       [-vsync {0|1}]"
9277     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
9278     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
9279     "\n\t\t: Modify particular graphic driver options:"
9280     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
9281     "\n\t\t:             built-in GLSL programs"
9282     "\n\t\t:            (requires compatible profile)"
9283     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
9284     "\n\t\t:             arrays to GPU memory)"
9285     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
9286     "\n\t\t:  vsync    - switch VSync on or off"
9287     "\n\t\t: Context creation options:"
9288     "\n\t\t:  softMode          - software OpenGL implementation"
9289     "\n\t\t:  compatibleProfile - backward-compatible profile"
9290     "\n\t\t:  quadbuffer        - QuadBuffer"
9291     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
9292     "\n\t\t: rendering paths producing the same visual result when"
9293     "\n\t\t: possible."
9294     "\n\t\t: Command is intended for testing old hardware compatibility.",
9295     __FILE__, VCaps, group);
9296   theCommands.Add ("vmemgpu",
9297     "vmemgpu [f]: print system-dependent GPU memory information if available;"
9298     " with f option returns free memory in bytes",
9299     __FILE__, VMemGpu, group);
9300   theCommands.Add ("vreadpixel",
9301     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
9302     " : Read pixel value for active view",
9303     __FILE__, VReadPixel, group);
9304   theCommands.Add("diffimage",
9305     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
9306     __FILE__, VDiffImage, group);
9307   theCommands.Add ("vselect",
9308     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
9309     "- emulates different types of selection:\n"
9310     "- 1) single click selection\n"
9311     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
9312     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
9313     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
9314     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
9315     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
9316     " (partial inclusion - overlap - is not allowed by default)\n"
9317     "- 5) any of these selections with shift button pressed",
9318     __FILE__, VSelect, group);
9319   theCommands.Add ("vmoveto",
9320     "vmoveto x y"
9321     "- emulates cursor movement to pixel postion (x,y)",
9322     __FILE__, VMoveTo, group);
9323   theCommands.Add ("vviewparams", "vviewparams usage:\n"
9324     "- vviewparams\n"
9325     "- vviewparams [-scale [s]] [-eye [x y z]] [-at [x y z]] [-up [x y z]]\n"
9326     "              [-proj [x y z]] [-center x y] [-size sx]\n"
9327     "-   Gets or sets current view parameters.\n"
9328     "-   If called without arguments, all view parameters are printed.\n"
9329     "-   The options are:\n"
9330     "      -scale [s]    : prints or sets viewport relative scale.\n"
9331     "      -eye [x y z]  : prints or sets eye location.\n"
9332     "      -at [x y z]   : prints or sets center of look.\n"
9333     "      -up [x y z]   : prints or sets direction of up vector.\n"
9334     "      -proj [x y z] : prints or sets direction of look.\n"
9335     "      -center x y   : sets location of center of the screen in pixels.\n"
9336     "      -size [sx]    : prints viewport projection width and height sizes\n"
9337     "                    : or changes the size of its maximum dimension.\n",
9338     __FILE__, VViewParams, group);
9339   theCommands.Add("vchangeselected",
9340     "vchangeselected shape"
9341     "- adds to shape to selection or remove one from it",
9342                 __FILE__, VChangeSelected, group);
9343   theCommands.Add ("vnbselected",
9344     "vnbselected"
9345     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
9346   theCommands.Add ("vcamera",
9347               "vcamera [-ortho] [-projtype]"
9348       "\n\t\t:         [-persp]"
9349       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
9350       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
9351       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
9352       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
9353       "\n\t\t: Manage camera parameters."
9354       "\n\t\t: Prints current value when option called without argument."
9355       "\n\t\t: Orthographic camera:"
9356       "\n\t\t:   -ortho      activate orthographic projection"
9357       "\n\t\t: Perspective camera:"
9358       "\n\t\t:   -persp      activate perspective  projection (mono)"
9359       "\n\t\t:   -fovy       field of view in y axis, in degrees"
9360       "\n\t\t:   -distance   distance of eye from camera center"
9361       "\n\t\t: Stereoscopic camera:"
9362       "\n\t\t:   -stereo     perspective  projection (stereo)"
9363       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
9364       "\n\t\t:   -rightEye   perspective  projection (right eye)"
9365       "\n\t\t:   -iod        intraocular distance value"
9366       "\n\t\t:   -iodType    distance type, absolute or relative"
9367       "\n\t\t:   -zfocus     stereographic focus value"
9368       "\n\t\t:   -zfocusType focus type, absolute or relative",
9369     __FILE__, VCamera, group);
9370   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
9371     "- vautozfit [on={1|0}] [scale]\n"
9372     "    Prints or changes parameters of automatic z-fit mode:\n"
9373     "   \"on\" - turns automatic z-fit on or off\n"
9374     "   \"scale\" - specifies factor to scale computed z range.\n",
9375     __FILE__, VAutoZFit, group);
9376   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
9377     "   vzrange                - without parameters shows current values\n"
9378     "   vzrange [znear] [zfar] - applies provided values to view",
9379     __FILE__,VZRange, group);
9380   theCommands.Add ("vpurgedisplay",
9381     "vpurgedisplay"
9382     "- removes structures which don't belong to objects displayed in neutral point",
9383     __FILE__, VPurgeDisplay, group);
9384   theCommands.Add("vsetviewsize",
9385     "vsetviewsize size",
9386     __FILE__,VSetViewSize,group);
9387   theCommands.Add("vmoveview",
9388     "vmoveview Dx Dy Dz [Start = 1|0]",
9389     __FILE__,VMoveView,group);
9390   theCommands.Add("vtranslateview",
9391     "vtranslateview Dx Dy Dz [Start = 1|0)]",
9392     __FILE__,VTranslateView,group);
9393   theCommands.Add("vturnview",
9394     "vturnview Ax Ay Az [Start = 1|0]",
9395     __FILE__,VTurnView,group);
9396   theCommands.Add("vtextureenv",
9397     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
9398     "or user-defined file and optionally applying texture mapping parameters\n"
9399     "                  Usage:\n"
9400     "                  vtextureenv off - disables environment mapping\n"
9401     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
9402     "                              std_texture = (0..7)\n"
9403     "                              rep         = {clamp|repeat}\n"
9404     "                              mod         = {decal|modulate}\n"
9405     "                              flt         = {nearest|bilinear|trilinear}\n"
9406     "                              ss, st      - scale factors for s and t texture coordinates\n"
9407     "                              ts, tt      - translation for s and t texture coordinates\n"
9408     "                              rot         - texture rotation angle in degrees",
9409     __FILE__, VTextureEnv, group);
9410   theCommands.Add("vhlr" ,
9411     "is_enabled={on|off} [show_hidden={1|0}]"
9412     " - Hidden line removal algorithm:"
9413     " - is_enabled: if is on HLR algorithm is applied\n"
9414     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
9415     __FILE__,VHLR,group);
9416   theCommands.Add("vhlrtype" ,
9417     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
9418     " - Changes the type of HLR algorithm using for shapes."
9419     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
9420     "   if equals to polyalgo, polygonal HLR algorithm is applied."
9421     "If shapes are not given HLR algoithm of given type is applied"
9422     " to all shapes in the view\n",
9423     __FILE__,VHLRType,group);
9424   theCommands.Add("vclipplane",
9425               "vclipplane planeName [{0|1}]"
9426       "\n\t\t:   [-equation A B C D]"
9427       "\n\t\t:   [-set|-unset [objects|views]]"
9428       "\n\t\t:   [-maxPlanes]"
9429       "\n\t\t:   [-capping {0|1}]"
9430       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
9431       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
9432       "\n\t\t:       [-texRotate Angle]"
9433       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
9434       "\n\t\t:       [-useObjShader {0|1}]"
9435       "\n\t\t: Clipping planes management:"
9436       "\n\t\t:   -maxPlanes   print plane limit for view"
9437       "\n\t\t:   -delete      delete plane with given name"
9438       "\n\t\t:   {off|on|0|1} turn clipping on/off"
9439       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
9440       "\n\t\t:                applied to active View when list is omitted"
9441       "\n\t\t:   -equation A B C D change plane equation"
9442       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
9443       "\n\t\t: Capping options:"
9444       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
9445       "\n\t\t:   -color R G B          set capping color"
9446       "\n\t\t:   -texName Texture      set capping texture"
9447       "\n\t\t:   -texScale SX SY       set capping tex scale"
9448       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
9449       "\n\t\t:   -texRotate Angle      set capping tex rotation"
9450       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
9451       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
9452       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
9453       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
9454       __FILE__, VClipPlane, group);
9455   theCommands.Add("vdefaults",
9456                "vdefaults [-absDefl value]"
9457        "\n\t\t:           [-devCoeff value]"
9458        "\n\t\t:           [-angDefl value]"
9459        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
9460     , __FILE__, VDefaults, group);
9461   theCommands.Add("vlight",
9462     "tool to manage light sources, without arguments shows list of lights."
9463     "\n    Main commands: "
9464     "\n      'clear' to clear lights"
9465     "\n      '{def}aults' to load deafault lights"
9466     "\n      'add' (or 'new') <type> to add any light source"
9467     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
9468     "\n      'change' <lightId> to edit light source with specified lightId"
9469     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
9470     "\n        {pos}ition X Y Z"
9471     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
9472     "\n        color colorName"
9473     "\n        {head}light 0|1"
9474     "\n        {sm}oothness value"
9475     "\n        {int}ensity value"
9476     "\n        {constAtten}uation value"
9477     "\n        {linearAtten}uation value"
9478     "\n        angle angleDeg"
9479     "\n        {spotexp}onent value"
9480     "\n        local|global"
9481     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
9482     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
9483     __FILE__, VLight, group);
9484   theCommands.Add("vraytrace",
9485             "vraytrace [0|1]"
9486     "\n\t\t: Turns on/off ray-tracing renderer."
9487     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
9488     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
9489     __FILE__, VRenderParams, group);
9490   theCommands.Add("vrenderparams",
9491     "\n    Manages rendering parameters: "
9492     "\n      '-raster'               Disables GPU ray-tracing"
9493     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
9494     "\n      '-rayTrace'             Enables  GPU ray-tracing"
9495     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
9496     "\n      '-shadows      on|off'  Enables/disables shadows rendering"
9497     "\n      '-reflections  on|off'  Enables/disables specular reflections"
9498     "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
9499     "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
9500     "\n      '-gi           on|off'  Enables/disables global illumination effects"
9501     "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
9502     "\n      '-env          on|off'  Enables/disables environment map background"
9503     "\n      '-shadingModel model'   Controls shading model from enumeration"
9504     "\n                              color, flat, gouraud, phong"
9505     "\n      '-resolution   value'   Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
9506     "\n    Unlike vcaps, these parameters dramatically change visual properties."
9507     "\n    Command is intended to control presentation quality depending on"
9508     "\n    hardware capabilities and performance.",
9509     __FILE__, VRenderParams, group);
9510   theCommands.Add("vfrustumculling",
9511     "vfrustumculling [toEnable]: enables/disables objects clipping",
9512     __FILE__,VFrustumCulling,group);
9513   theCommands.Add("vhighlightselected",
9514     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
9515     "Without arguments it shows if highlighting of selected objects is enabled now.",
9516     __FILE__,VHighlightSelected,group);
9517   theCommands.Add ("vplace",
9518             "vplace dx dy"
9519     "\n\t\t: Places the point (in pixels) at the center of the window",
9520     __FILE__, VPlace, group);
9521   theCommands.Add("vxrotate",
9522     "vxrotate",
9523     __FILE__,VXRotate,group);
9524
9525     theCommands.Add("vmanipulator",
9526       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
9527       "\n    tool to create and manage AIS manipulators."
9528       "\n    Options: "
9529       "\n      '-attach AISObject'                 attach manipulator to AISObject"
9530       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
9531       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
9532       "\n      '-enableModes    {0|1}'             enable modes when attaching"
9533       "\n      '-detach'                           detach manipulator"
9534       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
9535       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
9536       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
9537       "\n      '-move x y z'                     - move attached object"
9538       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
9539       "\n      '-scale factor'                   - scale attached object"
9540       "\n      '-autoActivate      {0|1}'        - set activation on detection"
9541       "\n      '-followTranslation {0|1}'        - set following translation transform"
9542       "\n      '-followRotation    {0|1}'        - set following rotation transform"
9543       "\n      '-gap value'                      - set gap between sub-parts"
9544       "\n      '-part axis mode    {0|1}'        - set visual part"
9545       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
9546       "\n      '-size value'                     - set size of manipulator"
9547       "\n      '-zoomable {0|1}'                 - set zoom persistence",
9548     __FILE__, VManipulator, group);
9549
9550 #if defined(_WIN32)
9551   theCommands.Add("vprogressive",
9552     "vprogressive",
9553     __FILE__, VProgressiveMode, group);
9554 #endif
9555 }