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