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