0028890: Visualization - After closing all views and then display the view again...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18
19 #include <AIS_Animation.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_ColorScale.hxx>
23 #include <AIS_Manipulator.hxx>
24 #include <AIS_RubberBand.hxx>
25 #include <AIS_Shape.hxx>
26 #include <AIS_InteractiveObject.hxx>
27 #include <AIS_ListOfInteractive.hxx>
28 #include <AIS_ListIteratorOfListOfInteractive.hxx>
29 #include <DBRep.hxx>
30 #include <Graphic3d_ArrayOfPolylines.hxx>
31 #include <Graphic3d_AspectMarker3d.hxx>
32 #include <Graphic3d_ExportFormat.hxx>
33 #include <Graphic3d_NameOfTextureEnv.hxx>
34 #include <Graphic3d_GraduatedTrihedron.hxx>
35 #include <Graphic3d_TextureEnv.hxx>
36 #include <Graphic3d_TextureParams.hxx>
37 #include <Graphic3d_TypeOfTextureFilter.hxx>
38 #include <Graphic3d_AspectFillArea3d.hxx>
39 #include <ViewerTest.hxx>
40 #include <ViewerTest_AutoUpdater.hxx>
41 #include <ViewerTest_EventManager.hxx>
42 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
43 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_CmdParser.hxx>
45 #include <V3d_AmbientLight.hxx>
46 #include <V3d_DirectionalLight.hxx>
47 #include <V3d_PositionalLight.hxx>
48 #include <V3d_SpotLight.hxx>
49 #include <NCollection_DoubleMap.hxx>
50 #include <NCollection_List.hxx>
51 #include <NCollection_Vector.hxx>
52 #include <AIS_InteractiveContext.hxx>
53 #include <Draw_Interpretor.hxx>
54 #include <Draw.hxx>
55 #include <Draw_Appli.hxx>
56 #include <Image_AlienPixMap.hxx>
57 #include <OpenGl_GraphicDriver.hxx>
58 #include <OSD_Timer.hxx>
59 #include <TColStd_HSequenceOfAsciiString.hxx>
60 #include <TColStd_SequenceOfInteger.hxx>
61 #include <TColStd_HSequenceOfReal.hxx>
62 #include <TColgp_Array1OfPnt2d.hxx>
63 #include <TColStd_MapOfAsciiString.hxx>
64 #include <Aspect_TypeOfLine.hxx>
65 #include <Image_Diff.hxx>
66 #include <Aspect_DisplayConnection.hxx>
67 #include <gp_Pnt.hxx>
68 #include <gp_Dir.hxx>
69 #include <gp_Pln.hxx>
70 #include <PrsMgr_PresentableObject.hxx>
71 #include <Graphic3d_ClipPlane.hxx>
72 #include <NCollection_DataMap.hxx>
73 #include <Graphic3d_Texture2Dmanual.hxx>
74 #include <Prs3d_ShadingAspect.hxx>
75 #include <Prs3d_Drawer.hxx>
76 #include <Prs3d_LineAspect.hxx>
77 #include <Prs3d_Root.hxx>
78
79 #ifdef _WIN32
80 #undef DrawText
81 #endif
82
83 #include <cstdlib>
84
85 #if defined(_WIN32)
86   #include <WNT_WClass.hxx>
87   #include <WNT_Window.hxx>
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 // Auxiliary definitions
98 static const char THE_KEY_DELETE = 127;
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 extern int VErase (Draw_Interpretor& theDI,
111                    Standard_Integer  theArgNb,
112                    const char**      theArgVec);
113
114 #if defined(_WIN32)
115 static Handle(WNT_Window)& VT_GetWindow() {
116   static Handle(WNT_Window) WNTWin;
117   return WNTWin;
118 }
119 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
120 static Handle(Cocoa_Window)& VT_GetWindow()
121 {
122   static Handle(Cocoa_Window) aWindow;
123   return aWindow;
124 }
125 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
126 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
127 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
128
129 #else
130 static Handle(Xw_Window)& VT_GetWindow(){
131   static Handle(Xw_Window) XWWin;
132   return XWWin;
133 }
134
135 static void VProcessEvents(ClientData,int);
136 #endif
137
138 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
139 {
140   static Handle(Aspect_DisplayConnection) aDisplayConnection;
141   return aDisplayConnection;
142 }
143
144 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
145 {
146   GetDisplayConnection() = theDisplayConnection;
147 }
148
149 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
150 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
151 {
152   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
153 #if defined(_WIN32)
154   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156     return aWindow->HWindow();
157 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
159   if (!aWindow.IsNull())
160   return aWindow->XWindow();
161 #endif
162   return aWindowHandle;
163 }
164 #endif
165
166 static Standard_Boolean MyHLRIsOn = Standard_False;
167
168 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
169 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
170 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
171 static OpenGl_Caps ViewerTest_myDefaultCaps;
172
173 static void OSWindowSetup();
174
175 static struct
176 {
177   Quantity_Color FlatColor;
178   Quantity_Color GradientColor1;
179   Quantity_Color GradientColor2;
180   Aspect_GradientFillMethod FillMethod;
181 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
182
183 //==============================================================================
184 //  EVENT GLOBAL VARIABLES
185 //==============================================================================
186
187 static int Start_Rot = 0;
188 int X_Motion = 0; // Current cursor position
189 int Y_Motion = 0;
190 int X_ButtonPress = 0; // Last ButtonPress position
191 int Y_ButtonPress = 0;
192 Standard_Boolean IsDragged = Standard_False;
193 Standard_Boolean DragFirst = Standard_False;
194 Standard_Boolean TheIsAnimating = Standard_False;
195
196
197 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
198 {
199   static Handle(AIS_RubberBand) aBand;
200   if (aBand.IsNull())
201   {
202     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
203     aBand->SetDisplayMode (0);
204   }
205   return aBand;
206 }
207
208 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
209
210 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
211 {
212   static ViewerTest_MapOfAISManipulators aMap;
213   return aMap;
214 }
215
216 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
217 {
218   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
219   for (; anIt.More(); anIt.Next())
220   {
221     if (anIt.Value()->HasActiveMode())
222     {
223       return anIt.Value();
224     }
225   }
226   return NULL;
227 }
228
229 //==============================================================================
230
231 #ifdef _WIN32
232 static LRESULT WINAPI ViewerWindowProc(
233                                        HWND hwnd,
234                                        UINT uMsg,
235                                        WPARAM wParam,
236                                        LPARAM lParam );
237 static LRESULT WINAPI AdvViewerWindowProc(
238   HWND hwnd,
239   UINT uMsg,
240   WPARAM wParam,
241   LPARAM lParam );
242 #endif
243
244
245 //==============================================================================
246 //function : WClass
247 //purpose  :
248 //==============================================================================
249
250 const Handle(Standard_Transient)& ViewerTest::WClass()
251 {
252   static Handle(Standard_Transient) theWClass;
253 #if defined(_WIN32)
254   if (theWClass.IsNull())
255   {
256     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
257                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
258                                 ::LoadCursorW (NULL, IDC_ARROW));
259   }
260 #endif
261   return theWClass;
262 }
263
264 //==============================================================================
265 //function : CreateName
266 //purpose  : Create numerical name for new object in theMap
267 //==============================================================================
268 template <typename ObjectType>
269 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
270                                     const TCollection_AsciiString& theDefaultString)
271 {
272   if (theObjectMap.IsEmpty())
273     return theDefaultString + TCollection_AsciiString(1);
274
275   Standard_Integer aNextKey = 1;
276   Standard_Boolean isFound = Standard_False;
277   while (!isFound)
278   {
279     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
280     // Look for objects with default names
281     if (theObjectMap.IsBound1(aStringKey))
282     {
283       aNextKey++;
284     }
285     else
286       isFound = Standard_True;
287   }
288
289   return theDefaultString + TCollection_AsciiString(aNextKey);
290 }
291
292 //==============================================================================
293 //structure : ViewerTest_Names
294 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
295 //==============================================================================
296 struct ViewerTest_Names
297 {
298 private:
299   TCollection_AsciiString myDriverName;
300   TCollection_AsciiString myViewerName;
301   TCollection_AsciiString myViewName;
302
303 public:
304
305   const TCollection_AsciiString& GetDriverName () const
306   {
307     return myDriverName;
308   }
309   void SetDriverName (const TCollection_AsciiString& theDriverName)
310   {
311     myDriverName = theDriverName;
312   }
313   const TCollection_AsciiString& GetViewerName () const
314   {
315     return myViewerName;
316   }
317   void SetViewerName (const TCollection_AsciiString& theViewerName)
318   {
319     myViewerName = theViewerName;
320   }
321   const TCollection_AsciiString& GetViewName () const
322   {
323     return myViewName;
324   }
325   void SetViewName (const TCollection_AsciiString& theViewName)
326   {
327     myViewName = theViewName;
328   }
329
330   //===========================================================================
331   //function : Constructor for ViewerTest_Names
332   //purpose  : Get view, viewer, driver names from custom string
333   //===========================================================================
334
335   ViewerTest_Names (const TCollection_AsciiString& theInputString)
336   {
337     TCollection_AsciiString aName(theInputString);
338     if (theInputString.IsEmpty())
339     {
340       // Get current configuration
341       if (ViewerTest_myDrivers.IsEmpty())
342         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
343           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
344       else
345         myDriverName = ViewerTest_myDrivers.Find2
346         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
347
348       if(ViewerTest_myContexts.IsEmpty())
349       {
350         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
351           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
352       }
353       else
354       {
355         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
356       }
357
358       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
359     }
360     else
361     {
362       // There is at least view name
363       Standard_Integer aParserNumber = 0;
364       for (Standard_Integer i = 0; i < 3; ++i)
365       {
366         Standard_Integer aParserPos = aName.SearchFromEnd("/");
367         if(aParserPos != -1)
368         {
369           aParserNumber++;
370           aName.Split(aParserPos-1);
371         }
372         else
373           break;
374       }
375       if (aParserNumber == 0)
376       {
377         // Only view name
378         if (!ViewerTest::GetAISContext().IsNull())
379         {
380           myDriverName = ViewerTest_myDrivers.Find2
381           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
382           myViewerName = ViewerTest_myContexts.Find2
383           (ViewerTest::GetAISContext());
384         }
385         else
386         {
387           // There is no opened contexts here, need to create names for viewer and driver
388           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
389             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
390
391           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
392             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
393         }
394         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
395       }
396       else if (aParserNumber == 1)
397       {
398         // Here is viewerName/viewName
399         if (!ViewerTest::GetAISContext().IsNull())
400           myDriverName = ViewerTest_myDrivers.Find2
401           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
402         else
403         {
404           // There is no opened contexts here, need to create name for driver
405           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
406             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
407         }
408         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
409
410         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
411       }
412       else
413       {
414         //Here is driverName/viewerName/viewName
415         myDriverName = TCollection_AsciiString(aName);
416
417         TCollection_AsciiString aViewerName(theInputString);
418         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
419         myViewerName = TCollection_AsciiString(aViewerName);
420
421         myViewName = TCollection_AsciiString(theInputString);
422       }
423     }
424   }
425 };
426
427 //==============================================================================
428 //function : FindContextByView
429 //purpose  : Find AIS_InteractiveContext by View
430 //==============================================================================
431
432 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
433 {
434   Handle(AIS_InteractiveContext) anAISContext;
435
436   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
437        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
438   {
439     if (anIter.Value()->CurrentViewer() == theView->Viewer())
440        return anIter.Key2();
441   }
442   return anAISContext;
443 }
444
445
446 //==============================================================================
447 //function : SetWindowTitle
448 //purpose  : Set window title
449 //==============================================================================
450
451 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
452                      Standard_CString theTitle)
453 {
454 #if defined(_WIN32)
455   const TCollection_ExtendedString theTitleW (theTitle);
456   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
457 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
458   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
459 #else
460   if(GetDisplayConnection()->GetDisplay())
461   {
462     Window aWindow =
463       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
464     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
465   }
466 #endif
467 }
468
469 //==============================================================================
470 //function : IsWindowOverlapped
471 //purpose  : Check if theWindow overlapp another view
472 //==============================================================================
473
474 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
475                                      const Standard_Integer thePxTop,
476                                      const Standard_Integer thePxRight,
477                                      const Standard_Integer thePxBottom,
478                                      TCollection_AsciiString& theViewId)
479 {
480   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
481       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
482   {
483     Standard_Integer aTop = 0,
484       aLeft = 0,
485       aRight = 0,
486       aBottom = 0;
487     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
488     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
489         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
490         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
491         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
492     {
493       theViewId = anIter.Key1();
494       return Standard_True;
495     }
496   }
497   return Standard_False;
498 }
499
500 // Workaround: to create and delete non-orthographic views outside ViewerTest
501 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
502 {
503   ViewerTest_myViews.UnBind1 (theName);
504 }
505
506 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
507                                const Handle(V3d_View)& theView)
508 {
509   ViewerTest_myViews.Bind (theName, theView);
510 }
511
512 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
513 {
514   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
515 }
516 //==============================================================================
517 //function : ViewerInit
518 //purpose  : Create the window viewer and initialize all the global variable
519 //==============================================================================
520
521 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
522                                                 const Standard_Integer thePxTop,
523                                                 const Standard_Integer thePxWidth,
524                                                 const Standard_Integer thePxHeight,
525                                                 Standard_CString theViewName,
526                                                 Standard_CString theDisplayName)
527 {
528   // Default position and dimension of the viewer window.
529   // Note that left top corner is set to be sufficiently small to have
530   // window fit in the small screens (actual for remote desktops, see #23003).
531   // The position corresponds to the window's client area, thus some
532   // gap is added for window frame to be visible.
533   Standard_Integer aPxLeft   = 20;
534   Standard_Integer aPxTop    = 40;
535   Standard_Integer aPxWidth  = 409;
536   Standard_Integer aPxHeight = 409;
537   Standard_Boolean toCreateViewer = Standard_False;
538
539   Handle(OpenGl_GraphicDriver) aGraphicDriver;
540   ViewerTest_Names aViewNames(theViewName);
541   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
542     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
543
544   if (thePxLeft != 0)
545     aPxLeft = thePxLeft;
546   if (thePxTop != 0)
547     aPxTop = thePxTop;
548   if (thePxWidth != 0)
549     aPxWidth = thePxWidth;
550   if (thePxHeight != 0)
551     aPxHeight = thePxHeight;
552
553   // Get graphic driver (create it or get from another view)
554   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
555   {
556     // Get connection string
557   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
558     TCollection_AsciiString aDisplayName(theDisplayName);
559     if (!aDisplayName.IsEmpty())
560       SetDisplayConnection (new Aspect_DisplayConnection ());
561     else
562       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
563   #else
564     (void)theDisplayName; // avoid warning on unused argument
565     SetDisplayConnection (new Aspect_DisplayConnection ());
566   #endif
567
568     if (Draw_VirtualWindows)
569     {
570       // don't waste the time waiting for VSync when window is not displayed on the screen
571       ViewerTest_myDefaultCaps.swapInterval = 0;
572       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
573       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
574     }
575     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
576     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
577
578     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
579     toCreateViewer = Standard_True;
580   }
581   else
582   {
583     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
584   }
585
586   //Dispose the window if input parameters are default
587   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
588   {
589     Standard_Integer aTop = 0,
590                      aLeft = 0,
591                      aRight = 0,
592                      aBottom = 0,
593                      aScreenWidth = 0,
594                      aScreenHeight = 0;
595
596     // Get screen resolution
597 #if defined(_WIN32) || defined(__WIN32__)
598     RECT aWindowSize;
599     GetClientRect(GetDesktopWindow(), &aWindowSize);
600     aScreenHeight = aWindowSize.bottom;
601     aScreenWidth = aWindowSize.right;
602 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
603     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
604 #else
605     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
606     aScreenWidth = WidthOfScreen(aScreen);
607     aScreenHeight = HeightOfScreen(aScreen);
608 #endif
609
610     TCollection_AsciiString anOverlappedViewId("");
611
612     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
613     {
614       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
615
616       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
617         && aRight + 2*aPxWidth + 40 > aScreenWidth)
618       {
619         if (aBottom + aPxHeight + 40 > aScreenHeight)
620         {
621           aPxLeft = 20;
622           aPxTop = 40;
623           break;
624         }
625         aPxLeft = 20;
626         aPxTop = aBottom + 40;
627       }
628       else
629         aPxLeft = aRight + 20;
630     }
631   }
632
633   // Get viewer name
634   TCollection_AsciiString aTitle("3D View - ");
635   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
636
637   // Change name of current active window
638   if (!ViewerTest::CurrentView().IsNull())
639   {
640     TCollection_AsciiString anActiveWindowTitle("3D View - ");
641     anActiveWindowTitle = anActiveWindowTitle
642       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
643     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
644   }
645
646   // Create viewer
647   Handle(V3d_Viewer) a3DViewer;
648   // If it's the single view, we first look for empty context
649   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
650   {
651     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
652       anIter(ViewerTest_myContexts);
653     if (anIter.More())
654       ViewerTest::SetAISContext (anIter.Value());
655     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
656   }
657   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
658   {
659     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
660     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
661   }
662   else if (a3DViewer.IsNull())
663   {
664     toCreateViewer = Standard_True;
665     a3DViewer = new V3d_Viewer(aGraphicDriver);
666     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
667     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
668                                            ViewerTest_DefaultBackground.GradientColor2,
669                                            ViewerTest_DefaultBackground.FillMethod);
670   }
671
672   // AIS context setup
673   if (ViewerTest::GetAISContext().IsNull() ||
674       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
675   {
676     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
677     ViewerTest::SetAISContext (aContext);
678     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
679   }
680   else
681   {
682     ViewerTest::ResetEventManager();
683   }
684
685   // Create window
686 #if defined(_WIN32)
687   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
688                                     Handle(WNT_WClass)::DownCast (WClass()),
689                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
690                                     aPxLeft, aPxTop,
691                                     aPxWidth, aPxHeight,
692                                     Quantity_NOC_BLACK);
693 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
694   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
695                                      aPxLeft, aPxTop,
696                                      aPxWidth, aPxHeight);
697   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
698 #else
699   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
700                                   aTitle.ToCString(),
701                                   aPxLeft, aPxTop,
702                                   aPxWidth, aPxHeight);
703 #endif
704   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
705
706   // View setup
707   Handle(V3d_View) aView = a3DViewer->CreateView();
708   aView->SetWindow (VT_GetWindow());
709   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
710
711   ViewerTest::CurrentView(aView);
712   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
713
714   // Setup for X11 or NT
715   OSWindowSetup();
716
717   // Set parameters for V3d_View and V3d_Viewer
718   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
719   aV3dView->SetComputedMode(Standard_False);
720   MyHLRIsOn = aV3dView->ComputedMode();
721
722   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
723   if (toCreateViewer)
724   {
725     a3DViewer->SetDefaultLights();
726     a3DViewer->SetLightOn();
727   }
728
729   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
730   #if TCL_MAJOR_VERSION  < 8
731   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
732       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
733   #else
734   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
735       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
736   #endif
737   #endif
738
739   VT_GetWindow()->Map();
740
741   // Set the handle of created view in the event manager
742   ViewerTest::ResetEventManager();
743
744   ViewerTest::CurrentView()->Redraw();
745
746   aView.Nullify();
747   a3DViewer.Nullify();
748
749   return aViewNames.GetViewName();
750 }
751
752 //==============================================================================
753 //function : RedrawAllViews
754 //purpose  : Redraw all created views
755 //==============================================================================
756 void ViewerTest::RedrawAllViews()
757 {
758   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
759   for (; aViewIt.More(); aViewIt.Next())
760   {
761     const Handle(V3d_View)& aView = aViewIt.Key2();
762     aView->Redraw();
763   }
764 }
765
766 //==============================================================================
767 //function : Vinit
768 //purpose  : Create the window viewer and initialize all the global variable
769 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
770 //==============================================================================
771
772 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
773 {
774   if (theArgsNb > 9)
775   {
776     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
777               << "Type help for more information.\n";
778     return 1;
779   }
780
781   TCollection_AsciiString aViewName, aDisplayName;
782   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
783   TCollection_AsciiString aName, aValue;
784   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
785   {
786     const TCollection_AsciiString anArg = theArgVec[anArgIt];
787     TCollection_AsciiString anArgCase = anArg;
788     anArgCase.UpperCase();
789     if (ViewerTest::SplitParameter (anArg, aName, aValue))
790     {
791       aName.UpperCase();
792       if (aName.IsEqual ("NAME"))
793       {
794         aViewName = aValue;
795       }
796       else if (aName.IsEqual ("L")
797             || aName.IsEqual ("LEFT"))
798       {
799         aPxLeft = aValue.IntegerValue();
800       }
801       else if (aName.IsEqual ("T")
802             || aName.IsEqual ("TOP"))
803       {
804         aPxTop = aValue.IntegerValue();
805       }
806     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
807       else if (aName.IsEqual ("DISP")
808             || aName.IsEqual ("DISPLAY"))
809       {
810         aDisplayName = aValue;
811       }
812     #endif
813       else if (aName.IsEqual ("W")
814             || aName.IsEqual ("WIDTH"))
815       {
816         aPxWidth = aValue.IntegerValue();
817       }
818       else if (aName.IsEqual ("H")
819             || aName.IsEqual ("HEIGHT"))
820       {
821         aPxHeight = aValue.IntegerValue();
822       }
823       else
824       {
825         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
826       }
827     }
828     else if (aViewName.IsEmpty())
829     {
830       aViewName = anArg;
831     }
832     else
833     {
834       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
835     }
836   }
837
838   ViewerTest_Names aViewNames (aViewName);
839   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
840   {
841     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
842     theDi.Eval (aCommand.ToCString());
843     return 0;
844   }
845
846   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
847                                                             aViewName.ToCString(),
848                                                             aDisplayName.ToCString());
849   theDi << aViewId;
850   return 0;
851 }
852
853 //==============================================================================
854 //function : VHLR
855 //purpose  : hidden lines removal algorithm
856 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
857 //==============================================================================
858
859 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
860 {
861   if (ViewerTest::CurrentView().IsNull())
862   {
863     di << argv[0] << ": Call vinit before this command, please.\n";
864     return 1;
865   }
866
867   if (argc < 2)
868   {
869     di << argv[0] << ": Wrong number of command arguments.\n"
870       << "Type help " << argv[0] << " for more information.\n";
871     return 1;
872   }
873
874   // Enable or disable HLR mode.
875   Standard_Boolean isHLROn =
876     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
877
878   if (isHLROn != MyHLRIsOn)
879   {
880     MyHLRIsOn = isHLROn;
881     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
882   }
883
884   // Show or hide hidden lines in HLR mode.
885   Standard_Boolean isCurrentShowHidden
886     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
887
888   Standard_Boolean isShowHidden =
889     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
890                 : isCurrentShowHidden;
891
892
893   if (isShowHidden != isCurrentShowHidden)
894   {
895     if (isShowHidden)
896     {
897       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
898     }
899     else
900     {
901       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
902     }
903
904     // Redisplay shapes.
905     if (MyHLRIsOn)
906     {
907       AIS_ListOfInteractive aListOfShapes;
908       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
909
910       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
911       {
912         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
913         if (aShape.IsNull())
914         {
915           continue;
916         }
917         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
918       }
919     }
920   }
921
922   ViewerTest::CurrentView()->Update();
923   return 0;
924 }
925
926 //==============================================================================
927 //function : VHLRType
928 //purpose  : change type of using HLR algorithm
929 //==============================================================================
930
931 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
932 {
933   if (ViewerTest::CurrentView().IsNull())
934   {
935     di << argv[0] << ": Call vinit before this command, please.\n";
936     return 1;
937   }
938
939   if (argc < 2)
940   {
941     di << argv[0] << ": Wrong number of command arguments.\n"
942       << "Type help " << argv[0] << " for more information.\n";
943     return 1;
944   }
945
946   Prs3d_TypeOfHLR aTypeOfHLR =
947     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
948
949   if (argc == 2)
950   {
951     AIS_ListOfInteractive aListOfShapes;
952     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
953     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
954     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
955       anIter.More(); anIter.Next())
956     {
957       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
958       if (aShape.IsNull())
959         continue;
960       if (aShape->TypeOfHLR() != aTypeOfHLR)
961         aShape->SetTypeOfHLR (aTypeOfHLR);
962       if (MyHLRIsOn)
963         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
964     }
965     ViewerTest::CurrentView()->Update();
966     return 0;
967   }
968   else
969   {
970     for (Standard_Integer i = 2; i < argc; ++i)
971     {
972       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
973       TCollection_AsciiString aName (argv[i]);
974
975       if (!aMap.IsBound2 (aName))
976       {
977         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
978         continue;
979       }
980       Handle(AIS_Shape) anAISObject =
981         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
982       if (anAISObject.IsNull())
983         continue;
984       anAISObject->SetTypeOfHLR (aTypeOfHLR);
985       if (MyHLRIsOn)
986         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
987     }
988     ViewerTest::CurrentView()->Update();
989   }
990
991   return 0;
992 }
993
994 //==============================================================================
995 //function : FindViewIdByWindowHandle
996 //purpose  : Find theView Id in the map of views by window handle
997 //==============================================================================
998 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
999 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1000 {
1001   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1002        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1003   {
1004     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1005     if (aWindowHandle == theWindowHandle)
1006       return anIter.Key1();
1007   }
1008   return TCollection_AsciiString("");
1009 }
1010 #endif
1011
1012 //==============================================================================
1013 //function : ActivateView
1014 //purpose  : Make the view active
1015 //==============================================================================
1016
1017 void ActivateView (const TCollection_AsciiString& theViewName)
1018 {
1019   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1020   if (!aView.IsNull())
1021   {
1022     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1023     if (!anAISContext.IsNull())
1024     {
1025       if (!ViewerTest::CurrentView().IsNull())
1026       {
1027         TCollection_AsciiString aTitle("3D View - ");
1028         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1029         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1030       }
1031
1032       ViewerTest::CurrentView (aView);
1033       // Update degenerate mode
1034       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1035       ViewerTest::SetAISContext (anAISContext);
1036       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1037       aTitle = aTitle + theViewName + "(*)";
1038       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1039 #if defined(_WIN32) || defined(__WIN32__)
1040       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1041 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1042       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1043 #else
1044       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1045 #endif
1046       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1047       ViewerTest::CurrentView()->Redraw();
1048     }
1049   }
1050 }
1051
1052 //==============================================================================
1053 //function : RemoveView
1054 //purpose  :
1055 //==============================================================================
1056 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1057                              const Standard_Boolean  theToRemoveContext)
1058 {
1059   if (!ViewerTest_myViews.IsBound2 (theView))
1060   {
1061     return;
1062   }
1063
1064   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1065   RemoveView (aViewName, theToRemoveContext);
1066 }
1067
1068 //==============================================================================
1069 //function : RemoveView
1070 //purpose  : Close and remove view from display, clear maps if neccessary
1071 //==============================================================================
1072 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1073 {
1074   if (!ViewerTest_myViews.IsBound1(theViewName))
1075   {
1076     cout << "Wrong view name\n";
1077     return;
1078   }
1079
1080   // Activate another view if it's active now
1081   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1082   {
1083     if (ViewerTest_myViews.Extent() > 1)
1084     {
1085       TCollection_AsciiString aNewViewName;
1086       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1087            anIter.More(); anIter.Next())
1088       {
1089         if (anIter.Key1() != theViewName)
1090         {
1091           aNewViewName = anIter.Key1();
1092           break;
1093         }
1094       }
1095       ActivateView (aNewViewName);
1096     }
1097     else
1098     {
1099       Handle(V3d_View) anEmptyView;
1100 #if defined(_WIN32) || defined(__WIN32__)
1101       Handle(WNT_Window) anEmptyWindow;
1102 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1103       Handle(Cocoa_Window) anEmptyWindow;
1104 #else
1105       Handle(Xw_Window) anEmptyWindow;
1106 #endif
1107       VT_GetWindow() = anEmptyWindow;
1108       ViewerTest::CurrentView (anEmptyView);
1109       if (isContextRemoved)
1110       {
1111         Handle(AIS_InteractiveContext) anEmptyContext;
1112         ViewerTest::SetAISContext(anEmptyContext);
1113       }
1114     }
1115   }
1116
1117   // Delete view
1118   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1119   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1120
1121   // Remove view resources
1122   ViewerTest_myViews.UnBind1(theViewName);
1123   aView->Window()->Unmap();
1124   aView->Remove();
1125
1126 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1127   XFlush (GetDisplayConnection()->GetDisplay());
1128 #endif
1129
1130   // Keep context opened only if the closed view is last to avoid
1131   // unused empty contexts
1132   if (!aCurrentContext.IsNull())
1133   {
1134     // Check if there are more difined views in the viewer
1135     aCurrentContext->CurrentViewer()->InitDefinedViews();
1136     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1137     {
1138       // Remove driver if there is no viewers that use it
1139       Standard_Boolean isRemoveDriver = Standard_True;
1140       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1141           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1142       {
1143         if (aCurrentContext != anIter.Key2() &&
1144           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1145         {
1146           isRemoveDriver = Standard_False;
1147           break;
1148         }
1149       }
1150
1151       aCurrentContext->RemoveAll (Standard_False);
1152       if(isRemoveDriver)
1153       {
1154         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1155       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1156         #if TCL_MAJOR_VERSION  < 8
1157         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1158         #else
1159         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1160         #endif
1161       #endif
1162       }
1163
1164       ViewerTest_myContexts.UnBind2(aCurrentContext);
1165     }
1166   }
1167   cout << "3D View - " << theViewName << " was deleted.\n";
1168
1169 }
1170
1171 //==============================================================================
1172 //function : VClose
1173 //purpose  : Remove the view defined by its name
1174 //==============================================================================
1175
1176 static int VClose (Draw_Interpretor& /*theDi*/,
1177                    Standard_Integer  theArgsNb,
1178                    const char**      theArgVec)
1179 {
1180   NCollection_List<TCollection_AsciiString> aViewList;
1181   if (theArgsNb > 1)
1182   {
1183     TCollection_AsciiString anArg (theArgVec[1]);
1184     anArg.UpperCase();
1185     if (anArg.IsEqual ("ALL")
1186      || anArg.IsEqual ("*"))
1187     {
1188       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1189            anIter.More(); anIter.Next())
1190       {
1191         aViewList.Append (anIter.Key1());
1192       }
1193       if (aViewList.IsEmpty())
1194       {
1195         std::cout << "No view to close\n";
1196         return 0;
1197       }
1198     }
1199     else
1200     {
1201       ViewerTest_Names aViewName (theArgVec[1]);
1202       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1203       {
1204         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1205         return 1;
1206       }
1207       aViewList.Append (aViewName.GetViewName());
1208     }
1209   }
1210   else
1211   {
1212     // close active view
1213     if (ViewerTest::CurrentView().IsNull())
1214     {
1215       std::cerr << "No active view!\n";
1216       return 1;
1217     }
1218     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1219   }
1220
1221   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1222   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1223        anIter.More(); anIter.Next())
1224   {
1225     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1226   }
1227
1228   return 0;
1229 }
1230
1231 //==============================================================================
1232 //function : VActivate
1233 //purpose  : Activate the view defined by its ID
1234 //==============================================================================
1235
1236 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1237 {
1238   if (theArgsNb > 2)
1239   {
1240     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1241     << "Usage: " << theArgVec[0] << " ViewID\n";
1242     return 1;
1243   }
1244   if(theArgsNb == 1)
1245   {
1246     theDi.Eval("vviewlist");
1247     return 0;
1248   }
1249
1250   TCollection_AsciiString aNameString(theArgVec[1]);
1251   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1252   {
1253     TCollection_AsciiString aTitle("3D View - ");
1254     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1255     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1256     Handle(V3d_View) anEmptyView;
1257 #if defined(_WIN32) || defined(__WIN32__)
1258     Handle(WNT_Window) anEmptyWindow;
1259 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1260     Handle(Cocoa_Window) anEmptyWindow;
1261 #else
1262     Handle(Xw_Window) anEmptyWindow;
1263 #endif
1264     VT_GetWindow() = anEmptyWindow;
1265     ViewerTest::CurrentView (anEmptyView);
1266     ViewerTest::ResetEventManager();
1267     theDi << theArgVec[0] << ": all views are inactive\n";
1268     return 0;
1269   }
1270
1271   ViewerTest_Names aViewNames(aNameString);
1272
1273   // Check if this view exists in the viewer with the driver
1274   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1275   {
1276     theDi << "Wrong view name\n";
1277     return 1;
1278   }
1279
1280   // Check if it is active already
1281   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1282   {
1283     theDi << theArgVec[0] << ": the view is active already\n";
1284     return 0;
1285   }
1286
1287   ActivateView (aViewNames.GetViewName());
1288   return 0;
1289 }
1290
1291 //==============================================================================
1292 //function : VViewList
1293 //purpose  : Print current list of views per viewer and graphic driver ID
1294 //           shared between viewers
1295 //==============================================================================
1296
1297 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1298 {
1299   if (theArgsNb > 2)
1300   {
1301     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1302           << "Usage: " << theArgVec[0] << " name";
1303     return 1;
1304   }
1305   if (ViewerTest_myContexts.Size() < 1)
1306     return 0;
1307
1308   Standard_Boolean isTreeView =
1309     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1310
1311   if (isTreeView)
1312   {
1313     theDi << theArgVec[0] <<":\n";
1314   }
1315
1316   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1317        aDriverIter.More(); aDriverIter.Next())
1318   {
1319     if (isTreeView)
1320       theDi << aDriverIter.Key1() << ":\n";
1321
1322     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1323       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1324     {
1325       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1326       {
1327         if (isTreeView)
1328         {
1329           TCollection_AsciiString aContextName(aContextIter.Key1());
1330           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1331         }
1332
1333         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1334              aViewIter.More(); aViewIter.Next())
1335         {
1336           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1337           {
1338             TCollection_AsciiString aViewName(aViewIter.Key1());
1339             if (isTreeView)
1340             {
1341               if (aViewIter.Value() == ViewerTest::CurrentView())
1342                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1343               else
1344                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1345             }
1346             else
1347             {
1348               theDi << aViewName << " ";
1349             }
1350           }
1351         }
1352       }
1353     }
1354   }
1355   return 0;
1356 }
1357
1358 //==============================================================================
1359 //function : VT_ProcessKeyPress
1360 //purpose  : Handle KeyPress event from a CString
1361 //==============================================================================
1362 void VT_ProcessKeyPress (const char* buf_ret)
1363 {
1364   //cout << "KeyPress" << endl;
1365   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1366   // Letter in alphabetic order
1367
1368   if (!strcasecmp (buf_ret, "A"))
1369   {
1370     // AXO
1371     aView->SetProj(V3d_XposYnegZpos);
1372   }
1373   else if (!strcasecmp (buf_ret, "D"))
1374   {
1375     // Reset
1376     aView->Reset();
1377   }
1378   else if (!strcasecmp (buf_ret, "F"))
1379   {
1380     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1381     {
1382       ViewerTest::GetAISContext()->FitSelected (aView);
1383     }
1384     else
1385     {
1386       // FitAll
1387       aView->FitAll();
1388     }
1389   }
1390   else if (!strcasecmp (buf_ret, "H"))
1391   {
1392     // HLR
1393     cout << "HLR" << endl;
1394     aView->SetComputedMode (!aView->ComputedMode());
1395     MyHLRIsOn = aView->ComputedMode();
1396   }
1397   else if (!strcasecmp (buf_ret, "P"))
1398   {
1399     // Type of HLR
1400     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1401     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1402       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1403     else
1404       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1405     if (aContext->NbSelected()==0)
1406     {
1407       AIS_ListOfInteractive aListOfShapes;
1408       aContext->DisplayedObjects(aListOfShapes);
1409       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1410         anIter.More(); anIter.Next())
1411       {
1412         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1413         if (aShape.IsNull())
1414           continue;
1415         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1416           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1417         else
1418           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1419         aContext->Redisplay (aShape, Standard_False);
1420       }
1421     }
1422     else
1423     {
1424       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1425       {
1426         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1427         if (aShape.IsNull())
1428           continue;
1429         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1430           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1431         else
1432           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1433         aContext->Redisplay (aShape, Standard_False);
1434       }
1435     }
1436
1437     aContext->UpdateCurrentViewer();
1438
1439   }
1440   else if (!strcasecmp (buf_ret, "S"))
1441   {
1442     std::cout << "setup Shaded display mode" << std::endl;
1443
1444     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1445     if(Ctx->NbSelected()==0)
1446       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1447     else{
1448       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1449         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1450       Ctx->UpdateCurrentViewer();
1451     }
1452   }
1453   else if (!strcasecmp (buf_ret, "U"))
1454   {
1455     // Unset display mode
1456     std::cout << "reset display mode to defaults" << std::endl;
1457
1458     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1459     if(Ctx->NbSelected()==0)
1460       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1461     else{
1462       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1463         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1464       Ctx->UpdateCurrentViewer();
1465     }
1466
1467   }
1468   else if (!strcasecmp (buf_ret, "T"))
1469   {
1470     // Top
1471     aView->SetProj(V3d_Zpos);
1472   }
1473   else if (!strcasecmp (buf_ret, "B"))
1474   {
1475     // Bottom
1476     aView->SetProj(V3d_Zneg);
1477   }
1478   else if (!strcasecmp (buf_ret, "L"))
1479   {
1480     // Left
1481     aView->SetProj(V3d_Xneg);
1482   }
1483   else if (!strcasecmp (buf_ret, "R"))
1484   {
1485     // Right
1486     aView->SetProj(V3d_Xpos);
1487   }
1488   else if (!strcasecmp (buf_ret, "W"))
1489   {
1490     std::cout << "setup WireFrame display mode" << std::endl;
1491     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1492     if(Ctx->NbSelected()==0)
1493       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1494     else{
1495       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1496         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1497       Ctx->UpdateCurrentViewer();
1498     }
1499   }
1500   else if (!strcasecmp (buf_ret, ","))
1501   {
1502     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1503   }
1504   else if (!strcasecmp (buf_ret, "."))
1505   {
1506     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1507   }
1508   else if (!strcasecmp (buf_ret, "/"))
1509   {
1510     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1511     if (aCamera->IsStereo())
1512     {
1513       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1514       aView->Redraw();
1515     }
1516   }
1517   else if (!strcasecmp (buf_ret, "*"))
1518   {
1519     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1520     if (aCamera->IsStereo())
1521     {
1522       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1523       aView->Redraw();
1524     }
1525   }
1526   else if (*buf_ret == THE_KEY_DELETE)
1527   {
1528     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1529     if (!aCtx.IsNull()
1530      && aCtx->NbSelected() > 0)
1531     {
1532       Draw_Interprete ("verase");
1533     }
1534   }
1535   else
1536   {
1537     // Number
1538     Standard_Integer Num = Draw::Atoi(buf_ret);
1539     if(Num>=0 && Num<=7)
1540       ViewerTest::StandardModeActivation(Num);
1541   }
1542 }
1543
1544 //==============================================================================
1545 //function : VT_ProcessExpose
1546 //purpose  : Redraw the View on an Expose Event
1547 //==============================================================================
1548 void VT_ProcessExpose()
1549 {
1550   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1551   if (!aView3d.IsNull())
1552   {
1553     aView3d->Redraw();
1554   }
1555 }
1556
1557 //==============================================================================
1558 //function : VT_ProcessConfigure
1559 //purpose  : Resize the View on an Configure Event
1560 //==============================================================================
1561 void VT_ProcessConfigure()
1562 {
1563   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1564   if (aView3d.IsNull())
1565   {
1566     return;
1567   }
1568
1569   aView3d->MustBeResized();
1570   aView3d->Update();
1571   aView3d->Redraw();
1572 }
1573
1574 //==============================================================================
1575 //function : VT_ProcessButton1Press
1576 //purpose  : Picking
1577 //==============================================================================
1578 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1579                                          const char**     theArgVec,
1580                                          Standard_Boolean theToPick,
1581                                          Standard_Boolean theIsShift)
1582 {
1583   if (TheIsAnimating)
1584   {
1585     TheIsAnimating = Standard_False;
1586     return Standard_False;
1587   }
1588
1589   if (theToPick)
1590   {
1591     Standard_Real X, Y, Z;
1592     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1593
1594     Draw::Set (theArgVec[1], X);
1595     Draw::Set (theArgVec[2], Y);
1596     Draw::Set (theArgVec[3], Z);
1597   }
1598
1599   if (theIsShift)
1600   {
1601     ViewerTest::CurrentEventManager()->ShiftSelect();
1602   }
1603   else
1604   {
1605     ViewerTest::CurrentEventManager()->Select();
1606   }
1607
1608   return Standard_False;
1609 }
1610
1611 //==============================================================================
1612 //function : VT_ProcessButton1Release
1613 //purpose  : End selecting
1614 //==============================================================================
1615 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1616 {
1617   if (IsDragged)
1618   {
1619     IsDragged = Standard_False;
1620     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1621     if (theIsShift)
1622     {
1623       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1624                        X_Motion, Y_Motion);
1625     }
1626     else
1627     {
1628       EM->Select (X_ButtonPress, Y_ButtonPress,
1629                   X_Motion, Y_Motion);
1630     }
1631   }
1632 }
1633
1634 //==============================================================================
1635 //function : VT_ProcessButton3Press
1636 //purpose  : Start Rotation
1637 //==============================================================================
1638 void VT_ProcessButton3Press()
1639 {
1640   Start_Rot = 1;
1641   if (MyHLRIsOn)
1642   {
1643     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1644   }
1645   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1646 }
1647
1648 //==============================================================================
1649 //function : VT_ProcessButton3Release
1650 //purpose  : End rotation
1651 //==============================================================================
1652 void VT_ProcessButton3Release()
1653 {
1654   if (Start_Rot)
1655   {
1656     Start_Rot = 0;
1657     if (MyHLRIsOn)
1658     {
1659       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1660     }
1661   }
1662 }
1663
1664 //==============================================================================
1665 //function : ProcessControlButton1Motion
1666 //purpose  : Zoom
1667 //==============================================================================
1668
1669 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1670 static void ProcessControlButton1Motion()
1671 {
1672   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1673
1674   X_ButtonPress = X_Motion;
1675   Y_ButtonPress = Y_Motion;
1676 }
1677 #endif
1678
1679 //==============================================================================
1680 //function : VT_ProcessControlButton2Motion
1681 //purpose  : Panning
1682 //==============================================================================
1683 void VT_ProcessControlButton2Motion()
1684 {
1685   Standard_Integer aDx = X_Motion - X_ButtonPress;
1686   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1687
1688   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1689
1690   ViewerTest::CurrentView()->Pan (aDx, aDy);
1691
1692   X_ButtonPress = X_Motion;
1693   Y_ButtonPress = Y_Motion;
1694 }
1695
1696 //==============================================================================
1697 //function : VT_ProcessControlButton3Motion
1698 //purpose  : Rotation
1699 //==============================================================================
1700 void VT_ProcessControlButton3Motion()
1701 {
1702   if (Start_Rot)
1703   {
1704     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1705   }
1706 }
1707
1708 //==============================================================================
1709 //function : VT_ProcessMotion
1710 //purpose  :
1711 //==============================================================================
1712 void VT_ProcessMotion()
1713 {
1714   //pre-hilights detected objects at mouse position
1715
1716   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1717   EM->MoveTo(X_Motion, Y_Motion);
1718 }
1719
1720
1721 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1722 {
1723   Xpix = X_Motion;Ypix=Y_Motion;
1724 }
1725
1726 //==============================================================================
1727 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1728 //purpose  : Switches to an axonometric, top, left and other views
1729 //==============================================================================
1730
1731 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1732 {
1733   if ( ViewerTest::CurrentView().IsNull() )
1734   {
1735     di<<"Call vinit before this command, please\n";
1736     return 1;
1737   }
1738
1739   ViewerTest::CurrentView()->SetProj(ori);
1740   return 0;
1741 }
1742
1743 //==============================================================================
1744 //function : VAxo
1745 //purpose  : Switch to an Axonometric view
1746 //Draw arg : No args
1747 //==============================================================================
1748
1749 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1750 {
1751   return ViewProject(di, V3d_XposYnegZpos);
1752 }
1753
1754 //==============================================================================
1755 //function : VTop
1756 //purpose  : Switch to a Top View
1757 //Draw arg : No args
1758 //==============================================================================
1759
1760 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1761 {
1762   return ViewProject(di, V3d_Zpos);
1763 }
1764
1765 //==============================================================================
1766 //function : VBottom
1767 //purpose  : Switch to a Bottom View
1768 //Draw arg : No args
1769 //==============================================================================
1770
1771 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1772 {
1773   return ViewProject(di, V3d_Zneg);
1774 }
1775
1776 //==============================================================================
1777 //function : VLeft
1778 //purpose  : Switch to a Left View
1779 //Draw arg : No args
1780 //==============================================================================
1781
1782 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1783 {
1784   return ViewProject(di, V3d_Xneg);
1785 }
1786
1787 //==============================================================================
1788 //function : VRight
1789 //purpose  : Switch to a Right View
1790 //Draw arg : No args
1791 //==============================================================================
1792
1793 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1794 {
1795   return ViewProject(di, V3d_Xpos);
1796 }
1797
1798 //==============================================================================
1799 //function : VFront
1800 //purpose  : Switch to a Front View
1801 //Draw arg : No args
1802 //==============================================================================
1803
1804 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1805 {
1806   return ViewProject(di, V3d_Yneg);
1807 }
1808
1809 //==============================================================================
1810 //function : VBack
1811 //purpose  : Switch to a Back View
1812 //Draw arg : No args
1813 //==============================================================================
1814
1815 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1816 {
1817   return ViewProject(di, V3d_Ypos);
1818 }
1819
1820 //==============================================================================
1821 //function : VHelp
1822 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1823 //Draw arg : No args
1824 //==============================================================================
1825
1826 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1827 {
1828
1829   di << "Q : Quit the application\n";
1830
1831   di << "=========================\n";
1832   di << "F : FitAll\n";
1833   di << "T : TopView\n";
1834   di << "B : BottomView\n";
1835   di << "R : RightView\n";
1836   di << "L : LeftView\n";
1837   di << "A : AxonometricView\n";
1838   di << "D : ResetView\n";
1839
1840   di << "=========================\n";
1841   di << "S : Shading\n";
1842   di << "W : Wireframe\n";
1843   di << "H : HidelLineRemoval\n";
1844   di << "U : Unset display mode\n";
1845   di << "Delete : Remove selection from viewer\n";
1846
1847   di << "=========================\n";
1848   di << "Selection mode \n";
1849   di << "0 : Shape\n";
1850   di << "1 : Vertex\n";
1851   di << "2 : Edge\n";
1852   di << "3 : Wire\n";
1853   di << "4 : Face\n";
1854   di << "5 : Shell\n";
1855   di << "6 : Solid\n";
1856   di << "7 : Compound\n";
1857
1858   di << "=========================\n";
1859   di << "Z : Switch Z clipping On/Off\n";
1860   di << ", : Hilight next detected\n";
1861   di << ". : Hilight previous detected\n";
1862
1863   return 0;
1864 }
1865
1866 #ifdef _WIN32
1867
1868 static Standard_Boolean Ppick = 0;
1869 static Standard_Integer Pargc = 0;
1870 static const char**           Pargv = NULL;
1871
1872
1873 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1874                                           UINT Msg,
1875                                           WPARAM wParam,
1876                                           LPARAM lParam )
1877 {
1878   if (!ViewerTest_myViews.IsEmpty()) {
1879
1880     WPARAM fwKeys = wParam;
1881
1882     switch( Msg ) {
1883     case WM_CLOSE:
1884        {
1885          // Delete view from map of views
1886          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1887          return 0;
1888        }
1889        break;
1890     case WM_ACTIVATE:
1891       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1892         || ViewerTest::CurrentView().IsNull())
1893       {
1894         // Activate inactive window
1895         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1896         {
1897           ActivateView (FindViewIdByWindowHandle(hwnd));
1898         }
1899       }
1900       break;
1901
1902     case WM_LBUTTONUP:
1903       if (IsDragged && !DragFirst)
1904       {
1905         if (!GetActiveAISManipulator().IsNull())
1906         {
1907           GetActiveAISManipulator()->StopTransform();
1908           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1909         }
1910
1911         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1912         {
1913           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1914           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1915         }
1916
1917         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
1918       }
1919       IsDragged = Standard_False;
1920       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1921
1922     case WM_RBUTTONUP:
1923       if (IsDragged && !DragFirst)
1924       {
1925         if (!GetActiveAISManipulator().IsNull())
1926         {
1927           GetActiveAISManipulator()->StopTransform (Standard_False);
1928           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
1929         }
1930         IsDragged = Standard_False;
1931       }
1932       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
1933
1934     case WM_LBUTTONDOWN:
1935       if (!GetActiveAISManipulator().IsNull())
1936       {
1937         IsDragged = ( fwKeys == MK_LBUTTON );
1938       }
1939       else
1940       {
1941         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
1942       }
1943
1944       if (IsDragged)
1945       {
1946         DragFirst = Standard_True;
1947         X_ButtonPress = LOWORD(lParam);
1948         Y_ButtonPress = HIWORD(lParam);
1949       }
1950       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1951
1952     case WM_MOUSEMOVE:
1953       if (IsDragged)
1954       {
1955         X_Motion = LOWORD (lParam);
1956         Y_Motion = HIWORD (lParam);
1957         if (!GetActiveAISManipulator().IsNull())
1958         {
1959           if (DragFirst)
1960           {
1961             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
1962           }
1963           else
1964           {
1965             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
1966             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
1967           }
1968         }
1969         else
1970         {
1971           bool toRedraw = false;
1972           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1973           {
1974             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1975             toRedraw = true;
1976           }
1977
1978           RECT aRect;
1979           if (GetClientRect (hwnd, &aRect))
1980           {
1981             int aHeight = aRect.bottom - aRect.top;
1982             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1983             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1984             toRedraw = true;
1985           }
1986           if (toRedraw)
1987           {
1988             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1989           }
1990         }
1991
1992         DragFirst = Standard_False;
1993       }
1994       else
1995         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1996       break;
1997
1998     default:
1999       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2000     }
2001     return 0;
2002   }
2003   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2004 }
2005
2006
2007 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2008                                        UINT Msg,
2009                                        WPARAM wParam,
2010                                        LPARAM lParam )
2011 {
2012   static int Up = 1;
2013   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2014   if (aView.IsNull())
2015   {
2016     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2017   }
2018
2019     PAINTSTRUCT    ps;
2020
2021     switch( Msg ) {
2022     case WM_PAINT:
2023       BeginPaint(hwnd, &ps);
2024       EndPaint(hwnd, &ps);
2025       VT_ProcessExpose();
2026       break;
2027
2028     case WM_SIZE:
2029       VT_ProcessConfigure();
2030       break;
2031     case WM_MOVE:
2032     case WM_MOVING:
2033     case WM_SIZING:
2034       switch (aView->RenderingParams().StereoMode)
2035       {
2036         case Graphic3d_StereoMode_RowInterlaced:
2037         case Graphic3d_StereoMode_ColumnInterlaced:
2038         case Graphic3d_StereoMode_ChessBoard:
2039           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2040           break;
2041         default:
2042           break;
2043       }
2044       break;
2045
2046     case WM_KEYDOWN:
2047       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2048       {
2049         char c[2];
2050         c[0] = (char) wParam;
2051         c[1] = '\0';
2052         if (wParam == VK_DELETE)
2053         {
2054           c[0] = THE_KEY_DELETE;
2055         }
2056         // comma
2057         else if (wParam == VK_OEM_COMMA)
2058         {
2059           c[0] = ',';
2060         }
2061         // dot
2062         else if (wParam == VK_OEM_PERIOD)
2063         {
2064           c[0] = '.';
2065         }
2066         else if (wParam == VK_DIVIDE)
2067         {
2068           c[0] = '/';
2069         }
2070         // dot
2071         else if (wParam == VK_MULTIPLY)
2072         {
2073           c[0] = '*';
2074         }
2075         VT_ProcessKeyPress (c);
2076       }
2077       break;
2078
2079     case WM_LBUTTONUP:
2080     case WM_MBUTTONUP:
2081     case WM_RBUTTONUP:
2082       Up = 1;
2083       VT_ProcessButton3Release();
2084       break;
2085
2086     case WM_LBUTTONDOWN:
2087     case WM_MBUTTONDOWN:
2088     case WM_RBUTTONDOWN:
2089       {
2090         WPARAM fwKeys = wParam;
2091
2092         Up = 0;
2093
2094         X_ButtonPress = LOWORD(lParam);
2095         Y_ButtonPress = HIWORD(lParam);
2096
2097         if (Msg == WM_LBUTTONDOWN)
2098         {
2099           if ((fwKeys & MK_CONTROL) != 0)
2100           {
2101             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2102           }
2103           else
2104           {
2105             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2106           }
2107         }
2108         else if (Msg == WM_RBUTTONDOWN)
2109         {
2110           // Start rotation
2111           VT_ProcessButton3Press();
2112         }
2113       }
2114       break;
2115
2116     case WM_MOUSEWHEEL:
2117     {
2118       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2119       if (wParam & MK_CONTROL)
2120       {
2121         if (aView->Camera()->IsStereo())
2122         {
2123           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2124           if (aFocus > 0.2
2125            && aFocus < 2.0)
2126           {
2127             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2128             aView->Redraw();
2129           }
2130         }
2131       }
2132       else
2133       {
2134         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2135       }
2136       break;
2137     }
2138
2139     case WM_MOUSEMOVE:
2140       {
2141         //cout << "\t WM_MOUSEMOVE" << endl;
2142         WPARAM fwKeys = wParam;
2143         X_Motion = LOWORD(lParam);
2144         Y_Motion = HIWORD(lParam);
2145
2146         if ( Up &&
2147           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2148           {
2149             Up = 0;
2150             X_ButtonPress = LOWORD(lParam);
2151             Y_ButtonPress = HIWORD(lParam);
2152
2153             if ((fwKeys & MK_RBUTTON) != 0) {
2154               // Start rotation
2155               VT_ProcessButton3Press();
2156             }
2157           }
2158
2159           if ((fwKeys & MK_CONTROL) != 0)
2160           {
2161             if ((fwKeys & MK_LBUTTON) != 0)
2162             {
2163               ProcessControlButton1Motion();
2164             }
2165             else if ((fwKeys & MK_MBUTTON) != 0
2166                  || ((fwKeys & MK_LBUTTON) != 0
2167                   && (fwKeys & MK_RBUTTON) != 0))
2168             {
2169               VT_ProcessControlButton2Motion();
2170             }
2171             else if ((fwKeys & MK_RBUTTON) != 0)
2172             {
2173               VT_ProcessControlButton3Motion();
2174             }
2175           }
2176           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2177           {
2178             VT_ProcessMotion();
2179           }
2180       }
2181       break;
2182
2183     default:
2184       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2185     }
2186     return 0L;
2187 }
2188
2189 //==============================================================================
2190 //function : ViewerMainLoop
2191 //purpose  : Get a Event on the view and dispatch it
2192 //==============================================================================
2193
2194
2195 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2196 {
2197   Ppick = (argc > 0)? 1 : 0;
2198   Pargc = argc;
2199   Pargv = argv;
2200
2201   if ( Ppick ) {
2202     MSG msg;
2203     msg.wParam = 1;
2204
2205     cout << "Start picking" << endl;
2206
2207     while ( Ppick == 1 ) {
2208       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2209       if (GetMessageW (&msg, NULL, 0, 0))
2210       {
2211         TranslateMessage (&msg);
2212         DispatchMessageW (&msg);
2213       }
2214     }
2215
2216     cout << "Picking done" << endl;
2217   }
2218
2219   return Ppick;
2220 }
2221
2222 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2223
2224 int min( int a, int b )
2225 {
2226   if( a<b )
2227     return a;
2228   else
2229     return b;
2230 }
2231
2232 int max( int a, int b )
2233 {
2234   if( a>b )
2235     return a;
2236   else
2237     return b;
2238 }
2239
2240 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2241
2242 {
2243   static XEvent aReport;
2244   Standard_Boolean pick = argc > 0;
2245   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2246   XNextEvent (aDisplay, &aReport);
2247
2248   // Handle event for the chosen display connection
2249   switch (aReport.type) {
2250       case ClientMessage:
2251         {
2252           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2253           {
2254             // Close the window
2255             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2256           }
2257         }
2258         return 0;
2259      case FocusIn:
2260       {
2261          // Activate inactive view
2262          Window aWindow = GetWindowHandle(VT_GetWindow());
2263          if(aWindow != aReport.xfocus.window)
2264          {
2265            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2266          }
2267       }
2268       break;
2269       case Expose:
2270         {
2271           VT_ProcessExpose();
2272         }
2273         break;
2274       case ConfigureNotify:
2275         {
2276           VT_ProcessConfigure();
2277         }
2278         break;
2279       case KeyPress:
2280         {
2281
2282           KeySym ks_ret ;
2283           char buf_ret[11] ;
2284           int ret_len ;
2285           XComposeStatus status_in_out;
2286
2287           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2288             (char *) buf_ret , 10 ,
2289             &ks_ret , &status_in_out ) ;
2290
2291
2292           buf_ret[ret_len] = '\0' ;
2293
2294           if (ret_len)
2295           {
2296             VT_ProcessKeyPress (buf_ret);
2297           }
2298         }
2299         break;
2300       case ButtonPress:
2301         {
2302           X_ButtonPress = aReport.xbutton.x;
2303           Y_ButtonPress = aReport.xbutton.y;
2304
2305           if (aReport.xbutton.button == Button1)
2306           {
2307             if (aReport.xbutton.state & ControlMask)
2308             {
2309               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2310             }
2311             else
2312             {
2313               IsDragged = Standard_True;
2314               DragFirst = Standard_True;
2315             }
2316           }
2317           else if (aReport.xbutton.button == Button3)
2318           {
2319             // Start rotation
2320             VT_ProcessButton3Press();
2321           }
2322         }
2323         break;
2324       case ButtonRelease:
2325         {
2326           if( IsDragged )
2327           {
2328             if( !DragFirst )
2329             {
2330               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2331               {
2332                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2333                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2334               }
2335             }
2336
2337             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2338             if( aContext.IsNull() )
2339             {
2340               cout << "The context is null. Please use vinit before createmesh" << endl;
2341               return 0;
2342             }
2343
2344             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2345             if( aReport.xbutton.button==1 )
2346               if( DragFirst )
2347                 if( ShiftPressed )
2348                 {
2349                   aContext->ShiftSelect (Standard_True);
2350                 }
2351                 else
2352                 {
2353                   aContext->Select (Standard_True);
2354                 }
2355               else
2356                 if( ShiftPressed )
2357                 {
2358                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2359                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2360                                         ViewerTest::CurrentView(), Standard_True);
2361                 }
2362                 else
2363                 {
2364                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2365                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2366                                    ViewerTest::CurrentView(), Standard_True);
2367                 }
2368             else
2369               VT_ProcessButton3Release();
2370
2371             IsDragged = Standard_False;
2372           }
2373           else
2374             VT_ProcessButton3Release();
2375         }
2376         break;
2377       case MotionNotify:
2378         {
2379           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2380           {
2381             break;
2382           }
2383           if( IsDragged )
2384           {
2385             if( !DragFirst )
2386             {
2387               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2388               {
2389                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2390               }
2391             }
2392
2393             X_Motion = aReport.xmotion.x;
2394             Y_Motion = aReport.xmotion.y;
2395             DragFirst = Standard_False;
2396
2397             Window aWindow = GetWindowHandle(VT_GetWindow());
2398             Window aRoot;
2399             int anX, anY;
2400             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2401             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2402             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2403             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2404             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2405           }
2406           else
2407           {
2408             X_Motion = aReport.xmotion.x;
2409             Y_Motion = aReport.xmotion.y;
2410
2411             // remove all the ButtonMotionMaskr
2412             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2413
2414             if ( aReport.xmotion.state & ControlMask ) {
2415               if ( aReport.xmotion.state & Button1Mask ) {
2416                 ProcessControlButton1Motion();
2417               }
2418               else if ( aReport.xmotion.state & Button2Mask ) {
2419                 VT_ProcessControlButton2Motion();
2420               }
2421               else if ( aReport.xmotion.state & Button3Mask ) {
2422                 VT_ProcessControlButton3Motion();
2423               }
2424             }
2425             else
2426             {
2427               VT_ProcessMotion();
2428             }
2429           }
2430         }
2431         break;
2432 }
2433 return pick;
2434 }
2435
2436 //==============================================================================
2437 //function : VProcessEvents
2438 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2439 //       event in the Viewer window
2440 //==============================================================================
2441
2442 static void VProcessEvents(ClientData,int)
2443 {
2444   NCollection_Vector<int> anEventNumbers;
2445   // Get number of messages from every display
2446   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2447        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2448   {
2449     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2450   }
2451     // Handle events for every display
2452   int anEventIter = 0;
2453   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2454        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2455   {
2456     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2457          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2458     {
2459       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2460       int anEventResult = ViewerMainLoop( 0, NULL);
2461       // If window is closed or context was not found finish current event processing loop
2462       if (!anEventResult)
2463         return;
2464     }
2465   }
2466
2467   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2468
2469 }
2470 #endif
2471
2472 //==============================================================================
2473 //function : OSWindowSetup
2474 //purpose  : Setup for the X11 window to be able to cath the event
2475 //==============================================================================
2476
2477
2478 static void OSWindowSetup()
2479 {
2480 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2481   // X11
2482
2483   Window  window   = VT_GetWindow()->XWindow();
2484   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2485   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2486   XSynchronize(aDisplay, 1);
2487
2488   // X11 : For keyboard on SUN
2489   XWMHints wmhints;
2490   wmhints.flags = InputHint;
2491   wmhints.input = 1;
2492
2493   XSetWMHints( aDisplay, window, &wmhints);
2494
2495   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2496     ButtonPressMask | ButtonReleaseMask |
2497     StructureNotifyMask |
2498     PointerMotionMask |
2499     Button1MotionMask | Button2MotionMask |
2500     Button3MotionMask | FocusChangeMask
2501     );
2502   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2503   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2504
2505   XSynchronize(aDisplay, 0);
2506
2507 #else
2508   // _WIN32
2509 #endif
2510
2511 }
2512
2513 //==============================================================================
2514 //function : VFit
2515 //purpose  :
2516 //==============================================================================
2517
2518 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2519 {
2520   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2521   if (aView.IsNull())
2522   {
2523     std::cout << "Error: no active viewer!\n";
2524     return 1;
2525   }
2526
2527   Standard_Boolean toFit = Standard_True;
2528   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2529   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2530   {
2531     TCollection_AsciiString anArg (theArgv[anArgIter]);
2532     anArg.LowerCase();
2533     if (anUpdateTool.parseRedrawMode (anArg))
2534     {
2535       continue;
2536     }
2537     else if (anArg == "-selected")
2538     {
2539       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2540       toFit = Standard_False;
2541     }
2542     else
2543     {
2544       std::cout << "Syntax error at '" << anArg << "'\n";
2545     }
2546   }
2547
2548   if (toFit)
2549   {
2550     aView->FitAll (0.01, Standard_False);
2551   }
2552   return 0;
2553 }
2554
2555 //=======================================================================
2556 //function : VFitArea
2557 //purpose  : Fit view to show area located between two points
2558 //         : given in world 2D or 3D coordinates.
2559 //=======================================================================
2560 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2561 {
2562   Handle(V3d_View) aView = ViewerTest::CurrentView();
2563   if (aView.IsNull())
2564   {
2565     std::cerr << theArgVec[0] << "Error: No active view.\n";
2566     return 1;
2567   }
2568
2569   // Parse arguments.
2570   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2571   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2572
2573   if (theArgNb == 5)
2574   {
2575     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2576     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2577     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2578     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2579   }
2580   else if (theArgNb == 7)
2581   {
2582     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2583     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2584     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2585     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2586     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2587     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2588   }
2589   else
2590   {
2591     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2592     theDI.PrintHelp(theArgVec[0]);
2593     return 1;
2594   }
2595
2596   // Convert model coordinates to view space
2597   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2598   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2599   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2600
2601   // Determine fit area
2602   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2603   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2604
2605   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2606
2607   if (aDiagonal < Precision::Confusion())
2608   {
2609     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2610     return 1;
2611   }
2612
2613   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2614   return 0;
2615 }
2616
2617 //==============================================================================
2618 //function : VZFit
2619 //purpose  : ZFitall, no DRAW arguments
2620 //Draw arg : No args
2621 //==============================================================================
2622 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2623 {
2624   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2625
2626   if (aCurrentView.IsNull())
2627   {
2628     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2629     return 1;
2630   }
2631
2632   if (theArgsNb == 1)
2633   {
2634     aCurrentView->ZFitAll();
2635     aCurrentView->Redraw();
2636     return 0;
2637   }
2638
2639   Standard_Real aScale = 1.0;
2640
2641   if (theArgsNb >= 2)
2642   {
2643     aScale = Draw::Atoi (theArgVec[1]);
2644   }
2645
2646   aCurrentView->ZFitAll (aScale);
2647   aCurrentView->Redraw();
2648
2649   return 0;
2650 }
2651
2652 //==============================================================================
2653 //function : VRepaint
2654 //purpose  :
2655 //==============================================================================
2656 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2657 {
2658   Handle(V3d_View) aView = ViewerTest::CurrentView();
2659   if (aView.IsNull())
2660   {
2661     std::cout << "Error: no active viewer!\n";
2662     return 1;
2663   }
2664
2665   Standard_Boolean isImmediateUpdate = Standard_False;
2666   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2667   {
2668     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2669     anArg.LowerCase();
2670     if (anArg == "-immediate")
2671     {
2672       isImmediateUpdate = Standard_True;
2673       if (anArgIter + 1 < theArgNb
2674        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2675       {
2676         ++anArgIter;
2677       }
2678     }
2679     else
2680     {
2681       std::cout << "Syntax error at '" << anArg << "'\n";
2682     }
2683   }
2684
2685   if (isImmediateUpdate)
2686   {
2687     aView->RedrawImmediate();
2688   }
2689   else
2690   {
2691     aView->Redraw();
2692   }
2693   return 0;
2694 }
2695
2696 //==============================================================================
2697 //function : VClear
2698 //purpose  : Remove all the object from the viewer
2699 //Draw arg : No args
2700 //==============================================================================
2701
2702 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2703 {
2704   Handle(V3d_View) V = ViewerTest::CurrentView();
2705   if(!V.IsNull())
2706     ViewerTest::Clear();
2707   return 0;
2708 }
2709
2710 //==============================================================================
2711 //function : VPick
2712 //purpose  :
2713 //==============================================================================
2714
2715 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2716 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2717
2718 if ( argc < 4 ) {
2719   di << argv[0] << "Invalid number of arguments\n";
2720   return 1;
2721 }
2722
2723 while (ViewerMainLoop( argc, argv)) {
2724 }
2725
2726 return 0;
2727 }
2728
2729 //==============================================================================
2730 //function : VSetBg
2731 //purpose  : Load image as background
2732 //==============================================================================
2733
2734 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2735 {
2736   if (argc < 2 || argc > 3)
2737   {
2738     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2739     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2740     return 1;
2741   }
2742
2743   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2744   if(AISContext.IsNull())
2745   {
2746     di << "use 'vinit' command before " << argv[0] << "\n";
2747     return 1;
2748   }
2749
2750   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2751   if (argc == 3)
2752   {
2753     const char* szType = argv[2];
2754     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2755     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2756     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2757     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2758     else
2759     {
2760       di << "Wrong fill type : " << szType << "\n";
2761       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2762       return 1;
2763     }
2764   }
2765
2766   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2767   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2768
2769   return 0;
2770 }
2771
2772 //==============================================================================
2773 //function : VSetBgMode
2774 //purpose  : Change background image fill type
2775 //==============================================================================
2776
2777 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2778 {
2779   if (argc != 2)
2780   {
2781     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2782     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2783     return 1;
2784   }
2785
2786   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2787   if(AISContext.IsNull())
2788   {
2789     di << "use 'vinit' command before " << argv[0] << "\n";
2790     return 1;
2791   }
2792   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2793   const char* szType = argv[1];
2794   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2795   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2796   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2797   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2798   else
2799   {
2800     di << "Wrong fill type : " << szType << "\n";
2801     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2802     return 1;
2803   }
2804   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2805   V3dView->SetBgImageStyle(aFillType, Standard_True);
2806   return 0;
2807 }
2808
2809 //==============================================================================
2810 //function : VSetGradientBg
2811 //purpose  : Mount gradient background
2812 //==============================================================================
2813 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2814 {
2815   if (argc != 8 )
2816   {
2817     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2818     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2819     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2820     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2821     return 1;
2822   }
2823
2824   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2825   if(AISContext.IsNull())
2826   {
2827     di << "use 'vinit' command before " << argv[0] << "\n";
2828     return 1;
2829   }
2830   if (argc == 8)
2831   {
2832
2833     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2834     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2835     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2836     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2837
2838     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2839     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2840     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2841
2842     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2843     int aType = Draw::Atoi(argv[7]);
2844     if( aType < 0 || aType > 8 )
2845     {
2846       di << "Wrong fill type \n";
2847       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2848       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2849       return 1;
2850     }
2851
2852     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2853
2854     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2855     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2856   }
2857
2858   return 0;
2859 }
2860
2861 //==============================================================================
2862 //function : VSetGradientBgMode
2863 //purpose  : Change gradient background fill style
2864 //==============================================================================
2865 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2866 {
2867   if (argc != 2 )
2868   {
2869     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2870     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2871     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2872     return 1;
2873   }
2874
2875   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2876   if(AISContext.IsNull())
2877   {
2878     di << "use 'vinit' command before " << argv[0] << "\n";
2879     return 1;
2880   }
2881   if (argc == 2)
2882   {
2883     int aType = Draw::Atoi(argv[1]);
2884     if( aType < 0 || aType > 8 )
2885     {
2886       di << "Wrong fill type \n";
2887       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2888       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2889       return 1;
2890     }
2891
2892     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2893
2894     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2895     V3dView->SetBgGradientStyle( aMethod, 1 );
2896   }
2897
2898   return 0;
2899 }
2900
2901 //==============================================================================
2902 //function : VSetColorBg
2903 //purpose  : Set color background
2904 //==============================================================================
2905 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2906 {
2907   if (argc != 4 )
2908   {
2909     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2910     di << "R,G,B = [0..255]\n";
2911     return 1;
2912   }
2913
2914   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2915   if(AISContext.IsNull())
2916   {
2917     di << "use 'vinit' command before " << argv[0] << "\n";
2918     return 1;
2919   }
2920   if (argc == 4)
2921   {
2922
2923     Standard_Real R = Draw::Atof(argv[1])/255.;
2924     Standard_Real G = Draw::Atof(argv[2])/255.;
2925     Standard_Real B = Draw::Atof(argv[3])/255.;
2926     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2927
2928     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2929     V3dView->SetBackgroundColor( aColor );
2930     V3dView->Update();
2931   }
2932
2933   return 0;
2934 }
2935
2936 //==============================================================================
2937 //function : VSetDefaultBg
2938 //purpose  : Set default viewer background fill color
2939 //==============================================================================
2940 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2941 {
2942   if (theArgNb != 4
2943    && theArgNb != 8)
2944   {
2945     std::cout << "Error: wrong syntax! See usage:\n";
2946     theDI.PrintHelp (theArgVec[0]);
2947     return 1;
2948   }
2949
2950   ViewerTest_DefaultBackground.FillMethod =
2951     theArgNb == 4 ? Aspect_GFM_NONE
2952                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2953
2954   if (theArgNb == 4)
2955   {
2956     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2957     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2958     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2959     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2960   }
2961   else
2962   {
2963     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2964     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2965     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2966     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2967
2968     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2969     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2970     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2971     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2972   }
2973
2974   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2975        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2976   {
2977     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2978     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2979     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2980                                          ViewerTest_DefaultBackground.GradientColor2,
2981                                          ViewerTest_DefaultBackground.FillMethod);
2982   }
2983
2984   return 0;
2985 }
2986
2987 //==============================================================================
2988 //function : VScale
2989 //purpose  : View Scaling
2990 //==============================================================================
2991
2992 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2993 {
2994   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2995   if ( V3dView.IsNull() ) return 1;
2996
2997   if ( argc != 4 ) {
2998     di << argv[0] << "Invalid number of arguments\n";
2999     return 1;
3000   }
3001   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3002   return 0;
3003 }
3004 //==============================================================================
3005 //function : VZBuffTrihedron
3006 //purpose  :
3007 //==============================================================================
3008
3009 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3010                             Standard_Integer  theArgNb,
3011                             const char**      theArgVec)
3012 {
3013   Handle(V3d_View) aView = ViewerTest::CurrentView();
3014   if (aView.IsNull())
3015   {
3016     std::cout << "Error: no active viewer!\n";
3017     return 1;
3018   }
3019
3020   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3021
3022   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3023   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3024   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3025   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3026   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3027   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3028   Standard_Real                 aScale        = 0.1;
3029   Standard_Real                 aSizeRatio    = 0.8;
3030   Standard_Real                 anArrowDiam   = 0.05;
3031   Standard_Integer              aNbFacets     = 12;
3032   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3033   {
3034     Standard_CString        anArg = theArgVec[anArgIter];
3035     TCollection_AsciiString aFlag (anArg);
3036     aFlag.LowerCase();
3037     if (anUpdateTool.parseRedrawMode (aFlag))
3038     {
3039       continue;
3040     }
3041     else if (aFlag == "-on")
3042     {
3043       continue;
3044     }
3045     else if (aFlag == "-off")
3046     {
3047       aView->TriedronErase();
3048       return 0;
3049     }
3050     else if (aFlag == "-pos"
3051           || aFlag == "-position"
3052           || aFlag == "-corner")
3053     {
3054       if (++anArgIter >= theArgNb)
3055       {
3056         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3057         return 1;
3058       }
3059
3060       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3061       aPosName.LowerCase();
3062       if (aPosName == "center")
3063       {
3064         aPosition = Aspect_TOTP_CENTER;
3065       }
3066       else if (aPosName == "left_lower"
3067             || aPosName == "lower_left"
3068             || aPosName == "leftlower"
3069             || aPosName == "lowerleft")
3070       {
3071         aPosition = Aspect_TOTP_LEFT_LOWER;
3072       }
3073       else if (aPosName == "left_upper"
3074             || aPosName == "upper_left"
3075             || aPosName == "leftupper"
3076             || aPosName == "upperleft")
3077       {
3078         aPosition = Aspect_TOTP_LEFT_UPPER;
3079       }
3080       else if (aPosName == "right_lower"
3081             || aPosName == "lower_right"
3082             || aPosName == "rightlower"
3083             || aPosName == "lowerright")
3084       {
3085         aPosition = Aspect_TOTP_RIGHT_LOWER;
3086       }
3087       else if (aPosName == "right_upper"
3088             || aPosName == "upper_right"
3089             || aPosName == "rightupper"
3090             || aPosName == "upperright")
3091       {
3092         aPosition = Aspect_TOTP_RIGHT_UPPER;
3093       }
3094       else
3095       {
3096         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3097         return 1;
3098       }
3099     }
3100     else if (aFlag == "-type")
3101     {
3102       if (++anArgIter >= theArgNb)
3103       {
3104         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3105         return 1;
3106       }
3107
3108       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3109       aTypeName.LowerCase();
3110       if (aTypeName == "wireframe"
3111        || aTypeName == "wire")
3112       {
3113         aVisType = V3d_WIREFRAME;
3114       }
3115       else if (aTypeName == "zbuffer"
3116             || aTypeName == "shaded")
3117       {
3118         aVisType = V3d_ZBUFFER;
3119       }
3120       else
3121       {
3122         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3123       }
3124     }
3125     else if (aFlag == "-scale")
3126     {
3127       if (++anArgIter >= theArgNb)
3128       {
3129         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3130         return 1;
3131       }
3132
3133       aScale = Draw::Atof (theArgVec[anArgIter]);
3134     }
3135     else if (aFlag == "-size"
3136           || aFlag == "-sizeratio")
3137     {
3138       if (++anArgIter >= theArgNb)
3139       {
3140         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3141         return 1;
3142       }
3143
3144       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3145     }
3146     else if (aFlag == "-arrowdiam"
3147           || aFlag == "-arrowdiameter")
3148     {
3149       if (++anArgIter >= theArgNb)
3150       {
3151         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3152         return 1;
3153       }
3154
3155       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3156     }
3157     else if (aFlag == "-nbfacets")
3158     {
3159       if (++anArgIter >= theArgNb)
3160       {
3161         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3162         return 1;
3163       }
3164
3165       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3166     }
3167     else if (aFlag == "-colorlabel"
3168           || aFlag == "-colorlabels")
3169     {
3170       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3171                                                            theArgVec + anArgIter + 1,
3172                                                            aLabelsColor);
3173       if (aNbParsed == 0)
3174       {
3175         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3176         return 1;
3177       }
3178       anArgIter += aNbParsed;
3179     }
3180     else if (aFlag == "-colorarrowx")
3181     {
3182       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3183                                                            theArgVec + anArgIter + 1,
3184                                                            anArrowColorX);
3185       if (aNbParsed == 0)
3186       {
3187         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3188         return 1;
3189       }
3190       anArgIter += aNbParsed;
3191     }
3192     else if (aFlag == "-colorarrowy")
3193     {
3194       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3195                                                            theArgVec + anArgIter + 1,
3196                                                            anArrowColorY);
3197       if (aNbParsed == 0)
3198       {
3199         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3200         return 1;
3201       }
3202       anArgIter += aNbParsed;
3203     }
3204     else if (aFlag == "-colorarrowz")
3205     {
3206       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3207                                                            theArgVec + anArgIter + 1,
3208                                                            anArrowColorZ);
3209       if (aNbParsed == 0)
3210       {
3211         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3212         return 1;
3213       }
3214       anArgIter += aNbParsed;
3215     }
3216     else
3217     {
3218       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3219       return 1;
3220     }
3221   }
3222
3223   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3224                                aSizeRatio, anArrowDiam, aNbFacets);
3225   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3226   aView->ZFitAll();
3227   return 0;
3228 }
3229
3230 //==============================================================================
3231 //function : VRotate
3232 //purpose  : Camera Rotating
3233 //==============================================================================
3234
3235 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3236 {
3237   Handle(V3d_View) aView = ViewerTest::CurrentView();
3238   if (aView.IsNull())
3239   {
3240     std::cout << "No active view!\n";
3241     return 1;
3242   }
3243
3244   Standard_Boolean hasFlags = Standard_False;
3245   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3246   {
3247     Standard_CString        anArg (theArgVec[anArgIter]);
3248     TCollection_AsciiString aFlag (anArg);
3249     aFlag.LowerCase();
3250     if (aFlag == "-mousestart"
3251      || aFlag == "-mousefrom")
3252     {
3253       hasFlags = Standard_True;
3254       if (anArgIter + 2 >= theArgNb)
3255       {
3256         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3257         return 1;
3258       }
3259
3260       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3261       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3262       aView->StartRotation (anX, anY);
3263     }
3264     else if (aFlag == "-mousemove")
3265     {
3266       hasFlags = Standard_True;
3267       if (anArgIter + 2 >= theArgNb)
3268       {
3269         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3270         return 1;
3271       }
3272
3273       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3274       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3275       aView->Rotation (anX, anY);
3276     }
3277     else if (theArgNb != 4
3278           && theArgNb != 7)
3279     {
3280       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3281       return 1;
3282     }
3283   }
3284
3285   if (hasFlags)
3286   {
3287     return 0;
3288   }
3289   else if (theArgNb == 4)
3290   {
3291     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3292     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3293     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3294     aView->Rotate (anAX, anAY, anAZ);
3295     return 0;
3296   }
3297   else if (theArgNb == 7)
3298   {
3299     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3300     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3301     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3302
3303     Standard_Real anX = Draw::Atof (theArgVec[4]);
3304     Standard_Real anY = Draw::Atof (theArgVec[5]);
3305     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3306
3307     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3308     return 0;
3309   }
3310
3311   std::cout << "Error: Invalid number of arguments\n";
3312   return 1;
3313 }
3314
3315 //==============================================================================
3316 //function : VZoom
3317 //purpose  : View zoom in / out (relative to current zoom)
3318 //==============================================================================
3319
3320 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3321   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3322   if ( V3dView.IsNull() ) {
3323     return 1;
3324   }
3325
3326   if ( argc == 2 ) {
3327     Standard_Real coef = Draw::Atof(argv[1]);
3328     if ( coef <= 0.0 ) {
3329       di << argv[1] << "Invalid value\n";
3330       return 1;
3331     }
3332     V3dView->SetZoom( Draw::Atof(argv[1]) );
3333     return 0;
3334   } else {
3335     di << argv[0] << " Invalid number of arguments\n";
3336     return 1;
3337   }
3338 }
3339
3340 //==============================================================================
3341 //function : VPan
3342 //purpose  : View panning (in pixels)
3343 //==============================================================================
3344
3345 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3346   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3347   if ( V3dView.IsNull() ) return 1;
3348
3349   if ( argc == 3 ) {
3350     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3351     return 0;
3352   } else {
3353     di << argv[0] << " Invalid number of arguments\n";
3354     return 1;
3355   }
3356 }
3357
3358 //==============================================================================
3359 //function : VPlace
3360 //purpose  : Place the point (in pixels) at the center of the window
3361 //==============================================================================
3362 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3363 {
3364   Handle(V3d_View) aView = ViewerTest::CurrentView();
3365   if (aView.IsNull())
3366   {
3367     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3368     return 1;
3369   }
3370
3371   if (theArgNb != 3)
3372   {
3373     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3374     return 1;
3375   }
3376
3377   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3378
3379   return 0;
3380 }
3381
3382 //==============================================================================
3383 //function : VExport
3384 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3385 //==============================================================================
3386
3387 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3388 {
3389   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3390   if (V3dView.IsNull())
3391     return 1;
3392
3393   if (argc == 1)
3394   {
3395     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3396     return 1;
3397   }
3398
3399   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3400   TCollection_AsciiString aFormatStr;
3401
3402   TCollection_AsciiString aFileName (argv[1]);
3403   Standard_Integer aLen = aFileName.Length();
3404
3405   if (argc > 2)
3406   {
3407     aFormatStr = TCollection_AsciiString (argv[2]);
3408   }
3409   else if (aLen >= 4)
3410   {
3411     if (aFileName.Value (aLen - 2) == '.')
3412     {
3413       aFormatStr = aFileName.ToCString() + aLen - 2;
3414     }
3415     else if (aFileName.Value (aLen - 3) == '.')
3416     {
3417       aFormatStr = aFileName.ToCString() + aLen - 3;
3418     }
3419     else
3420     {
3421       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3422       return 1;
3423     }
3424   }
3425   else
3426   {
3427     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3428     return 1;
3429   }
3430
3431   aFormatStr.UpperCase();
3432   if (aFormatStr == "PS")
3433     anExpFormat = Graphic3d_EF_PostScript;
3434   else if (aFormatStr == "EPS")
3435     anExpFormat = Graphic3d_EF_EnhPostScript;
3436   else if (aFormatStr == "TEX")
3437     anExpFormat = Graphic3d_EF_TEX;
3438   else if (aFormatStr == "PDF")
3439     anExpFormat = Graphic3d_EF_PDF;
3440   else if (aFormatStr == "SVG")
3441     anExpFormat = Graphic3d_EF_SVG;
3442   else if (aFormatStr == "PGF")
3443     anExpFormat = Graphic3d_EF_PGF;
3444   else if (aFormatStr == "EMF")
3445     anExpFormat = Graphic3d_EF_EMF;
3446   else
3447   {
3448     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3449     return 1;
3450   }
3451
3452   Standard_DISABLE_DEPRECATION_WARNINGS
3453   try
3454   {
3455     if (!V3dView->Export (argv[1], anExpFormat))
3456     {
3457       di << "Error: export of image to " << aFormatStr << " failed!\n";
3458     }
3459   }
3460   catch (Standard_Failure const& anException)
3461   {
3462     di << "Error: export of image to " << aFormatStr << " failed";
3463     di << " (exception: " << anException.GetMessageString() << ")";
3464   }
3465   Standard_ENABLE_DEPRECATION_WARNINGS
3466   return 0;
3467 }
3468
3469 static int VColorScale (Draw_Interpretor& theDI,
3470                         Standard_Integer  theArgNb,
3471                         const char**      theArgVec)
3472 {
3473   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3474   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3475   if (aContext.IsNull())
3476   {
3477     std::cout << "Error: no active view!\n";
3478     return 1;
3479   }
3480   if (theArgNb <= 1)
3481   {
3482     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3483     return 1;
3484   }
3485
3486   Handle(AIS_ColorScale) aColorScale;
3487   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3488   {
3489     // find existing object
3490     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3491     if (aColorScale.IsNull())
3492     {
3493       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3494       return 1;
3495     }
3496   }
3497
3498   if (theArgNb <= 2)
3499   {
3500     if (aColorScale.IsNull())
3501     {
3502       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3503       return 1;
3504     }
3505
3506     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3507           << "Min range: "            << aColorScale->GetMin() << "\n"
3508           << "Max range: "            << aColorScale->GetMax() << "\n"
3509           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3510           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3511           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3512           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3513           << "Label position: ";
3514     switch (aColorScale->GetLabelPosition())
3515     {
3516       case Aspect_TOCSP_NONE:
3517         theDI << "None\n";
3518         break;
3519       case Aspect_TOCSP_LEFT:
3520         theDI << "Left\n";
3521         break;
3522       case Aspect_TOCSP_RIGHT:
3523         theDI << "Right\n";
3524         break;
3525       case Aspect_TOCSP_CENTER:
3526         theDI << "Center\n";
3527         break;
3528     }
3529     return 0;
3530   }
3531
3532   if (aColorScale.IsNull())
3533   {
3534     aColorScale = new AIS_ColorScale();
3535     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3536     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3537   }
3538
3539   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3540   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3541   {
3542     Standard_CString        anArg = theArgVec[anArgIter];
3543     TCollection_AsciiString aFlag (anArg);
3544     aFlag.LowerCase();
3545     if (anUpdateTool.parseRedrawMode (aFlag))
3546     {
3547       continue;
3548     }
3549     else if (aFlag == "-range")
3550     {
3551       if (anArgIter + 3 >= theArgNb)
3552       {
3553         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3554         return 1;
3555       }
3556
3557       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3558       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3559       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3560       if (!aRangeMin.IsRealValue()
3561        || !aRangeMax.IsRealValue())
3562       {
3563         std::cout << "Error: the range values should be real!\n";
3564         return 1;
3565       }
3566       else if (!aNbIntervals.IsIntegerValue())
3567       {
3568         std::cout << "Error: the number of intervals should be integer!\n";
3569         return 1;
3570       }
3571
3572       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3573       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3574     }
3575     else if (aFlag == "-font")
3576     {
3577       if (anArgIter + 1 >= theArgNb)
3578       {
3579         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3580         return 1;
3581       }
3582       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3583       if (!aFontArg.IsIntegerValue())
3584       {
3585         std::cout << "Error: HeightFont value should be integer!\n";
3586         return 1;
3587       }
3588
3589       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3590       anArgIter += 1;
3591     }
3592     else if (aFlag == "-textpos")
3593     {
3594       if (anArgIter + 1 >= theArgNb)
3595       {
3596         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3597         return 1;
3598       }
3599
3600       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3601       aTextPosArg.LowerCase();
3602       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3603       if (aTextPosArg == "none")
3604       {
3605         aLabPosition = Aspect_TOCSP_NONE;
3606       }
3607       else if (aTextPosArg == "left")
3608       {
3609         aLabPosition = Aspect_TOCSP_LEFT;
3610       }
3611       else if (aTextPosArg == "right")
3612       {
3613         aLabPosition = Aspect_TOCSP_RIGHT;
3614       }
3615       else if (aTextPosArg == "center")
3616       {
3617         aLabPosition = Aspect_TOCSP_CENTER;
3618       }
3619       else
3620       {
3621         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3622         return 1;
3623       }
3624       aColorScale->SetLabelPosition (aLabPosition);
3625     }
3626     else if (aFlag == "-logarithmic"
3627           || aFlag == "-log")
3628     {
3629       if (anArgIter + 1 >= theArgNb)
3630       {
3631         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3632         return 1;
3633       }
3634
3635       Standard_Boolean IsLog;
3636       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3637       {
3638         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3639         return 1;
3640       }
3641       aColorScale->SetLogarithmic (IsLog);
3642     }
3643     else if (aFlag == "-huerange"
3644           || aFlag == "-hue")
3645     {
3646       if (anArgIter + 2 >= theArgNb)
3647       {
3648         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3649         return 1;
3650       }
3651
3652       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3653       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3654       aColorScale->SetHueRange (aHueMin, aHueMax);
3655     }
3656     else if (aFlag == "-colorrange")
3657     {
3658       Quantity_Color aColorMin, aColorMax;
3659       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3660                                                             theArgVec + (anArgIter + 1),
3661                                                             aColorMin);
3662       anArgIter += aNbParsed1;
3663       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3664                                                             theArgVec + (anArgIter + 1),
3665                                                             aColorMax);
3666       anArgIter += aNbParsed2;
3667       if (aNbParsed1 == 0
3668        || aNbParsed2 == 0)
3669       {
3670         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3671         return 1;
3672       }
3673
3674       aColorScale->SetColorRange (aColorMin, aColorMax);
3675     }
3676     else if (aFlag == "-reversed"
3677           || aFlag == "-inverted"
3678           || aFlag == "-topdown"
3679           || aFlag == "-bottomup")
3680     {
3681       Standard_Boolean toEnable = Standard_True;
3682       if (anArgIter + 1 < theArgNb
3683        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3684       {
3685         ++anArgIter;
3686       }
3687       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3688     }
3689     else if (aFlag == "-smooth"
3690           || aFlag == "-smoothtransition")
3691     {
3692       Standard_Boolean toEnable = Standard_True;
3693       if (anArgIter + 1 < theArgNb
3694        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3695       {
3696         ++anArgIter;
3697       }
3698       aColorScale->SetSmoothTransition (toEnable);
3699     }
3700     else if (aFlag == "-xy")
3701     {
3702       if (anArgIter + 2 >= theArgNb)
3703       {
3704         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3705         return 1;
3706       }
3707
3708       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3709       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3710       if (!anX.IsIntegerValue()
3711        || !anY.IsIntegerValue())
3712       {
3713         std::cout << "Error: coordinates should be integer values!\n";
3714         return 1;
3715       }
3716
3717       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3718     }
3719     else if (aFlag == "-width"
3720           || aFlag == "-w"
3721           || aFlag == "-breadth")
3722     {
3723       if (anArgIter + 1 >= theArgNb)
3724       {
3725         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3726         return 1;
3727       }
3728
3729       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3730       if (!aBreadth.IsIntegerValue())
3731       {
3732         std::cout << "Error: a width should be an integer value!\n";
3733         return 1;
3734       }
3735       aColorScale->SetBreadth (aBreadth.IntegerValue());
3736     }
3737     else if (aFlag == "-height"
3738           || aFlag == "-h")
3739     {
3740       if (anArgIter + 1 >= theArgNb)
3741       {
3742         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3743         return 1;
3744       }
3745
3746       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3747       if (!aHeight.IsIntegerValue())
3748       {
3749         std::cout << "Error: a width should be an integer value!\n";
3750         return 1;
3751       }
3752       aColorScale->SetHeight (aHeight.IntegerValue());
3753     }
3754     else if (aFlag == "-color")
3755     {
3756       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3757       {
3758         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3759         return 1;
3760       }
3761       else if (anArgIter + 2 >= theArgNb)
3762       {
3763         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3764         return 1;
3765       }
3766
3767       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3768       if (!anInd.IsIntegerValue())
3769       {
3770         std::cout << "Error: Index value should be integer!\n";
3771         return 1;
3772       }
3773       const Standard_Integer anIndex = anInd.IntegerValue();
3774       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3775       {
3776         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3777         return 1;
3778       }
3779
3780       Quantity_Color aColor;
3781       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3782                                                            theArgVec + (anArgIter + 1),
3783                                                            aColor);
3784       if (aNbParsed == 0)
3785       {
3786         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3787         return 1;
3788       }
3789       aColorScale->SetIntervalColor (aColor, anIndex);
3790       aColorScale->SetColorType (Aspect_TOCSD_USER);
3791       anArgIter += aNbParsed;
3792     }
3793     else if (aFlag == "-label")
3794     {
3795       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3796       {
3797         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3798         return 1;
3799       }
3800       else if (anArgIter + 2 >= theArgNb)
3801       {
3802         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3803         return 1;
3804       }
3805
3806       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3807       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
3808       {
3809         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
3810         return 1;
3811       }
3812
3813       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3814       aColorScale->SetLabel     (aText, anIndex);
3815       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3816       anArgIter += 2;
3817     }
3818     else if (aFlag == "-labelat"
3819           || aFlag == "-labat"
3820           || aFlag == "-labelatborder"
3821           || aFlag == "-labatborder"
3822           || aFlag == "-labelatcenter"
3823           || aFlag == "-labatcenter")
3824     {
3825       Standard_Boolean toEnable = Standard_True;
3826       if (aFlag == "-labelat"
3827        || aFlag == "-labat")
3828       {
3829         Standard_Integer aLabAtBorder = -1;
3830         if (++anArgIter >= theArgNb)
3831         {
3832           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
3833           anAtBorder.LowerCase();
3834           if (anAtBorder == "border")
3835           {
3836             aLabAtBorder = 1;
3837           }
3838           else if (anAtBorder == "center")
3839           {
3840             aLabAtBorder = 0;
3841           }
3842         }
3843         if (aLabAtBorder == -1)
3844         {
3845           std::cout << "Syntax error at argument '" << anArg << "'!\n";
3846           return 1;
3847         }
3848         toEnable = (aLabAtBorder == 1);
3849       }
3850       else if (anArgIter + 1 < theArgNb
3851             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3852       {
3853         ++anArgIter;
3854       }
3855       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
3856                                   || aFlag == "-labatcenter"
3857                                    ? !toEnable
3858                                    :  toEnable);
3859     }
3860     else if (aFlag == "-colors")
3861     {
3862       Aspect_SequenceOfColor aSeq;
3863       for (;;)
3864       {
3865         Quantity_Color aColor;
3866         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3867                                                              theArgVec + (anArgIter + 1),
3868                                                              aColor);
3869         if (aNbParsed == 0)
3870         {
3871           break;
3872         }
3873         anArgIter += aNbParsed;
3874         aSeq.Append (aColor);
3875       }
3876       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
3877       {
3878         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
3879                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
3880         return 1;
3881       }
3882
3883       aColorScale->SetColors    (aSeq);
3884       aColorScale->SetColorType (Aspect_TOCSD_USER);
3885     }
3886     else if (aFlag == "-labels"
3887           || aFlag == "-freelabels")
3888     {
3889       if (anArgIter + 1 >= theArgNb)
3890       {
3891         std::cout << "Syntax error at argument '" << anArg << "'!\n";
3892         return 1;
3893       }
3894
3895       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
3896                                  ? aColorScale->GetNumberOfIntervals() + 1
3897                                  : aColorScale->GetNumberOfIntervals();
3898       if (aFlag == "-freelabels")
3899       {
3900         ++anArgIter;
3901         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
3902       }
3903       if (anArgIter + aNbLabels >= theArgNb)
3904       {
3905         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
3906         return 1;
3907       }
3908
3909       TColStd_SequenceOfExtendedString aSeq;
3910       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
3911       {
3912         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
3913       }
3914       aColorScale->SetLabels (aSeq);
3915       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3916     }
3917     else if (aFlag == "-title")
3918     {
3919       if (anArgIter + 1 >= theArgNb)
3920       {
3921         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3922         return 1;
3923       }
3924
3925       Standard_Boolean isTwoArgs = Standard_False;
3926       if (anArgIter + 2 < theArgNb)
3927       {
3928         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
3929         aSecondArg.LowerCase();
3930       Standard_DISABLE_DEPRECATION_WARNINGS
3931         if (aSecondArg == "none")
3932         {
3933           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
3934           isTwoArgs = Standard_True;
3935         }
3936         else if (aSecondArg == "left")
3937         {
3938           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
3939           isTwoArgs = Standard_True;
3940         }
3941         else if (aSecondArg == "right")
3942         {
3943           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
3944           isTwoArgs = Standard_True;
3945         }
3946         else if (aSecondArg == "center")
3947         {
3948           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
3949           isTwoArgs = Standard_True;
3950         }
3951       Standard_ENABLE_DEPRECATION_WARNINGS
3952       }
3953
3954       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
3955       if (isTwoArgs)
3956       {
3957         anArgIter += 1;
3958       }
3959       anArgIter += 1;
3960     }
3961     else if (aFlag == "-demoversion"
3962           || aFlag == "-demo")
3963     {
3964       aColorScale->SetPosition (0, 0);
3965       aColorScale->SetTextHeight (16);
3966       aColorScale->SetRange (0.0, 100.0);
3967       aColorScale->SetNumberOfIntervals (10);
3968       aColorScale->SetBreadth (0);
3969       aColorScale->SetHeight  (0);
3970       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
3971       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
3972       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
3973     }
3974     else if (aFlag == "-findcolor")
3975     {
3976       if (anArgIter + 1 >= theArgNb)
3977       {
3978         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3979         return 1;
3980       }
3981
3982       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
3983
3984       if (!anArg1.IsRealValue())
3985       {
3986         std::cout << "Error: the value should be real!\n";
3987         return 1;
3988       }
3989
3990       Quantity_Color aColor;
3991       aColorScale->FindColor (anArg1.RealValue(), aColor);
3992       theDI << Quantity_Color::StringName (aColor.Name());
3993       return 0;
3994     }
3995     else
3996     {
3997       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
3998       return 1;
3999     }
4000   }
4001
4002   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4003   aView->Window()->Size (aWinWidth, aWinHeight);
4004   if (aColorScale->GetBreadth() == 0)
4005   {
4006     aColorScale->SetBreadth (aWinWidth);
4007   }
4008   if (aColorScale->GetHeight() == 0)
4009   {
4010     aColorScale->SetHeight (aWinHeight);
4011   }
4012   aColorScale->SetToUpdate();
4013   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4014   return 0;
4015 }
4016
4017 //==============================================================================
4018 //function : VGraduatedTrihedron
4019 //purpose  : Displays or hides a graduated trihedron
4020 //==============================================================================
4021 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4022                                   Quantity_Color& theColor)
4023 {
4024   Quantity_NameOfColor aColorName;
4025   TCollection_AsciiString aVal = theValue;
4026   aVal.UpperCase();
4027   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4028   {
4029     return Standard_False;
4030   }
4031   theColor = Quantity_Color (aColorName);
4032   return Standard_True;
4033 }
4034
4035 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4036 {
4037   if (theArgNum < 2)
4038   {
4039     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4040               << theArgs[0] <<"' for more information.\n";
4041     return 1;  //TCL_ERROR
4042   }
4043
4044   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4045   TCollection_AsciiString aParseKey;
4046   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4047   {
4048     TCollection_AsciiString anArg (theArgs [anArgIt]);
4049
4050     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4051     {
4052       aParseKey = anArg;
4053       aParseKey.Remove (1);
4054       aParseKey.LowerCase();
4055       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4056       continue;
4057     }
4058
4059     if (aParseKey.IsEmpty())
4060     {
4061       continue;
4062     }
4063
4064     aMapOfArgs(aParseKey)->Append (anArg);
4065   }
4066
4067   // Check parameters
4068   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4069        aMapIt.More(); aMapIt.Next())
4070   {
4071     const TCollection_AsciiString& aKey = aMapIt.Key();
4072     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4073
4074     // Bool key, without arguments
4075     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4076         && anArgs->IsEmpty())
4077     {
4078       continue;
4079     }
4080
4081     // One argument
4082     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4083           && anArgs->Length() == 1)
4084     {
4085       continue;
4086     }
4087
4088     // On/off arguments
4089     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4090         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4091         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4092         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4093         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4094     {
4095       continue;
4096     }
4097
4098     // One string argument
4099     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4100           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4101           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4102     {
4103       continue;
4104     }
4105
4106     // One integer argument
4107     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4108           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4109           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4110           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4111          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4112     {
4113       continue;
4114     }
4115
4116     // One real argument
4117     if ( aKey.IsEqual ("arrowlength")
4118          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4119     {
4120       continue;
4121     }
4122
4123     // Two string arguments
4124     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4125          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4126     {
4127       continue;
4128     }
4129
4130     TCollection_AsciiString aLowerKey;
4131     aLowerKey  = "-";
4132     aLowerKey += aKey;
4133     aLowerKey.LowerCase();
4134     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4135     std::cout << "Type help for more information.\n";
4136     return 1;
4137   }
4138
4139   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4140   if (anAISContext.IsNull())
4141   {
4142     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4143     return 1;
4144   }
4145
4146   Standard_Boolean toDisplay = Standard_True;
4147   Quantity_Color aColor;
4148   Graphic3d_GraduatedTrihedron aTrihedronData;
4149   // Process parameters
4150   Handle(TColStd_HSequenceOfAsciiString) aValues;
4151   if (aMapOfArgs.Find ("off", aValues))
4152   {
4153     toDisplay = Standard_False;
4154   }
4155
4156   // AXES NAMES
4157   if (aMapOfArgs.Find ("xname", aValues))
4158   {
4159     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4160   }
4161   if (aMapOfArgs.Find ("yname", aValues))
4162   {
4163     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4164   }
4165   if (aMapOfArgs.Find ("zname", aValues))
4166   {
4167     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4168   }
4169   if (aMapOfArgs.Find ("xdrawname", aValues))
4170   {
4171     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4172   }
4173   if (aMapOfArgs.Find ("ydrawname", aValues))
4174   {
4175     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4176   }
4177   if (aMapOfArgs.Find ("zdrawname", aValues))
4178   {
4179     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4180   }
4181   if (aMapOfArgs.Find ("xnameoffset", aValues))
4182   {
4183     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4184   }
4185   if (aMapOfArgs.Find ("ynameoffset", aValues))
4186   {
4187     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4188   }
4189   if (aMapOfArgs.Find ("znameoffset", aValues))
4190   {
4191     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4192   }
4193
4194   // COLORS
4195   if (aMapOfArgs.Find ("xnamecolor", aValues))
4196   {
4197     if (!GetColor (aValues->Value(1), aColor))
4198     {
4199       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4200       return 1;
4201     }
4202     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4203   }
4204   if (aMapOfArgs.Find ("ynamecolor", aValues))
4205   {
4206     if (!GetColor (aValues->Value(1), aColor))
4207     {
4208       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4209       return 1;
4210     }
4211     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4212   }
4213   if (aMapOfArgs.Find ("znamecolor", aValues))
4214   {
4215     if (!GetColor (aValues->Value(1), aColor))
4216     {
4217       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4218       return 1;
4219     }
4220     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4221   }
4222   if (aMapOfArgs.Find ("xcolor", aValues))
4223   {
4224     if (!GetColor (aValues->Value(1), aColor))
4225     {
4226       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4227       return 1;
4228     }
4229     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4230   }
4231   if (aMapOfArgs.Find ("ycolor", aValues))
4232   {
4233     if (!GetColor (aValues->Value(1), aColor))
4234     {
4235       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4236       return 1;
4237     }
4238     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4239   }
4240   if (aMapOfArgs.Find ("zcolor", aValues))
4241   {
4242     if (!GetColor (aValues->Value(1), aColor))
4243     {
4244       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4245       return 1;
4246     }
4247     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4248   }
4249
4250   // TICKMARKS
4251   if (aMapOfArgs.Find ("xticks", aValues))
4252   {
4253     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4254   }
4255   if (aMapOfArgs.Find ("yticks", aValues))
4256   {
4257     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4258   }
4259   if (aMapOfArgs.Find ("zticks", aValues))
4260   {
4261     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4262   }
4263   if (aMapOfArgs.Find ("xticklength", aValues))
4264   {
4265     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4266   }
4267   if (aMapOfArgs.Find ("yticklength", aValues))
4268   {
4269     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4270   }
4271   if (aMapOfArgs.Find ("zticklength", aValues))
4272   {
4273     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4274   }
4275   if (aMapOfArgs.Find ("xdrawticks", aValues))
4276   {
4277     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4278   }
4279   if (aMapOfArgs.Find ("ydrawticks", aValues))
4280   {
4281     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4282   }
4283   if (aMapOfArgs.Find ("zdrawticks", aValues))
4284   {
4285     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4286   }
4287
4288   // VALUES
4289   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4290   {
4291     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4292   }
4293   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4294   {
4295     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4296   }
4297   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4298   {
4299     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4300   }
4301   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4302   {
4303     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4304   }
4305   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4306   {
4307     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4308   }
4309   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4310   {
4311     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4312   }
4313
4314   // ARROWS
4315   if (aMapOfArgs.Find ("arrowlength", aValues))
4316   {
4317     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4318   }
4319
4320   // FONTS
4321   if (aMapOfArgs.Find ("namefont", aValues))
4322   {
4323     aTrihedronData.SetNamesFont (aValues->Value(1));
4324   }
4325   if (aMapOfArgs.Find ("valuesfont", aValues))
4326   {
4327     aTrihedronData.SetValuesFont (aValues->Value(1));
4328   }
4329
4330   if (aMapOfArgs.Find ("drawgrid", aValues))
4331   {
4332     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4333   }
4334   if (aMapOfArgs.Find ("drawaxes", aValues))
4335   {
4336     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4337   }
4338
4339   // The final step: display of erase trihedron
4340   if (toDisplay)
4341   {
4342     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4343   }
4344   else
4345   {
4346     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4347   }
4348
4349   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4350   ViewerTest::CurrentView()->Redraw();
4351
4352   return 0;
4353 }
4354
4355 //==============================================================================
4356 //function : VTile
4357 //purpose  :
4358 //==============================================================================
4359 static int VTile (Draw_Interpretor& theDI,
4360                   Standard_Integer  theArgNb,
4361                   const char**      theArgVec)
4362 {
4363   Handle(V3d_View) aView = ViewerTest::CurrentView();
4364   if (aView.IsNull())
4365   {
4366     std::cerr << "Error: no active viewer.\n";
4367     return 1;
4368   }
4369
4370   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4371   if (theArgNb < 2)
4372   {
4373     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4374           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4375           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4376     return 0;
4377   }
4378
4379   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4380   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4381   {
4382     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4383     anArg.LowerCase();
4384     if (anArg == "-lowerleft"
4385      || anArg == "-upperleft")
4386     {
4387       if (anArgIter + 3 < theArgNb)
4388       {
4389         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4390         return 1;
4391       }
4392       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4393       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4394       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4395     }
4396     else if (anArg == "-total"
4397           || anArg == "-totalsize"
4398           || anArg == "-viewsize")
4399     {
4400       if (anArgIter + 3 < theArgNb)
4401       {
4402         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4403         return 1;
4404       }
4405       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4406       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4407       if (aTile.TotalSize.x() < 1
4408        || aTile.TotalSize.y() < 1)
4409       {
4410         std::cerr << "Error: total size is incorrect.\n";
4411         return 1;
4412       }
4413     }
4414     else if (anArg == "-tilesize")
4415     {
4416       if (anArgIter + 3 < theArgNb)
4417       {
4418         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4419         return 1;
4420       }
4421
4422       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4423       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4424       if (aTile.TileSize.x() < 1
4425        || aTile.TileSize.y() < 1)
4426       {
4427         std::cerr << "Error: tile size is incorrect.\n";
4428         return 1;
4429       }
4430     }
4431     else if (anArg == "-unset")
4432     {
4433       aView->Camera()->SetTile (Graphic3d_CameraTile());
4434       aView->Redraw();
4435       return 0;
4436     }
4437   }
4438
4439   if (aTile.TileSize.x() < 1
4440    || aTile.TileSize.y() < 1)
4441   {
4442     std::cerr << "Error: tile size is undefined.\n";
4443     return 1;
4444   }
4445   else if (aTile.TotalSize.x() < 1
4446         || aTile.TotalSize.y() < 1)
4447   {
4448     std::cerr << "Error: total size is undefined.\n";
4449     return 1;
4450   }
4451
4452   aView->Camera()->SetTile (aTile);
4453   aView->Redraw();
4454   return 0;
4455 }
4456
4457 //! Format ZLayer ID.
4458 inline const char* formZLayerId (const Standard_Integer theLayerId)
4459 {
4460   switch (theLayerId)
4461   {
4462     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4463     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4464     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4465     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4466     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4467     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4468   }
4469   return "";
4470 }
4471
4472 //! Print the ZLayer information.
4473 inline void printZLayerInfo (Draw_Interpretor& theDI,
4474                              const Graphic3d_ZLayerSettings& theLayer)
4475 {
4476   if (!theLayer.Name().IsEmpty())
4477   {
4478     theDI << "  Name: " << theLayer.Name() << "\n";
4479   }
4480   if (theLayer.IsImmediate())
4481   {
4482     theDI << "  Immediate: TRUE\n";
4483   }
4484   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4485   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4486   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4487   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4488   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4489   {
4490     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4491   }
4492 }
4493
4494 //==============================================================================
4495 //function : VZLayer
4496 //purpose  : Test z layer operations for v3d viewer
4497 //==============================================================================
4498 static int VZLayer (Draw_Interpretor& theDI,
4499                     Standard_Integer  theArgNb,
4500                     const char**      theArgVec)
4501 {
4502   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4503   if (aContextAIS.IsNull())
4504   {
4505     std::cout << "No active viewer!\n";
4506     return 1;
4507   }
4508
4509   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4510   if (theArgNb < 2)
4511   {
4512     TColStd_SequenceOfInteger aLayers;
4513     aViewer->GetAllZLayers (aLayers);
4514     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4515     {
4516       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4517       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4518       printZLayerInfo (theDI, aSettings);
4519     }
4520     return 1;
4521   }
4522
4523   Standard_Integer anArgIter = 1;
4524   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4525   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4526   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4527   {
4528     ++anArgIter;
4529   }
4530
4531   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4532   if (aFirstArg.IsIntegerValue())
4533   {
4534     ++anArgIter;
4535     aLayerId = aFirstArg.IntegerValue();
4536   }
4537   else
4538   {
4539     aFirstArg.LowerCase();
4540     if (aFirstArg == "default"
4541      || aFirstArg == "def")
4542     {
4543       aLayerId = Graphic3d_ZLayerId_Default;
4544       ++anArgIter;
4545     }
4546     else if (aFirstArg == "top")
4547     {
4548       aLayerId = Graphic3d_ZLayerId_Top;
4549       ++anArgIter;
4550     }
4551     else if (aFirstArg == "topmost")
4552     {
4553       aLayerId = Graphic3d_ZLayerId_Topmost;
4554       ++anArgIter;
4555     }
4556     else if (aFirstArg == "overlay"
4557           || aFirstArg == "toposd")
4558     {
4559       aLayerId = Graphic3d_ZLayerId_TopOSD;
4560       ++anArgIter;
4561     }
4562     else if (aFirstArg == "underlay"
4563           || aFirstArg == "botosd")
4564     {
4565       aLayerId = Graphic3d_ZLayerId_BotOSD;
4566       ++anArgIter;
4567     }
4568     else
4569     {
4570       TColStd_SequenceOfInteger aLayers;
4571       aViewer->GetAllZLayers (aLayers);
4572       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4573       {
4574         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4575         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4576         {
4577           aLayerId = aLayeriter.Value();
4578           ++anArgIter;
4579           break;
4580         }
4581       }
4582     }
4583   }
4584
4585   for (; anArgIter < theArgNb; ++anArgIter)
4586   {
4587     // perform operation
4588     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4589     anArg.LowerCase();
4590     if (anUpdateTool.parseRedrawMode (anArg))
4591     {
4592       //
4593     }
4594     else if (anArg == "-add"
4595           || anArg == "add")
4596     {
4597       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4598       if (!aViewer->AddZLayer (aLayerId))
4599       {
4600         std::cout << "Error: can not add a new z layer!\n";
4601         return 0;
4602       }
4603
4604       theDI << aLayerId;
4605     }
4606     else if (anArg == "-del"
4607           || anArg == "-delete"
4608           || anArg == "del")
4609     {
4610       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4611       {
4612         if (++anArgIter >= theArgNb)
4613         {
4614           std::cout << "Syntax error: id of z layer to remove is missing\n";
4615           return 1;
4616         }
4617
4618         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4619       }
4620
4621       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4622        || aLayerId == Graphic3d_ZLayerId_Default
4623        || aLayerId == Graphic3d_ZLayerId_Top
4624        || aLayerId == Graphic3d_ZLayerId_Topmost
4625        || aLayerId == Graphic3d_ZLayerId_TopOSD
4626        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4627       {
4628         std::cout << "Syntax error: standard Z layer can not be removed\n";
4629         return 1;
4630       }
4631
4632       // move all object displayed in removing layer to default layer
4633       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4634            anObjIter.More(); anObjIter.Next())
4635       {
4636         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4637         if (aPrs.IsNull()
4638          || aPrs->ZLayer() != aLayerId)
4639         {
4640           continue;
4641         }
4642         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4643       }
4644
4645       if (!aViewer->RemoveZLayer (aLayerId))
4646       {
4647         std::cout << "Z layer can not be removed!\n";
4648       }
4649       else
4650       {
4651         theDI << aLayerId << " ";
4652       }
4653     }
4654     else if (anArg == "-get"
4655           || anArg == "get")
4656     {
4657       TColStd_SequenceOfInteger aLayers;
4658       aViewer->GetAllZLayers (aLayers);
4659       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4660       {
4661         theDI << aLayeriter.Value() << " ";
4662       }
4663
4664       theDI << "\n";
4665     }
4666     else if (anArg == "-name")
4667     {
4668       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4669       {
4670         std::cout << "Syntax error: id of Z layer is missing\n";
4671         return 1;
4672       }
4673
4674       if (++anArgIter >= theArgNb)
4675       {
4676         std::cout << "Syntax error: name is missing\n";
4677         return 1;
4678       }
4679
4680       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4681       aSettings.SetName (theArgVec[anArgIter]);
4682       aViewer->SetZLayerSettings (aLayerId, aSettings);
4683     }
4684     else if (anArg == "-origin")
4685     {
4686       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4687       {
4688         std::cout << "Syntax error: id of Z layer is missing\n";
4689         return 1;
4690       }
4691
4692       if (anArgIter + 2 >= theArgNb)
4693       {
4694         std::cout << "Syntax error: origin coordinates are missing\n";
4695         return 1;
4696       }
4697
4698       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4699       gp_XYZ anOrigin;
4700       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4701       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4702       anOrigin.SetZ (0.0);
4703       if (anArgIter + 3 < theArgNb)
4704       {
4705         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4706         anArgIter += 3;
4707       }
4708       else
4709       {
4710         anArgIter += 2;
4711       }
4712       aSettings.SetOrigin (anOrigin);
4713       aViewer->SetZLayerSettings (aLayerId, aSettings);
4714     }
4715     else if (anArg == "-settings"
4716           || anArg == "settings")
4717     {
4718       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4719       {
4720         if (++anArgIter >= theArgNb)
4721         {
4722           std::cout << "Syntax error: id of Z layer is missing\n";
4723           return 1;
4724         }
4725
4726         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4727       }
4728
4729       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4730       printZLayerInfo (theDI, aSettings);
4731     }
4732     else if (anArg == "-enable"
4733           || anArg == "enable"
4734           || anArg == "-disable"
4735           || anArg == "disable")
4736     {
4737       const Standard_Boolean toEnable = anArg == "-enable"
4738                                      || anArg == "enable";
4739       if (++anArgIter >= theArgNb)
4740       {
4741         std::cout << "Syntax error: option name is missing\n";
4742         return 1;
4743       }
4744
4745       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4746       aSubOp.LowerCase();
4747       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4748       {
4749         if (++anArgIter >= theArgNb)
4750         {
4751           std::cout << "Syntax error: id of Z layer is missing\n";
4752           return 1;
4753         }
4754
4755         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4756       }
4757
4758       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4759       if (aSubOp == "depthtest"
4760        || aSubOp == "test")
4761       {
4762         aSettings.SetEnableDepthTest (toEnable);
4763       }
4764       else if (aSubOp == "depthwrite"
4765             || aSubOp == "write")
4766       {
4767         aSettings.SetEnableDepthWrite (toEnable);
4768       }
4769       else if (aSubOp == "depthclear"
4770             || aSubOp == "clear")
4771       {
4772         aSettings.SetClearDepth (toEnable);
4773       }
4774       else if (aSubOp == "depthoffset"
4775             || aSubOp == "offset")
4776       {
4777         Graphic3d_PolygonOffset aParams;
4778         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4779         if (toEnable)
4780         {
4781           if (anArgIter + 2 >= theArgNb)
4782           {
4783             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4784             return 1;
4785           }
4786
4787           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4788           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4789         }
4790         aSettings.SetPolygonOffset (aParams);
4791       }
4792       else if (aSubOp == "positiveoffset"
4793             || aSubOp == "poffset")
4794       {
4795         if (toEnable)
4796         {
4797           aSettings.SetDepthOffsetPositive();
4798         }
4799         else
4800         {
4801           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4802         }
4803       }
4804       else if (aSubOp == "negativeoffset"
4805             || aSubOp == "noffset")
4806       {
4807         if (toEnable)
4808         {
4809           aSettings.SetDepthOffsetNegative();
4810         }
4811         else
4812         {
4813           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4814         }
4815       }
4816       else if (aSubOp == "textureenv")
4817       {
4818         aSettings.SetEnvironmentTexture (toEnable);
4819       }
4820
4821       aViewer->SetZLayerSettings (aLayerId, aSettings);
4822     }
4823     else
4824     {
4825       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
4826       return 1;
4827     }
4828   }
4829
4830   return 0;
4831 }
4832
4833 // The interactive presentation of 2d layer item
4834 // for "vlayerline" command it provides a presentation of
4835 // line with user-defined linewidth, linetype and transparency.
4836 class V3d_LineItem : public AIS_InteractiveObject
4837 {
4838 public:
4839   // CASCADE RTTI
4840   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4841
4842   // constructor
4843   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4844                                Standard_Real X2, Standard_Real Y2,
4845                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
4846                                Standard_Real theWidth    = 0.5,
4847                                Standard_Real theTransp   = 1.0);
4848
4849   private:
4850
4851   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
4852                 const Handle(Prs3d_Presentation)& thePresentation,
4853                 const Standard_Integer theMode) Standard_OVERRIDE;
4854
4855   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
4856                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
4857   {}
4858
4859 private:
4860
4861   Standard_Real       myX1, myY1, myX2, myY2;
4862   Aspect_TypeOfLine   myType;
4863   Standard_Real       myWidth;
4864 };
4865
4866 // default constructor for line item
4867 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
4868                            Standard_Real X2, Standard_Real Y2,
4869                            Aspect_TypeOfLine theType,
4870                            Standard_Real theWidth,
4871                            Standard_Real theTransp) :
4872   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
4873   myType(theType), myWidth(theWidth)
4874 {
4875   SetTransparency (1-theTransp);
4876 }
4877
4878 // render line
4879 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
4880                             const Handle(Prs3d_Presentation)& thePresentation,
4881                             const Standard_Integer /*theMode*/)
4882 {
4883   thePresentation->Clear();
4884   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
4885   Standard_Integer aWidth, aHeight;
4886   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
4887   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
4888   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
4889   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
4890   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
4891   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
4892   aGroup->SetPrimitivesAspect (anAspect->Aspect());
4893   aGroup->AddPrimitiveArray (aPrim);
4894 }
4895
4896 //=============================================================================
4897 //function : VLayerLine
4898 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
4899 //         : linewidth, transparency coefficient
4900 //============================================================================
4901 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4902 {
4903   // get the active view
4904   Handle(V3d_View) aView = ViewerTest::CurrentView();
4905   if (aView.IsNull())
4906   {
4907     di << "Call vinit before!\n";
4908     return 1;
4909   }
4910   else if (argc < 5)
4911   {
4912     di << "Use: " << argv[0];
4913     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
4914     di << " linetype : { 0 | 1 | 2 | 3 } \n";
4915     di << "              0 - solid  \n";
4916     di << "              1 - dashed \n";
4917     di << "              2 - dot    \n";
4918     di << "              3 - dashdot\n";
4919     di << " transparency : { 0.0 - 1.0 } \n";
4920     di << "                  0.0 - transparent\n";
4921     di << "                  1.0 - visible    \n";
4922     return 1;
4923   }
4924
4925   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4926   // get the input params
4927   Standard_Real X1 = Draw::Atof(argv[1]);
4928   Standard_Real Y1 = Draw::Atof(argv[2]);
4929   Standard_Real X2 = Draw::Atof(argv[3]);
4930   Standard_Real Y2 = Draw::Atof(argv[4]);
4931
4932   Standard_Real aWidth = 0.5;
4933   Standard_Real aTransparency = 1.0;
4934
4935   // has width
4936   if (argc > 5)
4937     aWidth = Draw::Atof(argv[5]);
4938
4939   // select appropriate line type
4940   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
4941   if (argc > 6
4942   && !ViewerTest::ParseLineType (argv[6], aLineType))
4943   {
4944     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
4945     return 1;
4946   }
4947
4948   // has transparency
4949   if (argc > 7)
4950   {
4951     aTransparency = Draw::Atof(argv[7]);
4952     if (aTransparency < 0 || aTransparency > 1.0)
4953       aTransparency = 1.0;
4954   }
4955
4956   static Handle (V3d_LineItem) aLine;
4957   if (!aLine.IsNull())
4958   {
4959     aContext->Erase (aLine, Standard_False);
4960   }
4961   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
4962                             aLineType, aWidth,
4963                             aTransparency);
4964
4965   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4966   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4967   aLine->SetToUpdate();
4968   aContext->Display (aLine, Standard_True);
4969
4970   return 0;
4971 }
4972
4973
4974 //==============================================================================
4975 //function : VGrid
4976 //purpose  :
4977 //==============================================================================
4978
4979 static int VGrid (Draw_Interpretor& /*theDI*/,
4980                   Standard_Integer  theArgNb,
4981                   const char**      theArgVec)
4982 {
4983   // get the active view
4984   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
4985   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
4986   if (aView.IsNull() || aViewer.IsNull())
4987   {
4988     std::cerr << "No active view. Please call vinit.\n";
4989     return 1;
4990   }
4991
4992   Aspect_GridType     aType = aViewer->GridType();
4993   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
4994   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4995   Standard_Integer anIter = 1;
4996   for (; anIter < theArgNb; ++anIter)
4997   {
4998     const char* aValue = theArgVec[anIter];
4999     if (anUpdateTool.parseRedrawMode (aValue))
5000     {
5001       continue;
5002     }
5003     else if (*aValue == 'r')
5004     {
5005       aType = Aspect_GT_Rectangular;
5006     }
5007     else if (*aValue == 'c')
5008     {
5009       aType = Aspect_GT_Circular;
5010     }
5011     else if (*aValue == 'l')
5012     {
5013       aMode = Aspect_GDM_Lines;
5014     }
5015     else if (*aValue == 'p')
5016     {
5017       aMode = Aspect_GDM_Points;
5018     }
5019     else if (strcmp (aValue, "off" ) == 0)
5020     {
5021       aViewer->DeactivateGrid();
5022       return 0;
5023     }
5024     else
5025     {
5026       break;
5027     }
5028   }
5029
5030   Standard_Integer aTail = (theArgNb - anIter);
5031   if (aTail == 0)
5032   {
5033     aViewer->ActivateGrid (aType, aMode);
5034     return 0;
5035   }
5036   else if (aTail != 2 && aTail != 5)
5037   {
5038     std::cerr << "Incorrect arguments number! Usage:\n"
5039               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5040     return 1;
5041   }
5042
5043   Standard_Real anOriginX, anOriginY, aRotAngle;
5044   if (aType == Aspect_GT_Rectangular)
5045   {
5046     Standard_Real aRStepX, aRStepY;
5047     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5048
5049     anOriginX = Draw::Atof (theArgVec[anIter++]);
5050     anOriginY = Draw::Atof (theArgVec[anIter++]);
5051     if (aTail == 5)
5052     {
5053       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5054       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5055       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5056     }
5057     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5058     aViewer->ActivateGrid (aType, aMode);
5059   }
5060   else if (aType == Aspect_GT_Circular)
5061   {
5062     Standard_Real aRadiusStep;
5063     Standard_Integer aDivisionNumber;
5064     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5065
5066     anOriginX = Draw::Atof (theArgVec[anIter++]);
5067     anOriginY = Draw::Atof (theArgVec[anIter++]);
5068     if (aTail == 5)
5069     {
5070       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5071       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5072       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5073     }
5074
5075     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5076     aViewer->ActivateGrid (aType, aMode);
5077   }
5078
5079   return 0;
5080 }
5081
5082 //==============================================================================
5083 //function : VPriviledgedPlane
5084 //purpose  :
5085 //==============================================================================
5086
5087 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5088                               Standard_Integer  theArgNb,
5089                               const char**      theArgVec)
5090 {
5091   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5092   {
5093     std::cerr << "Error: wrong number of arguments! See usage:\n";
5094     theDI.PrintHelp (theArgVec[0]);
5095     return 1;
5096   }
5097
5098   // get the active viewer
5099   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5100   if (aViewer.IsNull())
5101   {
5102     std::cerr << "Error: no active viewer. Please call vinit.\n";
5103     return 1;
5104   }
5105
5106   if (theArgNb == 1)
5107   {
5108     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5109     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5110     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5111     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5112     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5113           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5114           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5115     return 0;
5116   }
5117
5118   Standard_Integer anArgIdx = 1;
5119   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5120   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5121   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5122   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5123   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5124   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5125
5126   gp_Ax3 aPriviledgedPlane;
5127   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5128   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5129   if (theArgNb > 7)
5130   {
5131     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5132     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5133     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5134     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5135     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5136   }
5137   else
5138   {
5139     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5140   }
5141
5142   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5143
5144   return 0;
5145 }
5146
5147 //==============================================================================
5148 //function : VConvert
5149 //purpose  :
5150 //==============================================================================
5151
5152 static int VConvert (Draw_Interpretor& theDI,
5153                      Standard_Integer  theArgNb,
5154                      const char**      theArgVec)
5155 {
5156   // get the active view
5157   Handle(V3d_View) aView = ViewerTest::CurrentView();
5158   if (aView.IsNull())
5159   {
5160     std::cerr << "Error: no active view. Please call vinit.\n";
5161     return 1;
5162   }
5163
5164   enum { Model, Ray, View, Window, Grid } aMode = Model;
5165
5166   // access coordinate arguments
5167   TColStd_SequenceOfReal aCoord;
5168   Standard_Integer anArgIdx = 1;
5169   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5170   {
5171     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5172     if (!anArg.IsRealValue())
5173     {
5174       break;
5175     }
5176     aCoord.Append (anArg.RealValue());
5177   }
5178
5179   // non-numeric argument too early
5180   if (aCoord.IsEmpty())
5181   {
5182     std::cerr << "Error: wrong number of arguments! See usage:\n";
5183     theDI.PrintHelp (theArgVec[0]);
5184     return 1;
5185   }
5186
5187   // collect all other arguments and options
5188   for (; anArgIdx < theArgNb; ++anArgIdx)
5189   {
5190     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5191     anArg.LowerCase();
5192     if      (anArg == "window") aMode = Window;
5193     else if (anArg == "view")   aMode = View;
5194     else if (anArg == "grid")   aMode = Grid;
5195     else if (anArg == "ray")    aMode = Ray;
5196     else
5197     {
5198       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5199       theDI.PrintHelp (theArgVec[0]);
5200       return 1;
5201     }
5202   }
5203
5204   // complete input checks
5205   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5206       (aCoord.Length() == 2 && theArgNb > 4) ||
5207       (aCoord.Length() == 3 && theArgNb > 5))
5208   {
5209     std::cerr << "Error: wrong number of arguments! See usage:\n";
5210     theDI.PrintHelp (theArgVec[0]);
5211     return 1;
5212   }
5213
5214   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5215   Standard_Integer aXYp[2] = {0, 0};
5216
5217   // convert one-dimensional coordinate
5218   if (aCoord.Length() == 1)
5219   {
5220     switch (aMode)
5221     {
5222       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5223       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5224       default:
5225         std::cerr << "Error: wrong arguments! See usage:\n";
5226         theDI.PrintHelp (theArgVec[0]);
5227         return 1;
5228     }
5229   }
5230
5231   // convert 2D coordinates from projection or view reference space
5232   if (aCoord.Length() == 2)
5233   {
5234     switch (aMode)
5235     {
5236       case Model :
5237         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5238         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5239         return 0;
5240
5241       case View :
5242         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5243         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5244         return 0;
5245
5246       case Window :
5247         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5248         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5249         return 0;
5250
5251       case Grid :
5252         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5253         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5254         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5255         return 0;
5256
5257       case Ray :
5258         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5259                                 (Standard_Integer) aCoord (2),
5260                                 aXYZ[0], aXYZ[1], aXYZ[2],
5261                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5262         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5263         return 0;
5264
5265       default:
5266         std::cerr << "Error: wrong arguments! See usage:\n";
5267         theDI.PrintHelp (theArgVec[0]);
5268         return 1;
5269     }
5270   }
5271
5272   // convert 3D coordinates from view reference space
5273   else if (aCoord.Length() == 3)
5274   {
5275     switch (aMode)
5276     {
5277       case Window :
5278         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5279         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5280         return 0;
5281
5282       case Grid :
5283         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5284         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5285         return 0;
5286
5287       default:
5288         std::cerr << "Error: wrong arguments! See usage:\n";
5289         theDI.PrintHelp (theArgVec[0]);
5290         return 1;
5291     }
5292   }
5293
5294   return 0;
5295 }
5296
5297 //==============================================================================
5298 //function : VFps
5299 //purpose  :
5300 //==============================================================================
5301
5302 static int VFps (Draw_Interpretor& theDI,
5303                  Standard_Integer  theArgNb,
5304                  const char**      theArgVec)
5305 {
5306   // get the active view
5307   Handle(V3d_View) aView = ViewerTest::CurrentView();
5308   if (aView.IsNull())
5309   {
5310     std::cerr << "No active view. Please call vinit.\n";
5311     return 1;
5312   }
5313
5314   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5315   if (aFramesNb <= 0)
5316   {
5317     std::cerr << "Incorrect arguments!\n";
5318     return 1;
5319   }
5320
5321   // the time is meaningless for first call
5322   // due to async OpenGl rendering
5323   aView->Redraw();
5324
5325   // redraw view in loop to estimate average values
5326   OSD_Timer aTimer;
5327   aTimer.Start();
5328   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5329   {
5330     aView->Redraw();
5331   }
5332   aTimer.Stop();
5333   Standard_Real aCpu;
5334   const Standard_Real aTime = aTimer.ElapsedTime();
5335   aTimer.OSD_Chronometer::Show (aCpu);
5336
5337   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5338   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5339
5340   // return statistics
5341   theDI << "FPS: " << aFpsAver << "\n"
5342         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5343
5344   // compute additional statistics in ray-tracing mode
5345   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5346
5347   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5348   {
5349     Standard_Integer aSizeX;
5350     Standard_Integer aSizeY;
5351
5352     aView->Window()->Size (aSizeX, aSizeY);
5353
5354     // 1 shadow ray and 1 secondary ray pew each bounce
5355     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5356
5357     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5358   }
5359
5360   return 0;
5361 }
5362
5363 //==============================================================================
5364 //function : VGlDebug
5365 //purpose  :
5366 //==============================================================================
5367
5368 static int VGlDebug (Draw_Interpretor& theDI,
5369                      Standard_Integer  theArgNb,
5370                      const char**      theArgVec)
5371 {
5372   Handle(OpenGl_GraphicDriver) aDriver;
5373   Handle(V3d_View) aView = ViewerTest::CurrentView();
5374   if (!aView.IsNull())
5375   {
5376     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5377   }
5378   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5379   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5380
5381   if (theArgNb < 2)
5382   {
5383     TCollection_AsciiString aDebActive, aSyncActive;
5384     if (aCaps == NULL)
5385     {
5386       aCaps = aDefCaps;
5387     }
5388     else
5389     {
5390       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5391                                                                   "GL_ARB_debug_output");
5392       aDebActive = isActive ? " (active)" : " (inactive)";
5393       if (isActive)
5394       {
5395         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5396         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5397       }
5398     }
5399
5400     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5401           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5402           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5403           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5404     return 0;
5405   }
5406
5407   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5408   {
5409     Standard_CString        anArg     = theArgVec[anArgIter];
5410     TCollection_AsciiString anArgCase (anArg);
5411     anArgCase.LowerCase();
5412     Standard_Boolean toEnableDebug = Standard_True;
5413     if (anArgCase == "-glsl"
5414      || anArgCase == "-glslwarn"
5415      || anArgCase == "-glslwarns"
5416      || anArgCase == "-glslwarnings")
5417     {
5418       Standard_Boolean toShowWarns = Standard_True;
5419       if (++anArgIter < theArgNb
5420       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5421       {
5422         --anArgIter;
5423       }
5424       aDefCaps->glslWarnings = toShowWarns;
5425       if (aCaps != NULL)
5426       {
5427         aCaps->glslWarnings = toShowWarns;
5428       }
5429     }
5430     else if (anArgCase == "-extra"
5431           || anArgCase == "-extramsg"
5432           || anArgCase == "-extramessages")
5433     {
5434       Standard_Boolean toShow = Standard_True;
5435       if (++anArgIter < theArgNb
5436       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5437       {
5438         --anArgIter;
5439       }
5440       aDefCaps->suppressExtraMsg = !toShow;
5441       if (aCaps != NULL)
5442       {
5443         aCaps->suppressExtraMsg = !toShow;
5444       }
5445     }
5446     else if (anArgCase == "-noextra"
5447           || anArgCase == "-noextramsg"
5448           || anArgCase == "-noextramessages")
5449     {
5450       Standard_Boolean toSuppress = Standard_True;
5451       if (++anArgIter < theArgNb
5452       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5453       {
5454         --anArgIter;
5455       }
5456       aDefCaps->suppressExtraMsg = toSuppress;
5457       if (aCaps != NULL)
5458       {
5459         aCaps->suppressExtraMsg = toSuppress;
5460       }
5461     }
5462     else if (anArgCase == "-sync")
5463     {
5464       Standard_Boolean toSync = Standard_True;
5465       if (++anArgIter < theArgNb
5466       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5467       {
5468         --anArgIter;
5469       }
5470       aDefCaps->contextSyncDebug = toSync;
5471       if (toSync)
5472       {
5473         aDefCaps->contextDebug = Standard_True;
5474       }
5475     }
5476     else if (anArgCase == "-debug")
5477     {
5478       if (++anArgIter < theArgNb
5479       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5480       {
5481         --anArgIter;
5482       }
5483       aDefCaps->contextDebug = toEnableDebug;
5484     }
5485     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5486           && (anArgIter + 1 == theArgNb))
5487     {
5488       // simple alias to turn on almost everything
5489       aDefCaps->contextDebug     = toEnableDebug;
5490       aDefCaps->contextSyncDebug = toEnableDebug;
5491       aDefCaps->glslWarnings     = toEnableDebug;
5492     }
5493     else
5494     {
5495       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5496       return 1;
5497     }
5498   }
5499
5500   return 0;
5501 }
5502
5503 //==============================================================================
5504 //function : VVbo
5505 //purpose  :
5506 //==============================================================================
5507
5508 static int VVbo (Draw_Interpretor& theDI,
5509                  Standard_Integer  theArgNb,
5510                  const char**      theArgVec)
5511 {
5512   const Standard_Boolean toSet    = (theArgNb > 1);
5513   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5514   if (toSet)
5515   {
5516     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5517   }
5518
5519   // get the context
5520   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5521   if (aContextAIS.IsNull())
5522   {
5523     if (!toSet)
5524     {
5525       std::cerr << "No active view!\n";
5526     }
5527     return 1;
5528   }
5529   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5530   if (!aDriver.IsNull())
5531   {
5532     if (!toSet)
5533     {
5534       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5535     }
5536     else
5537     {
5538       aDriver->ChangeOptions().vboDisable = toUseVbo;
5539     }
5540   }
5541
5542   return 0;
5543 }
5544
5545 //==============================================================================
5546 //function : VCaps
5547 //purpose  :
5548 //==============================================================================
5549
5550 static int VCaps (Draw_Interpretor& theDI,
5551                   Standard_Integer  theArgNb,
5552                   const char**      theArgVec)
5553 {
5554   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5555   Handle(OpenGl_GraphicDriver)   aDriver;
5556   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5557   if (!aContext.IsNull())
5558   {
5559     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5560     aCaps   = &aDriver->ChangeOptions();
5561   }
5562
5563   if (theArgNb < 2)
5564   {
5565     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5566     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5567     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5568     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5569     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5570     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5571     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5572     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5573     return 0;
5574   }
5575
5576   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5577   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5578   {
5579     Standard_CString        anArg     = theArgVec[anArgIter];
5580     TCollection_AsciiString anArgCase (anArg);
5581     anArgCase.LowerCase();
5582     if (anUpdateTool.parseRedrawMode (anArg))
5583     {
5584       continue;
5585     }
5586     else if (anArgCase == "-vsync"
5587           || anArgCase == "-swapinterval")
5588     {
5589       Standard_Boolean toEnable = Standard_True;
5590       if (++anArgIter < theArgNb
5591       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5592       {
5593         --anArgIter;
5594       }
5595       aCaps->swapInterval = toEnable;
5596     }
5597     else if (anArgCase == "-ffp")
5598     {
5599       Standard_Boolean toEnable = Standard_True;
5600       if (++anArgIter < theArgNb
5601       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5602       {
5603         --anArgIter;
5604       }
5605       aCaps->ffpEnable = toEnable;
5606     }
5607     else if (anArgCase == "-vbo")
5608     {
5609       Standard_Boolean toEnable = Standard_True;
5610       if (++anArgIter < theArgNb
5611       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5612       {
5613         --anArgIter;
5614       }
5615       aCaps->vboDisable = !toEnable;
5616     }
5617     else if (anArgCase == "-sprite"
5618           || anArgCase == "-sprites")
5619     {
5620       Standard_Boolean toEnable = Standard_True;
5621       if (++anArgIter < theArgNb
5622       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5623       {
5624         --anArgIter;
5625       }
5626       aCaps->pntSpritesDisable = !toEnable;
5627     }
5628     else if (anArgCase == "-softmode")
5629     {
5630       Standard_Boolean toEnable = Standard_True;
5631       if (++anArgIter < theArgNb
5632       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5633       {
5634         --anArgIter;
5635       }
5636       aCaps->contextNoAccel = toEnable;
5637     }
5638     else if (anArgCase == "-winbuffer"
5639           || anArgCase == "-windowbuffer"
5640           || anArgCase == "-usewinbuffer"
5641           || anArgCase == "-usewindowbuffer"
5642           || anArgCase == "-usesystembuffer")
5643     {
5644       Standard_Boolean toEnable = Standard_True;
5645       if (++anArgIter < theArgNb
5646       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5647       {
5648         --anArgIter;
5649       }
5650       aCaps->useSystemBuffer = toEnable;
5651     }
5652     else if (anArgCase == "-accel"
5653           || anArgCase == "-acceleration")
5654     {
5655       Standard_Boolean toEnable = Standard_True;
5656       if (++anArgIter < theArgNb
5657       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5658       {
5659         --anArgIter;
5660       }
5661       aCaps->contextNoAccel = !toEnable;
5662     }
5663     else if (anArgCase == "-compat"
5664           || anArgCase == "-compatprofile"
5665           || anArgCase == "-compatible"
5666           || anArgCase == "-compatibleprofile")
5667     {
5668       Standard_Boolean toEnable = Standard_True;
5669       if (++anArgIter < theArgNb
5670       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5671       {
5672         --anArgIter;
5673       }
5674       aCaps->contextCompatible = toEnable;
5675       if (!aCaps->contextCompatible)
5676       {
5677         aCaps->ffpEnable = Standard_False;
5678       }
5679     }
5680     else if (anArgCase == "-core"
5681           || anArgCase == "-coreprofile")
5682     {
5683       Standard_Boolean toEnable = Standard_True;
5684       if (++anArgIter < theArgNb
5685       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5686       {
5687         --anArgIter;
5688       }
5689       aCaps->contextCompatible = !toEnable;
5690       if (!aCaps->contextCompatible)
5691       {
5692         aCaps->ffpEnable = Standard_False;
5693       }
5694     }
5695     else if (anArgCase == "-stereo"
5696           || anArgCase == "-quadbuffer")
5697     {
5698       Standard_Boolean toEnable = Standard_True;
5699       if (++anArgIter < theArgNb
5700       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5701       {
5702         --anArgIter;
5703       }
5704       aCaps->contextStereo = toEnable;
5705     }
5706     else
5707     {
5708       std::cout << "Error: unknown argument '" << anArg << "'\n";
5709       return 1;
5710     }
5711   }
5712   if (aCaps != &ViewerTest_myDefaultCaps)
5713   {
5714     ViewerTest_myDefaultCaps = *aCaps;
5715   }
5716   return 0;
5717 }
5718
5719 //==============================================================================
5720 //function : VMemGpu
5721 //purpose  :
5722 //==============================================================================
5723
5724 static int VMemGpu (Draw_Interpretor& theDI,
5725                     Standard_Integer  theArgNb,
5726                     const char**      theArgVec)
5727 {
5728   // get the context
5729   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5730   if (aContextAIS.IsNull())
5731   {
5732     std::cerr << "No active view. Please call vinit.\n";
5733     return 1;
5734   }
5735
5736   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5737   if (aDriver.IsNull())
5738   {
5739     std::cerr << "Graphic driver not available.\n";
5740     return 1;
5741   }
5742
5743   Standard_Size aFreeBytes = 0;
5744   TCollection_AsciiString anInfo;
5745   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5746   {
5747     std::cerr << "Information not available.\n";
5748     return 1;
5749   }
5750
5751   if (theArgNb > 1 && *theArgVec[1] == 'f')
5752   {
5753     theDI << Standard_Real (aFreeBytes);
5754   }
5755   else
5756   {
5757     theDI << anInfo;
5758   }
5759
5760   return 0;
5761 }
5762
5763 // ==============================================================================
5764 // function : VReadPixel
5765 // purpose  :
5766 // ==============================================================================
5767 static int VReadPixel (Draw_Interpretor& theDI,
5768                        Standard_Integer  theArgNb,
5769                        const char**      theArgVec)
5770 {
5771   // get the active view
5772   Handle(V3d_View) aView = ViewerTest::CurrentView();
5773   if (aView.IsNull())
5774   {
5775     std::cerr << "No active view. Please call vinit.\n";
5776     return 1;
5777   }
5778   else if (theArgNb < 3)
5779   {
5780     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5781     return 1;
5782   }
5783
5784   Image_Format         aFormat     = Image_Format_RGBA;
5785   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
5786
5787   Standard_Integer aWidth, aHeight;
5788   aView->Window()->Size (aWidth, aHeight);
5789   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5790   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5791   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5792   {
5793     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5794     return 1;
5795   }
5796
5797   Standard_Boolean toShowName = Standard_False;
5798   Standard_Boolean toShowHls  = Standard_False;
5799   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5800   {
5801     TCollection_AsciiString aParam (theArgVec[anIter]);
5802     aParam.LowerCase();
5803     if (aParam == "rgb")
5804     {
5805       aFormat     = Image_Format_RGB;
5806       aBufferType = Graphic3d_BT_RGB;
5807     }
5808     else if (aParam == "hls")
5809     {
5810       aFormat     = Image_Format_RGB;
5811       aBufferType = Graphic3d_BT_RGB;
5812       toShowHls   = Standard_True;
5813     }
5814     else if (aParam == "rgbf")
5815     {
5816       aFormat     = Image_Format_RGBF;
5817       aBufferType = Graphic3d_BT_RGB;
5818     }
5819     else if (aParam == "rgba")
5820     {
5821       aFormat     = Image_Format_RGBA;
5822       aBufferType = Graphic3d_BT_RGBA;
5823     }
5824     else if (aParam == "rgbaf")
5825     {
5826       aFormat     = Image_Format_RGBAF;
5827       aBufferType = Graphic3d_BT_RGBA;
5828     }
5829     else if (aParam == "depth")
5830     {
5831       aFormat     = Image_Format_GrayF;
5832       aBufferType = Graphic3d_BT_Depth;
5833     }
5834     else if (aParam == "name")
5835     {
5836       toShowName = Standard_True;
5837     }
5838   }
5839
5840   Image_PixMap anImage;
5841   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5842   {
5843     std::cerr << "Image allocation failed\n";
5844     return 1;
5845   }
5846   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
5847   {
5848     std::cerr << "Image dump failed\n";
5849     return 1;
5850   }
5851
5852   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
5853   if (toShowName)
5854   {
5855     if (aBufferType == Graphic3d_BT_RGBA)
5856     {
5857       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
5858     }
5859     else
5860     {
5861       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
5862     }
5863   }
5864   else
5865   {
5866     switch (aBufferType)
5867     {
5868       default:
5869       case Graphic3d_BT_RGB:
5870       {
5871         if (toShowHls)
5872         {
5873           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
5874         }
5875         else
5876         {
5877           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
5878         }
5879         break;
5880       }
5881       case Graphic3d_BT_RGBA:
5882       {
5883         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
5884         break;
5885       }
5886       case Graphic3d_BT_Depth:
5887       {
5888         theDI << aColor.GetRGB().Red();
5889         break;
5890       }
5891     }
5892   }
5893
5894   return 0;
5895 }
5896
5897 //==============================================================================
5898 //function : VDiffImage
5899 //purpose  : The draw-command compares two images.
5900 //==============================================================================
5901
5902 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
5903 {
5904   if (theArgNb < 6)
5905   {
5906     theDI << "Not enough arguments.\n";
5907     return 1;
5908   }
5909
5910   // image file names
5911   const char* anImgPathRef = theArgVec[1];
5912   const char* anImgPathNew = theArgVec[2];
5913
5914   // get string tolerance and check its validity
5915   Standard_Real aTolColor = Draw::Atof (theArgVec[3]);
5916   if (aTolColor < 0.0)
5917     aTolColor = 0.0;
5918   if (aTolColor > 1.0)
5919     aTolColor = 1.0;
5920
5921   Standard_Boolean toBlackWhite     = (Draw::Atoi (theArgVec[4]) == 1);
5922   Standard_Boolean isBorderFilterOn = (Draw::Atoi (theArgVec[5]) == 1);
5923
5924   // image file of difference
5925   const char* aDiffImagePath = (theArgNb >= 7) ? theArgVec[6] : NULL;
5926
5927   // compare the images
5928   Image_Diff aComparer;
5929   if (!aComparer.Init (anImgPathRef, anImgPathNew, toBlackWhite))
5930   {
5931     return 1;
5932   }
5933
5934   aComparer.SetColorTolerance (aTolColor);
5935   aComparer.SetBorderFilterOn (isBorderFilterOn);
5936   Standard_Integer aDiffColorsNb = aComparer.Compare();
5937   theDI << aDiffColorsNb << "\n";
5938
5939   // save image of difference
5940   if (aDiffColorsNb >0 && aDiffImagePath != NULL)
5941   {
5942     aComparer.SaveDiffImage (aDiffImagePath);
5943   }
5944
5945   return 0;
5946 }
5947
5948 //=======================================================================
5949 //function : VSelect
5950 //purpose  : Emulates different types of selection by mouse:
5951 //           1) single click selection
5952 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
5953 //           3) selection with polygon having corners at
5954 //           pixel positions (x1,y1),...,(xn,yn)
5955 //           4) any of these selections with shift button pressed
5956 //=======================================================================
5957 static Standard_Integer VSelect (Draw_Interpretor& di,
5958                                  Standard_Integer argc,
5959                                  const char ** argv)
5960 {
5961   if(argc < 3)
5962   {
5963     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
5964     return 1;
5965   }
5966
5967   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
5968   if(myAIScontext.IsNull())
5969   {
5970     di << "use 'vinit' command before " << argv[0] << "\n";
5971     return 1;
5972   }
5973
5974   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
5975   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
5976   TCollection_AsciiString anArg;
5977   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
5978   anArg.LowerCase();
5979   if (anArg == "-allowoverlap")
5980   {
5981     Standard_Boolean isValidated = isShiftSelection ? argc == 8
5982       : argc == 7;
5983     if (!isValidated)
5984     {
5985       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
5986       return 1;
5987     }
5988
5989     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
5990     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
5991     aCoordsNb -= 2;
5992   }
5993
5994   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
5995   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
5996   if(aCoordsNb == 2)
5997   {
5998     if(isShiftSelection)
5999       aCurrentEventManager->ShiftSelect();
6000     else
6001       aCurrentEventManager->Select();
6002   }
6003   else if(aCoordsNb == 4)
6004   {
6005     if(isShiftSelection)
6006       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6007     else
6008       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6009   }
6010   else
6011   {
6012     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6013
6014     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6015       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6016
6017     if(isShiftSelection)
6018       aCurrentEventManager->ShiftSelect(aPolyline);
6019     else
6020       aCurrentEventManager->Select(aPolyline);
6021   }
6022   return 0;
6023 }
6024
6025 //=======================================================================
6026 //function : VMoveTo
6027 //purpose  : Emulates cursor movement to defined pixel position
6028 //=======================================================================
6029 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6030                                 Standard_Integer argc,
6031                                 const char ** argv)
6032 {
6033   if(argc != 3)
6034   {
6035     di << "Usage : " << argv[0] << " x y\n";
6036     return 1;
6037   }
6038
6039   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6040   if(aContext.IsNull())
6041   {
6042     di << "use 'vinit' command before " << argv[0] << "\n";
6043     return 1;
6044   }
6045   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6046   return 0;
6047 }
6048
6049 namespace
6050 {
6051   //! Global map storing all animations registered in ViewerTest.
6052   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6053
6054   //! The animation calling the Draw Harness command.
6055   class ViewerTest_AnimationProc : public AIS_Animation
6056   {
6057   public:
6058
6059     //! Main constructor.
6060     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6061                               Draw_Interpretor* theDI,
6062                               const TCollection_AsciiString& theCommand)
6063     : AIS_Animation (theAnimationName),
6064       myDrawInter(theDI),
6065       myCommand  (theCommand)
6066     {
6067       //
6068     }
6069
6070   protected:
6071
6072     //! Evaluate the command.
6073     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6074     {
6075       TCollection_AsciiString aCmd = myCommand;
6076       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6077       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6078       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6079       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6080       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6081       myDrawInter->Eval (aCmd.ToCString());
6082     }
6083
6084     //! Find the keyword in the command and replace it with value.
6085     //! @return the position of the keyword to pass value
6086     void replace (TCollection_AsciiString&       theCmd,
6087                   const TCollection_AsciiString& theKey,
6088                   const TCollection_AsciiString& theVal)
6089     {
6090       TCollection_AsciiString aCmd (theCmd);
6091       aCmd.LowerCase();
6092       const Standard_Integer aPos = aCmd.Search (theKey);
6093       if (aPos == -1)
6094       {
6095         return;
6096       }
6097
6098       TCollection_AsciiString aPart1, aPart2;
6099       Standard_Integer aPart1To = aPos - 1;
6100       if (aPart1To >= 1
6101        && aPart1To <= theCmd.Length())
6102       {
6103         aPart1 = theCmd.SubString (1, aPart1To);
6104       }
6105
6106       Standard_Integer aPart2From = aPos + theKey.Length();
6107       if (aPart2From >= 1
6108        && aPart2From <= theCmd.Length())
6109       {
6110         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6111       }
6112
6113       theCmd = aPart1 + theVal + aPart2;
6114     }
6115
6116   protected:
6117
6118     Draw_Interpretor*       myDrawInter;
6119     TCollection_AsciiString myCommand;
6120
6121   };
6122
6123   //! Replace the animation with the new one.
6124   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6125                                 Handle(AIS_Animation)&       theAnimation,
6126                                 const Handle(AIS_Animation)& theAnimationNew)
6127   {
6128     theAnimationNew->CopyFrom (theAnimation);
6129     if (!theParentAnimation.IsNull())
6130     {
6131       theParentAnimation->Replace (theAnimation, theAnimationNew);
6132     }
6133     else
6134     {
6135       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6136       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6137     }
6138     theAnimation = theAnimationNew;
6139   }
6140
6141   //! Parse the point.
6142   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6143   {
6144     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6145     if (!anXYZ[0].IsRealValue()
6146      || !anXYZ[1].IsRealValue()
6147      || !anXYZ[2].IsRealValue())
6148     {
6149       return Standard_False;
6150     }
6151
6152     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6153     return Standard_True;
6154   }
6155
6156   //! Parse the quaternion.
6157   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6158   {
6159     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6160     if (!anXYZW[0].IsRealValue()
6161      || !anXYZW[1].IsRealValue()
6162      || !anXYZW[2].IsRealValue()
6163      || !anXYZW[3].IsRealValue())
6164     {
6165       return Standard_False;
6166     }
6167
6168     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6169     return Standard_True;
6170   }
6171
6172 }
6173
6174 //=================================================================================================
6175 //function : VViewParams
6176 //purpose  : Gets or sets AIS View characteristics
6177 //=================================================================================================
6178 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6179 {
6180   Handle(V3d_View) aView = ViewerTest::CurrentView();
6181   if (aView.IsNull())
6182   {
6183     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6184     return 1;
6185   }
6186
6187   Standard_Boolean toSetProj     = Standard_False;
6188   Standard_Boolean toSetUp       = Standard_False;
6189   Standard_Boolean toSetAt       = Standard_False;
6190   Standard_Boolean toSetEye      = Standard_False;
6191   Standard_Boolean toSetScale    = Standard_False;
6192   Standard_Boolean toSetSize     = Standard_False;
6193   Standard_Boolean toSetCenter2d = Standard_False;
6194   Standard_Real    aViewScale = aView->Scale();
6195   Standard_Real    aViewSize  = 1.0;
6196   Graphic3d_Vec2i  aCenter2d;
6197   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6198   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6199   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6200   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6201   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6202   if (theArgsNb == 1)
6203   {
6204     // print all of the available view parameters
6205     char aText[4096];
6206     Sprintf (aText,
6207              "Scale: %g\n"
6208              "Proj:  %12g %12g %12g\n"
6209              "Up:    %12g %12g %12g\n"
6210              "At:    %12g %12g %12g\n"
6211              "Eye:   %12g %12g %12g\n",
6212               aViewScale,
6213               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6214               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6215               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6216               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6217     theDi << aText;
6218     return 0;
6219   }
6220
6221   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6222   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6223   {
6224     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6225     anArg.LowerCase();
6226     if (anUpdateTool.parseRedrawMode (anArg))
6227     {
6228       continue;
6229     }
6230     else if (anArg == "-cmd"
6231           || anArg == "-command"
6232           || anArg == "-args")
6233     {
6234       char aText[4096];
6235       Sprintf (aText,
6236                "-scale %g "
6237                "-proj %g %g %g "
6238                "-up %g %g %g "
6239                "-at %g %g %g\n",
6240                 aViewScale,
6241                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6242                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6243                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6244       theDi << aText;
6245     }
6246     else if (anArg == "-scale"
6247           || anArg == "-size")
6248     {
6249       if (anArgIter + 1 < theArgsNb
6250        && *theArgVec[anArgIter + 1] != '-')
6251       {
6252         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6253         if (aValueArg.IsRealValue())
6254         {
6255           ++anArgIter;
6256           if (anArg == "-scale")
6257           {
6258             toSetScale = Standard_True;
6259             aViewScale = aValueArg.RealValue();
6260           }
6261           else if (anArg == "-size")
6262           {
6263             toSetSize = Standard_True;
6264             aViewSize = aValueArg.RealValue();
6265           }
6266           continue;
6267         }
6268       }
6269       if (anArg == "-scale")
6270       {
6271         theDi << "Scale: " << aView->Scale() << "\n";
6272       }
6273       else if (anArg == "-size")
6274       {
6275         Graphic3d_Vec2d aSizeXY;
6276         aView->Size (aSizeXY.x(), aSizeXY.y());
6277         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6278       }
6279     }
6280     else if (anArg == "-eye"
6281           || anArg == "-at"
6282           || anArg == "-up"
6283           || anArg == "-proj")
6284     {
6285       if (anArgIter + 3 < theArgsNb)
6286       {
6287         gp_XYZ anXYZ;
6288         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6289         {
6290           anArgIter += 3;
6291           if (anArg == "-eye")
6292           {
6293             toSetEye = Standard_True;
6294             aViewEye = anXYZ;
6295           }
6296           else if (anArg == "-at")
6297           {
6298             toSetAt = Standard_True;
6299             aViewAt = anXYZ;
6300           }
6301           else if (anArg == "-up")
6302           {
6303             toSetUp = Standard_True;
6304             aViewUp = anXYZ;
6305           }
6306           else if (anArg == "-proj")
6307           {
6308             toSetProj = Standard_True;
6309             aViewProj = anXYZ;
6310           }
6311           continue;
6312         }
6313       }
6314
6315       if (anArg == "-eye")
6316       {
6317         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6318       }
6319       else if (anArg == "-at")
6320       {
6321         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6322       }
6323       else if (anArg == "-up")
6324       {
6325         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6326       }
6327       else if (anArg == "-proj")
6328       {
6329         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6330       }
6331     }
6332     else if (anArg == "-center")
6333     {
6334       if (anArgIter + 2 < theArgsNb)
6335       {
6336         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6337         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6338         if (anX.IsIntegerValue()
6339          && anY.IsIntegerValue())
6340         {
6341           toSetCenter2d = Standard_True;
6342           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6343         }
6344       }
6345     }
6346     else
6347     {
6348       std::cout << "Syntax error at '" << anArg << "'\n";
6349       return 1;
6350     }
6351   }
6352
6353   // change view parameters in proper order
6354   if (toSetScale)
6355   {
6356     aView->SetScale (aViewScale);
6357   }
6358   if (toSetSize)
6359   {
6360     aView->SetSize (aViewSize);
6361   }
6362   if (toSetEye)
6363   {
6364     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6365   }
6366   if (toSetAt)
6367   {
6368     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6369   }
6370   if (toSetProj)
6371   {
6372     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6373   }
6374   if (toSetUp)
6375   {
6376     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6377   }
6378   if (toSetCenter2d)
6379   {
6380     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6381   }
6382
6383   return 0;
6384 }
6385
6386 //==============================================================================
6387 //function : VAnimation
6388 //purpose  :
6389 //==============================================================================
6390 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6391                                     Standard_Integer  theArgNb,
6392                                     const char**      theArgVec)
6393 {
6394   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6395   if (theArgNb < 2)
6396   {
6397     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6398          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6399     {
6400       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6401     }
6402     return 0;
6403   }
6404   if (aCtx.IsNull())
6405   {
6406     std::cout << "Error: no active view\n";
6407     return 1;
6408   }
6409
6410   Standard_Integer anArgIter = 1;
6411   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6412   if (aNameArg.IsEmpty())
6413   {
6414     std::cout << "Syntax error: animation name is not defined.\n";
6415     return 1;
6416   }
6417
6418   TCollection_AsciiString aNameArgLower = aNameArg;
6419   aNameArgLower.LowerCase();
6420   if (aNameArgLower == "-reset"
6421    || aNameArgLower == "-clear")
6422   {
6423     ViewerTest_AnimationTimelineMap.Clear();
6424     return 0;
6425   }
6426   else if (aNameArg.Value (1) == '-')
6427   {
6428     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6429     return 1;
6430   }
6431
6432   const char* aNameSplitter = "/";
6433   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6434   if (aSplitPos == -1)
6435   {
6436     aNameSplitter = ".";
6437     aSplitPos = aNameArg.Search (aNameSplitter);
6438   }
6439
6440   // find existing or create a new animation by specified name within syntax "parent.child".
6441   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6442   for (; !aNameArg.IsEmpty();)
6443   {
6444     TCollection_AsciiString aNameParent;
6445     if (aSplitPos != -1)
6446     {
6447       if (aSplitPos == aNameArg.Length())
6448       {
6449         std::cout << "Syntax error: animation name is not defined.\n";
6450         return 1;
6451       }
6452
6453       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
6454       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
6455
6456       aSplitPos = aNameArg.Search (aNameSplitter);
6457     }
6458     else
6459     {
6460       aNameParent = aNameArg;
6461       aNameArg.Clear();
6462     }
6463
6464     if (anAnimation.IsNull())
6465     {
6466       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
6467       {
6468         anAnimation = new AIS_Animation (aNameParent);
6469         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
6470       }
6471       aRootAnimation = anAnimation;
6472     }
6473     else
6474     {
6475       aParentAnimation = anAnimation;
6476       anAnimation = aParentAnimation->Find (aNameParent);
6477       if (anAnimation.IsNull())
6478       {
6479         anAnimation = new AIS_Animation (aNameParent);
6480         aParentAnimation->Add (anAnimation);
6481       }
6482     }
6483   }
6484
6485   if (anArgIter >= theArgNb)
6486   {
6487     // just print the list of children
6488     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
6489     {
6490       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
6491     }
6492     return 0;
6493   }
6494
6495   // animation parameters
6496   Standard_Boolean toPlay = Standard_False;
6497   Standard_Real aPlaySpeed     = 1.0;
6498   Standard_Real aPlayStartTime = anAnimation->StartPts();
6499   Standard_Real aPlayDuration  = anAnimation->Duration();
6500   Standard_Integer aFpsNum     = 0;
6501   Standard_Integer aFpsDen     = 1;
6502   Standard_Boolean isFreeCamera = Standard_False;
6503   Standard_Boolean isLockLoop   = Standard_False;
6504   Handle(V3d_View) aView = ViewerTest::CurrentView();
6505   for (; anArgIter < theArgNb; ++anArgIter)
6506   {
6507     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6508     anArg.LowerCase();
6509     // general options
6510     if (anArg == "-reset"
6511      || anArg == "-clear")
6512     {
6513       anAnimation->Clear();
6514     }
6515     else if (anArg == "-remove"
6516           || anArg == "-del"
6517           || anArg == "-delete")
6518     {
6519       if (!aParentAnimation.IsNull())
6520       {
6521         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
6522       }
6523       else
6524       {
6525         aParentAnimation->Remove (anAnimation);
6526       }
6527     }
6528     // playback options
6529     else if (anArg == "-play")
6530     {
6531       toPlay = Standard_True;
6532       if (++anArgIter < theArgNb)
6533       {
6534         if (*theArgVec[anArgIter] == '-')
6535         {
6536           --anArgIter;
6537           continue;
6538         }
6539         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
6540
6541         if (++anArgIter < theArgNb)
6542         {
6543           if (*theArgVec[anArgIter] == '-')
6544           {
6545             --anArgIter;
6546             continue;
6547           }
6548           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6549         }
6550       }
6551     }
6552     else if (anArg == "-resume")
6553     {
6554       toPlay = Standard_True;
6555       aPlayStartTime = anAnimation->ElapsedTime();
6556       if (++anArgIter < theArgNb)
6557       {
6558         if (*theArgVec[anArgIter] == '-')
6559         {
6560           --anArgIter;
6561           continue;
6562         }
6563
6564         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
6565       }
6566     }
6567     else if (anArg == "-playspeed"
6568           || anArg == "-speed")
6569     {
6570       if (++anArgIter >= theArgNb)
6571       {
6572         std::cout << "Syntax error at " << anArg << ".\n";
6573         return 1;
6574       }
6575       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
6576     }
6577     else if (anArg == "-lock"
6578           || anArg == "-lockloop"
6579           || anArg == "-playlockloop")
6580     {
6581       isLockLoop = Standard_True;
6582     }
6583     else if (anArg == "-freecamera"
6584           || anArg == "-playfreecamera"
6585           || anArg == "-freelook")
6586     {
6587       isFreeCamera = Standard_True;
6588     }
6589     else if (anArg == "-fps")
6590     {
6591       if (++anArgIter >= theArgNb)
6592       {
6593         std::cout << "Syntax error at " << anArg << ".\n";
6594         return 1;
6595       }
6596
6597       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
6598       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
6599       if (aSplitIndex == 0)
6600       {
6601         aFpsNum = aFpsArg.IntegerValue();
6602       }
6603       else
6604       {
6605         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
6606         aFpsArg.Split (aFpsArg.Length() - 1);
6607         const TCollection_AsciiString aNumStr = aFpsArg;
6608         aFpsNum = aNumStr.IntegerValue();
6609         aFpsDen = aDenStr.IntegerValue();
6610         if (aFpsDen < 1)
6611         {
6612           std::cout << "Syntax error at " << anArg << ".\n";
6613           return 1;
6614         }
6615       }
6616     }
6617     // animation definition options
6618     else if (anArg == "-start"
6619           || anArg == "-starttime"
6620           || anArg == "-startpts")
6621     {
6622       if (++anArgIter >= theArgNb)
6623       {
6624         std::cout << "Syntax error at " << anArg << ".\n";
6625         return 1;
6626       }
6627
6628       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
6629       aRootAnimation->UpdateTotalDuration();
6630     }
6631     else if (anArg == "-end"
6632           || anArg == "-endtime"
6633           || anArg == "-endpts")
6634     {
6635       if (++anArgIter >= theArgNb)
6636       {
6637         std::cout << "Syntax error at " << anArg << ".\n";
6638         return 1;
6639       }
6640
6641       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
6642       aRootAnimation->UpdateTotalDuration();
6643     }
6644     else if (anArg == "-dur"
6645           || anArg == "-duration")
6646     {
6647       if (++anArgIter >= theArgNb)
6648       {
6649         std::cout << "Syntax error at " << anArg << ".\n";
6650         return 1;
6651       }
6652
6653       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
6654       aRootAnimation->UpdateTotalDuration();
6655     }
6656     else if (anArg == "-command"
6657           || anArg == "-cmd"
6658           || anArg == "-invoke"
6659           || anArg == "-eval"
6660           || anArg == "-proc")
6661     {
6662       if (++anArgIter >= theArgNb)
6663       {
6664         std::cout << "Syntax error at " << anArg << ".\n";
6665         return 1;
6666       }
6667
6668       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
6669       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
6670     }
6671     else if (anArg == "-objecttrsf"
6672           || anArg == "-objectransformation"
6673           || anArg == "-objtransformation"
6674           || anArg == "-objtrsf"
6675           || anArg == "-object"
6676           || anArg == "-obj")
6677     {
6678       if (++anArgIter >= theArgNb)
6679       {
6680         std::cout << "Syntax error at " << anArg << ".\n";
6681         return 1;
6682       }
6683
6684       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
6685       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
6686       if (!aMapOfAIS.IsBound2 (anObjName))
6687       {
6688         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
6689         return 1;
6690       }
6691
6692       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
6693       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
6694       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
6695       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
6696       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
6697       Standard_Boolean isTrsfSet = Standard_False;
6698       Standard_Integer aTrsfArgIter = anArgIter + 1;
6699       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
6700       {
6701         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
6702         aTrsfArg.LowerCase();
6703         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
6704         if (aTrsfArg.StartsWith ("-rotation")
6705          || aTrsfArg.StartsWith ("-rot"))
6706         {
6707           isTrsfSet = Standard_True;
6708           if (aTrsfArgIter + 4 >= theArgNb
6709           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
6710           {
6711             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6712             return 1;
6713           }
6714           aTrsfArgIter += 4;
6715         }
6716         else if (aTrsfArg.StartsWith ("-location")
6717               || aTrsfArg.StartsWith ("-loc"))
6718         {
6719           isTrsfSet = Standard_True;
6720           if (aTrsfArgIter + 3 >= theArgNb
6721           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
6722           {
6723             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6724             return 1;
6725           }
6726           aTrsfArgIter += 3;
6727         }
6728         else if (aTrsfArg.StartsWith ("-scale"))
6729         {
6730           isTrsfSet = Standard_True;
6731           if (++aTrsfArgIter >= theArgNb)
6732           {
6733             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6734             return 1;
6735           }
6736
6737           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
6738           if (!aScaleStr.IsRealValue())
6739           {
6740             std::cout << "Syntax error at " << aTrsfArg << ".\n";
6741             return 1;
6742           }
6743           aScales[anIndex] = aScaleStr.RealValue();
6744         }
6745         else
6746         {
6747           anArgIter = aTrsfArgIter - 1;
6748           break;
6749         }
6750       }
6751       if (!isTrsfSet)
6752       {
6753         std::cout << "Syntax error at " << anArg << ".\n";
6754         return 1;
6755       }
6756       else if (aTrsfArgIter >= theArgNb)
6757       {
6758         anArgIter = theArgNb;
6759       }
6760
6761       aTrsfs[0].SetRotation        (aRotQuats[0]);
6762       aTrsfs[1].SetRotation        (aRotQuats[1]);
6763       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
6764       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
6765       aTrsfs[0].SetScaleFactor     (aScales[0]);
6766       aTrsfs[1].SetScaleFactor     (aScales[1]);
6767
6768       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
6769       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
6770     }
6771     else if (anArg == "-viewtrsf"
6772           || anArg == "-view")
6773     {
6774       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
6775       if (aCamAnimation.IsNull())
6776       {
6777         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
6778         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
6779       }
6780
6781       Handle(Graphic3d_Camera) aCams[2] =
6782       {
6783         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
6784         new Graphic3d_Camera (aCamAnimation->View()->Camera())
6785       };
6786
6787       Standard_Boolean isTrsfSet = Standard_False;
6788       Standard_Integer aViewArgIter = anArgIter + 1;
6789       for (; aViewArgIter < theArgNb; ++aViewArgIter)
6790       {
6791         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
6792         aViewArg.LowerCase();
6793         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
6794         if (aViewArg.StartsWith ("-scale"))
6795         {
6796           isTrsfSet = Standard_True;
6797           if (++aViewArgIter >= theArgNb)
6798           {
6799             std::cout << "Syntax error at " << anArg << ".\n";
6800             return 1;
6801           }
6802
6803           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
6804           if (!aScaleStr.IsRealValue())
6805           {
6806             std::cout << "Syntax error at " << aViewArg << ".\n";
6807             return 1;
6808           }
6809           Standard_Real aScale = aScaleStr.RealValue();
6810           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
6811           aCams[anIndex]->SetScale (aScale);
6812         }
6813         else if (aViewArg.StartsWith ("-eye")
6814               || aViewArg.StartsWith ("-center")
6815               || aViewArg.StartsWith ("-at")
6816               || aViewArg.StartsWith ("-up"))
6817         {
6818           isTrsfSet = Standard_True;
6819           gp_XYZ anXYZ;
6820           if (aViewArgIter + 3 >= theArgNb
6821           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
6822           {
6823             std::cout << "Syntax error at " << aViewArg << ".\n";
6824             return 1;
6825           }
6826           aViewArgIter += 3;
6827
6828           if (aViewArg.StartsWith ("-eye"))
6829           {
6830             aCams[anIndex]->SetEye (anXYZ);
6831           }
6832           else if (aViewArg.StartsWith ("-center")
6833                 || aViewArg.StartsWith ("-at"))
6834           {
6835             aCams[anIndex]->SetCenter (anXYZ);
6836           }
6837           else if (aViewArg.StartsWith ("-up"))
6838           {
6839             aCams[anIndex]->SetUp (anXYZ);
6840           }
6841         }
6842         else
6843         {
6844           anArgIter = aViewArgIter - 1;
6845           break;
6846         }
6847       }
6848       if (!isTrsfSet)
6849       {
6850         std::cout << "Syntax error at " << anArg << ".\n";
6851         return 1;
6852       }
6853       else if (aViewArgIter >= theArgNb)
6854       {
6855         anArgIter = theArgNb;
6856       }
6857
6858       aCamAnimation->SetCameraStart(aCams[0]);
6859       aCamAnimation->SetCameraEnd  (aCams[1]);
6860     }
6861     else
6862     {
6863       std::cout << "Syntax error at " << anArg << ".\n";
6864       return 1;
6865     }
6866   }
6867
6868   if (!toPlay)
6869   {
6870     return 0;
6871   }
6872
6873   // Start animation timeline and process frame updating.
6874   TheIsAnimating = Standard_True;
6875   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
6876   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
6877   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
6878   if (isFreeCamera)
6879   {
6880     aView->Camera()->Copy (aCameraBack);
6881   }
6882
6883   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
6884   if (aFpsNum <= 0)
6885   {
6886     while (!anAnimation->IsStopped())
6887     {
6888       aCameraBack->Copy (aView->Camera());
6889       const Standard_Real aPts = anAnimation->UpdateTimer();
6890       if (isFreeCamera)
6891       {
6892         aView->Camera()->Copy (aCameraBack);
6893       }
6894
6895       if (aPts >= anUpperPts)
6896       {
6897         anAnimation->Pause();
6898         break;
6899       }
6900
6901       if (aView->IsInvalidated())
6902       {
6903         aView->Redraw();
6904       }
6905       else
6906       {
6907         aView->RedrawImmediate();
6908       }
6909
6910       if (!isLockLoop)
6911       {
6912         // handle user events
6913         theDI.Eval ("after 1 set waiter 1");
6914         theDI.Eval ("vwait waiter");
6915       }
6916       if (!TheIsAnimating)
6917       {
6918         anAnimation->Pause();
6919         theDI << aPts;
6920         break;
6921       }
6922     }
6923
6924     if (aView->IsInvalidated())
6925     {
6926       aView->Redraw();
6927     }
6928     else
6929     {
6930       aView->RedrawImmediate();
6931     }
6932   }
6933   else
6934   {
6935     OSD_Timer aPerfTimer;
6936     aPerfTimer.Start();
6937
6938     // Manage frame-rated animation here
6939     Standard_Real aPts = aPlayStartTime;
6940     int64_t aNbFrames = 0;
6941     for (; aPts <= anUpperPts;)
6942     {
6943       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aFpsDen) / Standard_Real(aFpsNum)) * Standard_Real(aNbFrames));
6944       aPts = aPlayStartTime + aRecPts;
6945       ++aNbFrames;
6946       if (!anAnimation->Update (aPts))
6947       {
6948         break;
6949       }
6950
6951       aView->Redraw();
6952     }
6953
6954     aPerfTimer.Stop();
6955     anAnimation->Stop();
6956     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
6957     theDI << "Average FPS: " << aRecFps << "\n"
6958           << "Nb. Frames: "  << Standard_Real(aNbFrames);
6959
6960     aView->Redraw();
6961   }
6962
6963   aView->SetImmediateUpdate (wasImmediateUpdate);
6964   TheIsAnimating = Standard_False;
6965   return 0;
6966 }
6967
6968
6969 //=======================================================================
6970 //function : VChangeSelected
6971 //purpose  : Adds the shape to selection or remove one from it
6972 //=======================================================================
6973 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
6974                                 Standard_Integer argc,
6975                                 const char ** argv)
6976 {
6977   if(argc != 2)
6978   {
6979     di<<"Usage : " << argv[0] << " shape \n";
6980     return 1;
6981   }
6982   //get AIS_Shape:
6983   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6984   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
6985   TCollection_AsciiString aName(argv[1]);
6986   Handle(AIS_InteractiveObject) anAISObject;
6987
6988   if(!aMap.IsBound2(aName))
6989   {
6990     di<<"Use 'vdisplay' before";
6991     return 1;
6992   }
6993   else
6994   {
6995     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
6996     if(anAISObject.IsNull()){
6997       di<<"No interactive object \n";
6998       return 1;
6999     }
7000
7001     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7002   }
7003   return 0;
7004 }
7005
7006 //=======================================================================
7007 //function : VNbSelected
7008 //purpose  : Returns number of selected objects
7009 //=======================================================================
7010 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7011                                 Standard_Integer argc,
7012                                 const char ** argv)
7013 {
7014   if(argc != 1)
7015   {
7016     di << "Usage : " << argv[0] << "\n";
7017     return 1;
7018   }
7019   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7020   if(aContext.IsNull())
7021   {
7022     di << "use 'vinit' command before " << argv[0] << "\n";
7023     return 1;
7024   }
7025   di << aContext->NbSelected() << "\n";
7026   return 0;
7027 }
7028
7029 //=======================================================================
7030 //function : VPurgeDisplay
7031 //purpose  : Switches altialiasing on or off
7032 //=======================================================================
7033 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7034                                 Standard_Integer argc,
7035                                 const char ** argv)
7036 {
7037   if (argc > 1)
7038   {
7039     di << "Usage : " << argv[0] << "\n";
7040     return 1;
7041   }
7042   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7043   if (aContext.IsNull())
7044   {
7045     di << "use 'vinit' command before " << argv[0] << "\n";
7046     return 1;
7047   }
7048
7049   di << aContext->PurgeDisplay() << "\n";
7050   return 0;
7051 }
7052
7053 //=======================================================================
7054 //function : VSetViewSize
7055 //purpose  :
7056 //=======================================================================
7057 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7058                                 Standard_Integer argc,
7059                                 const char ** argv)
7060 {
7061   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7062   if(aContext.IsNull())
7063   {
7064     di << "use 'vinit' command before " << argv[0] << "\n";
7065     return 1;
7066   }
7067   if(argc != 2)
7068   {
7069     di<<"Usage : " << argv[0] << " Size\n";
7070     return 1;
7071   }
7072   Standard_Real aSize = Draw::Atof (argv[1]);
7073   if (aSize <= 0.)
7074   {
7075     di<<"Bad Size value  : " << aSize << "\n";
7076     return 1;
7077   }
7078
7079   Handle(V3d_View) aView = ViewerTest::CurrentView();
7080   aView->SetSize(aSize);
7081   return 0;
7082 }
7083
7084 //=======================================================================
7085 //function : VMoveView
7086 //purpose  :
7087 //=======================================================================
7088 static Standard_Integer VMoveView (Draw_Interpretor& di,
7089                                 Standard_Integer argc,
7090                                 const char ** argv)
7091 {
7092   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7093   if(aContext.IsNull())
7094   {
7095     di << "use 'vinit' command before " << argv[0] << "\n";
7096     return 1;
7097   }
7098   if(argc < 4 || argc > 5)
7099   {
7100     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7101     return 1;
7102   }
7103   Standard_Real Dx = Draw::Atof (argv[1]);
7104   Standard_Real Dy = Draw::Atof (argv[2]);
7105   Standard_Real Dz = Draw::Atof (argv[3]);
7106   Standard_Boolean aStart = Standard_True;
7107   if (argc == 5)
7108   {
7109       aStart = (Draw::Atoi (argv[4]) > 0);
7110   }
7111
7112   Handle(V3d_View) aView = ViewerTest::CurrentView();
7113   aView->Move(Dx,Dy,Dz,aStart);
7114   return 0;
7115 }
7116
7117 //=======================================================================
7118 //function : VTranslateView
7119 //purpose  :
7120 //=======================================================================
7121 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7122                                 Standard_Integer argc,
7123                                 const char ** argv)
7124 {
7125   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7126   if(aContext.IsNull())
7127   {
7128     di << "use 'vinit' command before " << argv[0] << "\n";
7129     return 1;
7130   }
7131   if(argc < 4 || argc > 5)
7132   {
7133     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7134     return 1;
7135   }
7136   Standard_Real Dx = Draw::Atof (argv[1]);
7137   Standard_Real Dy = Draw::Atof (argv[2]);
7138   Standard_Real Dz = Draw::Atof (argv[3]);
7139   Standard_Boolean aStart = Standard_True;
7140   if (argc == 5)
7141   {
7142       aStart = (Draw::Atoi (argv[4]) > 0);
7143   }
7144
7145   Handle(V3d_View) aView = ViewerTest::CurrentView();
7146   aView->Translate(Dx,Dy,Dz,aStart);
7147   return 0;
7148 }
7149
7150 //=======================================================================
7151 //function : VTurnView
7152 //purpose  :
7153 //=======================================================================
7154 static Standard_Integer VTurnView (Draw_Interpretor& di,
7155                                 Standard_Integer argc,
7156                                 const char ** argv)
7157 {
7158   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7159   if(aContext.IsNull()) {
7160     di << "use 'vinit' command before " << argv[0] << "\n";
7161     return 1;
7162   }
7163   if(argc < 4 || argc > 5){
7164     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7165     return 1;
7166   }
7167   Standard_Real Ax = Draw::Atof (argv[1]);
7168   Standard_Real Ay = Draw::Atof (argv[2]);
7169   Standard_Real Az = Draw::Atof (argv[3]);
7170   Standard_Boolean aStart = Standard_True;
7171   if (argc == 5)
7172   {
7173       aStart = (Draw::Atoi (argv[4]) > 0);
7174   }
7175
7176   Handle(V3d_View) aView = ViewerTest::CurrentView();
7177   aView->Turn(Ax,Ay,Az,aStart);
7178   return 0;
7179 }
7180
7181 //==============================================================================
7182 //function : VTextureEnv
7183 //purpose  : ENables or disables environment mapping
7184 //==============================================================================
7185 class OCC_TextureEnv : public Graphic3d_TextureEnv
7186 {
7187 public:
7188   OCC_TextureEnv(const Standard_CString FileName);
7189   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7190   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7191                             const Standard_Boolean theModulateFlag,
7192                             const Graphic3d_TypeOfTextureFilter theFilter,
7193                             const Standard_ShortReal theXScale,
7194                             const Standard_ShortReal theYScale,
7195                             const Standard_ShortReal theXShift,
7196                             const Standard_ShortReal theYShift,
7197                             const Standard_ShortReal theAngle);
7198   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7199 };
7200 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7201
7202 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7203   : Graphic3d_TextureEnv(theFileName)
7204 {
7205 }
7206
7207 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7208   : Graphic3d_TextureEnv(theTexId)
7209 {
7210 }
7211
7212 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7213                                           const Standard_Boolean theModulateFlag,
7214                                           const Graphic3d_TypeOfTextureFilter theFilter,
7215                                           const Standard_ShortReal theXScale,
7216                                           const Standard_ShortReal theYScale,
7217                                           const Standard_ShortReal theXShift,
7218                                           const Standard_ShortReal theYShift,
7219                                           const Standard_ShortReal theAngle)
7220 {
7221   myParams->SetRepeat     (theRepeatFlag);
7222   myParams->SetModulate   (theModulateFlag);
7223   myParams->SetFilter     (theFilter);
7224   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7225   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7226   myParams->SetRotation   (theAngle);
7227 }
7228
7229 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7230 {
7231   // get the active view
7232   Handle(V3d_View) aView = ViewerTest::CurrentView();
7233   if (aView.IsNull())
7234   {
7235     std::cerr << "No active view. Please call vinit.\n";
7236     return 1;
7237   }
7238
7239   // Checking the input arguments
7240   Standard_Boolean anEnableFlag = Standard_False;
7241   Standard_Boolean isOk         = theArgNb >= 2;
7242   if (isOk)
7243   {
7244     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7245     anEnableFlag = anEnableOpt.IsEqual("on");
7246     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7247   }
7248   if (anEnableFlag)
7249   {
7250     isOk = (theArgNb == 3 || theArgNb == 11);
7251     if (isOk)
7252     {
7253       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7254       isOk = (!aTextureOpt.IsIntegerValue() ||
7255              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7256
7257       if (isOk && theArgNb == 11)
7258       {
7259         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7260                                 aModulateOpt(theArgVec[4]),
7261                                 aFilterOpt  (theArgVec[5]),
7262                                 aSScaleOpt  (theArgVec[6]),
7263                                 aTScaleOpt  (theArgVec[7]),
7264                                 aSTransOpt  (theArgVec[8]),
7265                                 aTTransOpt  (theArgVec[9]),
7266                                 anAngleOpt  (theArgVec[10]);
7267         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7268                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7269                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7270                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7271                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7272                 anAngleOpt.IsRealValue());
7273       }
7274     }
7275   }
7276
7277   if (!isOk)
7278   {
7279     std::cerr << "Usage :" << std::endl;
7280     std::cerr << theArgVec[0] << " off" << std::endl;
7281     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;
7282     return 1;
7283   }
7284
7285   if (anEnableFlag)
7286   {
7287     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7288     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7289                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7290                                      new OCC_TextureEnv(theArgVec[2]);
7291
7292     if (theArgNb == 11)
7293     {
7294       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7295       aTexEnv->SetTextureParameters(
7296         aRepeatOpt.  IsEqual("repeat"),
7297         aModulateOpt.IsEqual("modulate"),
7298         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7299                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7300                                                                            Graphic3d_TOTF_TRILINEAR,
7301         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7302         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7303         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7304         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7305         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7306         );
7307     }
7308     aView->SetTextureEnv(aTexEnv);
7309   }
7310   else // Disabling environment mapping
7311   {
7312     Handle(Graphic3d_TextureEnv) aTexture;
7313     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7314   }
7315
7316   aView->Redraw();
7317   return 0;
7318 }
7319
7320 namespace
7321 {
7322   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
7323
7324   //! Remove registered clipping plane from all views and objects.
7325   static void removePlane (MapOfPlanes& theRegPlanes,
7326                            const TCollection_AsciiString& theName)
7327   {
7328     Handle(Graphic3d_ClipPlane) aClipPlane;
7329     if (!theRegPlanes.Find (theName, aClipPlane))
7330     {
7331       std::cout << "Warning: no such plane.\n";
7332       return;
7333     }
7334
7335     theRegPlanes.UnBind (theName);
7336     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
7337          anIObjIt.More(); anIObjIt.Next())
7338     {
7339       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
7340       aPrs->RemoveClipPlane (aClipPlane);
7341     }
7342
7343     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
7344          aViewIt.More(); aViewIt.Next())
7345     {
7346       const Handle(V3d_View)& aView = aViewIt.Key2();
7347       aView->RemoveClipPlane(aClipPlane);
7348     }
7349
7350     ViewerTest::RedrawAllViews();
7351   }
7352 }
7353
7354 //===============================================================================================
7355 //function : VClipPlane
7356 //purpose  :
7357 //===============================================================================================
7358 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7359 {
7360   // use short-cut for created clip planes map of created (or "registered by name") clip planes
7361   static MapOfPlanes aRegPlanes;
7362
7363   if (theArgsNb < 2)
7364   {
7365     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
7366     {
7367       theDi << aPlaneIter.Key() << " ";
7368     }
7369     return 0;
7370   }
7371
7372   TCollection_AsciiString aCommand (theArgVec[1]);
7373   aCommand.LowerCase();
7374   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
7375   if (anActiveView.IsNull())
7376   {
7377     std::cout << "Error: no active view.\n";
7378     return 1;
7379   }
7380
7381   // print maximum number of planes for current viewer
7382   if (aCommand == "-maxplanes"
7383    || aCommand == "maxplanes")
7384   {
7385     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
7386           << " plane slots provided by driver.\n";
7387     return 0;
7388   }
7389
7390   // create / delete plane instance
7391   if (aCommand == "-create"
7392    || aCommand == "create"
7393    || aCommand == "-delete"
7394    || aCommand == "delete"
7395    || aCommand == "-clone"
7396    || aCommand == "clone")
7397   {
7398     if (theArgsNb < 3)
7399     {
7400       std::cout << "Syntax error: plane name is required.\n";
7401       return 1;
7402     }
7403
7404     Standard_Boolean toCreate = aCommand == "-create"
7405                              || aCommand == "create";
7406     Standard_Boolean toClone  = aCommand == "-clone"
7407                              || aCommand == "clone";
7408     Standard_Boolean toDelete = aCommand == "-delete"
7409                              || aCommand == "delete";
7410     TCollection_AsciiString aPlane (theArgVec[2]);
7411
7412     if (toCreate)
7413     {
7414       if (aRegPlanes.IsBound (aPlane))
7415       {
7416         std::cout << "Warning: existing plane has been overridden.\n";
7417         toDelete = true;
7418       }
7419       else
7420       {
7421         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7422         return 0;
7423       }
7424     }
7425     else if (toClone) // toClone
7426     {
7427       if (!aRegPlanes.IsBound (aPlane))
7428       {
7429         std::cout << "Error: no such plane.\n";
7430         return 1;
7431       }
7432       else if (theArgsNb < 4)
7433       {
7434         std::cout << "Syntax error: enter name for new plane.\n";
7435         return 1;
7436       }
7437
7438       TCollection_AsciiString aClone (theArgVec[3]);
7439       if (aRegPlanes.IsBound (aClone))
7440       {
7441         std::cout << "Error: plane name is in use.\n";
7442         return 1;
7443       }
7444
7445       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
7446
7447       aRegPlanes.Bind (aClone, aClipPlane->Clone());
7448       return 0;
7449     }
7450
7451     if (toDelete)
7452     {
7453       if (aPlane == "ALL"
7454        || aPlane == "all"
7455        || aPlane == "*")
7456       {
7457         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
7458         {
7459           aPlane = aPlaneIter.Key();
7460           removePlane (aRegPlanes, aPlane);
7461           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
7462         }
7463       }
7464       else
7465       {
7466         removePlane (aRegPlanes, aPlane);
7467       }
7468     }
7469
7470     if (toCreate)
7471     {
7472       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
7473     }
7474     return 0;
7475   }
7476
7477   // set / unset plane command
7478   if (aCommand == "set"
7479    || aCommand == "unset")
7480   {
7481     if (theArgsNb < 5)
7482     {
7483       std::cout << "Syntax error: need more arguments.\n";
7484       return 1;
7485     }
7486
7487     // redirect to new syntax
7488     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
7489     anArgVec.SetValue (1, theArgVec[0]);
7490     anArgVec.SetValue (2, theArgVec[2]);
7491     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
7492     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
7493     {
7494       anArgVec.SetValue (anIt, theArgVec[anIt]);
7495     }
7496
7497     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
7498   }
7499
7500   // change plane command
7501   TCollection_AsciiString aPlaneName;
7502   Handle(Graphic3d_ClipPlane) aClipPlane;
7503   Standard_Integer anArgIter = 0;
7504   if (aCommand == "-change"
7505    || aCommand == "change")
7506   {
7507     // old syntax support
7508     if (theArgsNb < 3)
7509     {
7510       std::cout << "Syntax error: need more arguments.\n";
7511       return 1;
7512     }
7513
7514     anArgIter  = 3;
7515     aPlaneName = theArgVec[2];
7516     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
7517     {
7518       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
7519       return 1;
7520     }
7521   }
7522   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
7523   {
7524     anArgIter  = 2;
7525     aPlaneName = theArgVec[1];
7526   }
7527   else
7528   {
7529     anArgIter  = 2;
7530     aPlaneName = theArgVec[1];
7531     aClipPlane = new Graphic3d_ClipPlane();
7532     aRegPlanes.Bind (aPlaneName, aClipPlane);
7533     theDi << "Created new plane " << aPlaneName << ".\n";
7534   }
7535
7536   if (theArgsNb - anArgIter < 1)
7537   {
7538     std::cout << "Syntax error: need more arguments.\n";
7539     return 1;
7540   }
7541
7542   for (; anArgIter < theArgsNb; ++anArgIter)
7543   {
7544     const char**     aChangeArgs   = theArgVec + anArgIter;
7545     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
7546     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
7547     aChangeArg.LowerCase();
7548
7549     Standard_Boolean toEnable = Standard_True;
7550     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
7551     {
7552       aClipPlane->SetOn (toEnable);
7553     }
7554     else if (aChangeArg == "-equation"
7555           || aChangeArg == "equation")
7556     {
7557       if (aNbChangeArgs < 5)
7558       {
7559         std::cout << "Syntax error: need more arguments.\n";
7560         return 1;
7561       }
7562
7563       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
7564       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
7565       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
7566       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
7567       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
7568       anArgIter += 4;
7569     }
7570     else if (aChangeArg == "-capping"
7571           || aChangeArg == "capping")
7572     {
7573       if (aNbChangeArgs < 2)
7574       {
7575         std::cout << "Syntax error: need more arguments.\n";
7576         return 1;
7577       }
7578
7579       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7580       {
7581         aClipPlane->SetCapping (toEnable);
7582         anArgIter += 1;
7583       }
7584       else
7585       {
7586         // just skip otherwise (old syntax)
7587       }
7588     }
7589     else if (aChangeArg == "-useobjectmaterial"
7590           || aChangeArg == "-useobjectmat"
7591           || aChangeArg == "-useobjmat"
7592           || aChangeArg == "-useobjmaterial")
7593     {
7594       if (aNbChangeArgs < 2)
7595       {
7596         std::cout << "Syntax error: need more arguments.\n";
7597         return 1;
7598       }
7599
7600       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7601       {
7602         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
7603         anArgIter += 1;
7604       }
7605     }
7606     else if (aChangeArg == "-useobjecttexture"
7607           || aChangeArg == "-useobjecttex"
7608           || aChangeArg == "-useobjtexture"
7609           || aChangeArg == "-useobjtex")
7610     {
7611       if (aNbChangeArgs < 2)
7612       {
7613         std::cout << "Syntax error: need more arguments.\n";
7614         return 1;
7615       }
7616
7617       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7618       {
7619         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
7620         anArgIter += 1;
7621       }
7622     }
7623     else if (aChangeArg == "-useobjectshader"
7624           || aChangeArg == "-useobjshader")
7625     {
7626       if (aNbChangeArgs < 2)
7627       {
7628         std::cout << "Syntax error: need more arguments.\n";
7629         return 1;
7630       }
7631
7632       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
7633       {
7634         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
7635         anArgIter += 1;
7636       }
7637     }
7638     else if (aChangeArg == "-color"
7639           || aChangeArg == "color")
7640     {
7641       Quantity_Color aColor;
7642       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
7643                                                            aChangeArgs + 1,
7644                                                            aColor);
7645       if (aNbParsed == 0)
7646       {
7647         std::cout << "Syntax error: need more arguments.\n";
7648         return 1;
7649       }
7650
7651       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
7652       aMat.SetAmbientColor (aColor);
7653       aMat.SetDiffuseColor (aColor);
7654       aClipPlane->SetCappingMaterial (aMat);
7655       anArgIter += aNbParsed;
7656     }
7657     else if (aChangeArg == "-texname"
7658           || aChangeArg == "texname")
7659     {
7660       if (aNbChangeArgs < 2)
7661       {
7662         std::cout << "Syntax error: need more arguments.\n";
7663         return 1;
7664       }
7665
7666       TCollection_AsciiString aTextureName (aChangeArgs[1]);
7667       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
7668       if (!aTexture->IsDone())
7669       {
7670         aClipPlane->SetCappingTexture (NULL);
7671       }
7672       else
7673       {
7674         aTexture->EnableModulate();
7675         aTexture->EnableRepeat();
7676         aClipPlane->SetCappingTexture (aTexture);
7677       }
7678       anArgIter += 1;
7679     }
7680     else if (aChangeArg == "-texscale"
7681           || aChangeArg == "texscale")
7682     {
7683       if (aClipPlane->CappingTexture().IsNull())
7684       {
7685         std::cout << "Error: no texture is set.\n";
7686         return 1;
7687       }
7688
7689       if (aNbChangeArgs < 3)
7690       {
7691         std::cout << "Syntax error: need more arguments.\n";
7692         return 1;
7693       }
7694
7695       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7696       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7697       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
7698       anArgIter += 2;
7699     }
7700     else if (aChangeArg == "-texorigin"
7701           || aChangeArg == "texorigin") // texture origin
7702     {
7703       if (aClipPlane->CappingTexture().IsNull())
7704       {
7705         std::cout << "Error: no texture is set.\n";
7706         return 1;
7707       }
7708
7709       if (aNbChangeArgs < 3)
7710       {
7711         std::cout << "Syntax error: need more arguments.\n";
7712         return 1;
7713       }
7714
7715       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7716       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
7717
7718       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
7719       anArgIter += 2;
7720     }
7721     else if (aChangeArg == "-texrotate"
7722           || aChangeArg == "texrotate") // texture rotation
7723     {
7724       if (aClipPlane->CappingTexture().IsNull())
7725       {
7726         std::cout << "Error: no texture is set.\n";
7727         return 1;
7728       }
7729
7730       if (aNbChangeArgs < 2)
7731       {
7732         std::cout << "Syntax error: need more arguments.\n";
7733         return 1;
7734       }
7735
7736       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
7737       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
7738       anArgIter += 1;
7739     }
7740     else if (aChangeArg == "-hatch"
7741           || aChangeArg == "hatch")
7742     {
7743       if (aNbChangeArgs < 2)
7744       {
7745         std::cout << "Syntax error: need more arguments.\n";
7746         return 1;
7747       }
7748
7749       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
7750       aHatchStr.LowerCase();
7751       if (aHatchStr == "on")
7752       {
7753         aClipPlane->SetCappingHatchOn();
7754       }
7755       else if (aHatchStr == "off")
7756       {
7757         aClipPlane->SetCappingHatchOff();
7758       }
7759       else
7760       {
7761         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
7762       }
7763       anArgIter += 1;
7764     }
7765     else if (aChangeArg == "-delete"
7766           || aChangeArg == "delete")
7767     {
7768       removePlane (aRegPlanes, aPlaneName);
7769       return 0;
7770     }
7771     else if (aChangeArg == "-set"
7772           || aChangeArg == "-unset")
7773     {
7774       // set / unset plane command
7775       Standard_Boolean toSet = aChangeArg == "-set";
7776       Standard_Integer anIt = 1;
7777       for (; anIt < aNbChangeArgs; ++anIt)
7778       {
7779         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
7780         if (anEntityName.IsEmpty()
7781          || anEntityName.Value (1) == '-')
7782         {
7783           break;
7784         }
7785         else if (ViewerTest_myViews.IsBound1 (anEntityName))
7786         {
7787           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
7788           if (toSet)
7789           {
7790             aView->AddClipPlane (aClipPlane);
7791           }
7792           else
7793           {
7794             aView->RemoveClipPlane (aClipPlane);
7795           }
7796           continue;
7797         }
7798         else if (GetMapOfAIS().IsBound2 (anEntityName))
7799         {
7800           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
7801           if (toSet)
7802           {
7803             aIObj->AddClipPlane (aClipPlane);
7804           }
7805           else
7806           {
7807             aIObj->RemoveClipPlane (aClipPlane);
7808           }
7809         }
7810         else
7811         {
7812           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
7813           return 1;
7814         }
7815       }
7816
7817       if (anIt == 1)
7818       {
7819         // apply to active view
7820         if (toSet)
7821         {
7822           anActiveView->AddClipPlane (aClipPlane);
7823         }
7824         else
7825         {
7826           anActiveView->RemoveClipPlane (aClipPlane);
7827         }
7828       }
7829       else
7830       {
7831         anArgIter = anArgIter + anIt - 1;
7832       }
7833     }
7834     else
7835     {
7836       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
7837       return 1;
7838     }
7839   }
7840
7841   ViewerTest::RedrawAllViews();
7842   return 0;
7843 }
7844
7845 //===============================================================================================
7846 //function : VZRange
7847 //purpose  :
7848 //===============================================================================================
7849 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7850 {
7851   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7852
7853   if (aCurrentView.IsNull())
7854   {
7855     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7856     return 1;
7857   }
7858
7859   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
7860
7861   if (theArgsNb < 2)
7862   {
7863     theDi << "ZNear: " << aCamera->ZNear() << "\n";
7864     theDi << "ZFar: " << aCamera->ZFar() << "\n";
7865     return 0;
7866   }
7867
7868   if (theArgsNb == 3)
7869   {
7870     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
7871     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
7872
7873     if (aNewZNear >= aNewZFar)
7874     {
7875       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
7876       return 1;
7877     }
7878
7879     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
7880     {
7881       std::cout << theArgVec[0] << ": invalid arguments: ";
7882       std::cout << "znear, zfar should be positive for perspective camera.\n";
7883       return 1;
7884     }
7885
7886     aCamera->SetZRange (aNewZNear, aNewZFar);
7887   }
7888   else
7889   {
7890     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7891     return 1;
7892   }
7893
7894   aCurrentView->Redraw();
7895
7896   return 0;
7897 }
7898
7899 //===============================================================================================
7900 //function : VAutoZFit
7901 //purpose  :
7902 //===============================================================================================
7903 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7904 {
7905   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
7906
7907   if (aCurrentView.IsNull())
7908   {
7909     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
7910     return 1;
7911   }
7912
7913   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
7914
7915   if (theArgsNb > 3)
7916   {
7917     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
7918     return 1;
7919   }
7920
7921   if (theArgsNb < 2)
7922   {
7923     theDi << "Auto z-fit mode: \n"
7924           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
7925           << "Scale: " << aScale << "\n";
7926     return 0;
7927   }
7928
7929   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
7930
7931   if (theArgsNb >= 3)
7932   {
7933     aScale = Draw::Atoi (theArgVec[2]);
7934   }
7935
7936   aCurrentView->SetAutoZFitMode (isOn, aScale);
7937   aCurrentView->AutoZFit();
7938   aCurrentView->Redraw();
7939
7940   return 0;
7941 }
7942
7943 //! Auxiliary function to print projection type
7944 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
7945 {
7946   switch (theProjType)
7947   {
7948     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
7949     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
7950     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
7951     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
7952     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
7953   }
7954   return "UNKNOWN";
7955 }
7956
7957 //===============================================================================================
7958 //function : VCamera
7959 //purpose  :
7960 //===============================================================================================
7961 static int VCamera (Draw_Interpretor& theDI,
7962                     Standard_Integer  theArgsNb,
7963                     const char**      theArgVec)
7964 {
7965   Handle(V3d_View) aView = ViewerTest::CurrentView();
7966   if (aView.IsNull())
7967   {
7968     std::cout << "Error: no active view.\n";
7969     return 1;
7970   }
7971
7972   Handle(Graphic3d_Camera) aCamera = aView->Camera();
7973   if (theArgsNb < 2)
7974   {
7975     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
7976     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
7977     theDI << "Distance:   " << aCamera->Distance() << "\n";
7978     theDI << "IOD:        " << aCamera->IOD() << "\n";
7979     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
7980     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
7981     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
7982     return 0;
7983   }
7984
7985   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7986   {
7987     Standard_CString        anArg = theArgVec[anArgIter];
7988     TCollection_AsciiString anArgCase (anArg);
7989     anArgCase.LowerCase();
7990     if (anArgCase == "-proj"
7991      || anArgCase == "-projection"
7992      || anArgCase == "-projtype"
7993      || anArgCase == "-projectiontype")
7994     {
7995       theDI << projTypeName (aCamera->ProjectionType()) << " ";
7996     }
7997     else if (anArgCase == "-ortho"
7998           || anArgCase == "-orthographic")
7999     {
8000       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8001     }
8002     else if (anArgCase == "-persp"
8003           || anArgCase == "-perspective"
8004           || anArgCase == "-perspmono"
8005           || anArgCase == "-perspectivemono"
8006           || anArgCase == "-mono")
8007     {
8008       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8009     }
8010     else if (anArgCase == "-stereo"
8011           || anArgCase == "-stereoscopic"
8012           || anArgCase == "-perspstereo"
8013           || anArgCase == "-perspectivestereo")
8014     {
8015       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8016     }
8017     else if (anArgCase == "-left"
8018           || anArgCase == "-lefteye"
8019           || anArgCase == "-monoleft"
8020           || anArgCase == "-monolefteye"
8021           || anArgCase == "-perpsleft"
8022           || anArgCase == "-perpslefteye")
8023     {
8024       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8025     }
8026     else if (anArgCase == "-right"
8027           || anArgCase == "-righteye"
8028           || anArgCase == "-monoright"
8029           || anArgCase == "-monorighteye"
8030           || anArgCase == "-perpsright")
8031     {
8032       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8033     }
8034     else if (anArgCase == "-dist"
8035           || anArgCase == "-distance")
8036     {
8037       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8038       if (anArgValue != NULL
8039       && *anArgValue != '-')
8040       {
8041         ++anArgIter;
8042         aCamera->SetDistance (Draw::Atof (anArgValue));
8043         continue;
8044       }
8045       theDI << aCamera->Distance() << " ";
8046     }
8047     else if (anArgCase == "-iod")
8048     {
8049       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8050       if (anArgValue != NULL
8051       && *anArgValue != '-')
8052       {
8053         ++anArgIter;
8054         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8055         continue;
8056       }
8057       theDI << aCamera->IOD() << " ";
8058     }
8059     else if (anArgCase == "-iodtype")
8060     {
8061       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8062       TCollection_AsciiString anValueCase (anArgValue);
8063       anValueCase.LowerCase();
8064       if (anValueCase == "abs"
8065        || anValueCase == "absolute")
8066       {
8067         ++anArgIter;
8068         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8069         continue;
8070       }
8071       else if (anValueCase == "rel"
8072             || anValueCase == "relative")
8073       {
8074         ++anArgIter;
8075         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8076         continue;
8077       }
8078       else if (*anArgValue != '-')
8079       {
8080         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8081         return 1;
8082       }
8083       switch (aCamera->GetIODType())
8084       {
8085         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8086         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8087       }
8088     }
8089     else if (anArgCase == "-zfocus")
8090     {
8091       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8092       if (anArgValue != NULL
8093       && *anArgValue != '-')
8094       {
8095         ++anArgIter;
8096         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8097         continue;
8098       }
8099       theDI << aCamera->ZFocus() << " ";
8100     }
8101     else if (anArgCase == "-zfocustype")
8102     {
8103       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8104       TCollection_AsciiString anValueCase (anArgValue);
8105       anValueCase.LowerCase();
8106       if (anValueCase == "abs"
8107        || anValueCase == "absolute")
8108       {
8109         ++anArgIter;
8110         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8111         continue;
8112       }
8113       else if (anValueCase == "rel"
8114             || anValueCase == "relative")
8115       {
8116         ++anArgIter;
8117         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8118         continue;
8119       }
8120       else if (*anArgValue != '-')
8121       {
8122         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8123         return 1;
8124       }
8125       switch (aCamera->ZFocusType())
8126       {
8127         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8128         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8129       }
8130     }
8131     else if (anArgCase == "-fov"
8132           || anArgCase == "-fovy")
8133     {
8134       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8135       if (anArgValue != NULL
8136       && *anArgValue != '-')
8137       {
8138         ++anArgIter;
8139         aCamera->SetFOVy (Draw::Atof (anArgValue));
8140         continue;
8141       }
8142       theDI << aCamera->FOVy() << " ";
8143     }
8144     else
8145     {
8146       std::cout << "Error: unknown argument '" << anArg << "'\n";
8147       return 1;
8148     }
8149   }
8150
8151   aView->AutoZFit();
8152   aView->Redraw();
8153
8154   return 0;
8155 }
8156
8157 //! Parse stereo output mode
8158 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8159                                          Graphic3d_StereoMode& theMode)
8160 {
8161   TCollection_AsciiString aFlag (theArg);
8162   aFlag.LowerCase();
8163   if (aFlag == "quadbuffer")
8164   {
8165     theMode = Graphic3d_StereoMode_QuadBuffer;
8166   }
8167   else if (aFlag == "anaglyph")
8168   {
8169     theMode = Graphic3d_StereoMode_Anaglyph;
8170   }
8171   else if (aFlag == "row"
8172         || aFlag == "rowinterlaced")
8173   {
8174     theMode = Graphic3d_StereoMode_RowInterlaced;
8175   }
8176   else if (aFlag == "col"
8177         || aFlag == "colinterlaced"
8178         || aFlag == "columninterlaced")
8179   {
8180     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8181   }
8182   else if (aFlag == "chess"
8183         || aFlag == "chessboard")
8184   {
8185     theMode = Graphic3d_StereoMode_ChessBoard;
8186   }
8187   else if (aFlag == "sbs"
8188         || aFlag == "sidebyside")
8189   {
8190     theMode = Graphic3d_StereoMode_SideBySide;
8191   }
8192   else if (aFlag == "ou"
8193         || aFlag == "overunder")
8194   {
8195     theMode = Graphic3d_StereoMode_OverUnder;
8196   }
8197   else if (aFlag == "pageflip"
8198         || aFlag == "softpageflip")
8199   {
8200     theMode = Graphic3d_StereoMode_SoftPageFlip;
8201   }
8202   else
8203   {
8204     return Standard_False;
8205   }
8206   return Standard_True;
8207 }
8208
8209 //! Parse anaglyph filter
8210 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8211                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8212 {
8213   TCollection_AsciiString aFlag (theArg);
8214   aFlag.LowerCase();
8215   if (aFlag == "redcyansimple")
8216   {
8217     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8218   }
8219   else if (aFlag == "redcyan"
8220         || aFlag == "redcyanoptimized")
8221   {
8222     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8223   }
8224   else if (aFlag == "yellowbluesimple")
8225   {
8226     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8227   }
8228   else if (aFlag == "yellowblue"
8229         || aFlag == "yellowblueoptimized")
8230   {
8231     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8232   }
8233   else if (aFlag == "greenmagenta"
8234         || aFlag == "greenmagentasimple")
8235   {
8236     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8237   }
8238   else
8239   {
8240     return Standard_False;
8241   }
8242   return Standard_True;
8243 }
8244
8245 //==============================================================================
8246 //function : VStereo
8247 //purpose  :
8248 //==============================================================================
8249
8250 static int VStereo (Draw_Interpretor& theDI,
8251                     Standard_Integer  theArgNb,
8252                     const char**      theArgVec)
8253 {
8254   Handle(V3d_View) aView = ViewerTest::CurrentView();
8255   if (theArgNb < 2)
8256   {
8257     if (aView.IsNull())
8258     {
8259       std::cout << "Error: no active viewer!\n";
8260       return 0;
8261     }
8262
8263     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8264     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8265     if (isActive)
8266     {
8267       TCollection_AsciiString aMode;
8268       switch (aView->RenderingParams().StereoMode)
8269       {
8270         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8271         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8272         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8273         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8274         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8275         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8276         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8277         case Graphic3d_StereoMode_Anaglyph  :
8278           aMode = "anaglyph";
8279           switch (aView->RenderingParams().AnaglyphFilter)
8280           {
8281             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8282             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8283             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8284             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8285             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8286             default: break;
8287           }
8288         default: break;
8289       }
8290       theDI << "Mode " << aMode << "\n";
8291     }
8292     return 0;
8293   }
8294
8295   Handle(Graphic3d_Camera) aCamera;
8296   Graphic3d_RenderingParams*   aParams   = NULL;
8297   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8298   if (!aView.IsNull())
8299   {
8300     aParams   = &aView->ChangeRenderingParams();
8301     aMode     = aParams->StereoMode;
8302     aCamera   = aView->Camera();
8303   }
8304
8305   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8306   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8307   {
8308     Standard_CString        anArg = theArgVec[anArgIter];
8309     TCollection_AsciiString aFlag (anArg);
8310     aFlag.LowerCase();
8311     if (anUpdateTool.parseRedrawMode (aFlag))
8312     {
8313       continue;
8314     }
8315     else if (aFlag == "0"
8316           || aFlag == "off")
8317     {
8318       if (++anArgIter < theArgNb)
8319       {
8320         std::cout << "Error: wrong number of arguments!\n";
8321         return 1;
8322       }
8323
8324       if (!aCamera.IsNull()
8325        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
8326       {
8327         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8328       }
8329       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
8330       return 0;
8331     }
8332     else if (aFlag == "1"
8333           || aFlag == "on")
8334     {
8335       if (++anArgIter < theArgNb)
8336       {
8337         std::cout << "Error: wrong number of arguments!\n";
8338         return 1;
8339       }
8340
8341       if (!aCamera.IsNull())
8342       {
8343         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8344       }
8345       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8346       return 0;
8347     }
8348     else if (aFlag == "-reverse"
8349           || aFlag == "-reversed"
8350           || aFlag == "-swap")
8351     {
8352       Standard_Boolean toEnable = Standard_True;
8353       if (++anArgIter < theArgNb
8354       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
8355       {
8356         --anArgIter;
8357       }
8358       aParams->ToReverseStereo = toEnable;
8359     }
8360     else if (aFlag == "-noreverse"
8361           || aFlag == "-noswap")
8362     {
8363       Standard_Boolean toDisable = Standard_True;
8364       if (++anArgIter < theArgNb
8365       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
8366       {
8367         --anArgIter;
8368       }
8369       aParams->ToReverseStereo = !toDisable;
8370     }
8371     else if (aFlag == "-mode"
8372           || aFlag == "-stereomode")
8373     {
8374       if (++anArgIter >= theArgNb
8375       || !parseStereoMode (theArgVec[anArgIter], aMode))
8376       {
8377         std::cout << "Error: syntax error at '" << anArg << "'\n";
8378         return 1;
8379       }
8380
8381       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8382       {
8383         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8384       }
8385     }
8386     else if (aFlag == "-anaglyph"
8387           || aFlag == "-anaglyphfilter")
8388     {
8389       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8390       if (++anArgIter >= theArgNb
8391       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
8392       {
8393         std::cout << "Error: syntax error at '" << anArg << "'\n";
8394         return 1;
8395       }
8396
8397       aMode = Graphic3d_StereoMode_Anaglyph;
8398       aParams->AnaglyphFilter = aFilter;
8399     }
8400     else if (parseStereoMode (anArg, aMode)) // short syntax
8401     {
8402       if (aMode == Graphic3d_StereoMode_QuadBuffer)
8403       {
8404         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
8405       }
8406     }
8407     else
8408     {
8409       std::cout << "Error: syntax error at '" << anArg << "'\n";
8410       return 1;
8411     }
8412   }
8413
8414   if (!aView.IsNull())
8415   {
8416     aParams->StereoMode = aMode;
8417     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8418   }
8419   return 0;
8420 }
8421
8422 //===============================================================================================
8423 //function : VDefaults
8424 //purpose  :
8425 //===============================================================================================
8426 static int VDefaults (Draw_Interpretor& theDi,
8427                       Standard_Integer  theArgsNb,
8428                       const char**      theArgVec)
8429 {
8430   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
8431   if (aCtx.IsNull())
8432   {
8433     std::cerr << "No active viewer!\n";
8434     return 1;
8435   }
8436
8437   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
8438   if (theArgsNb < 2)
8439   {
8440     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
8441     {
8442       theDi << "DeflType:           relative\n"
8443             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
8444     }
8445     else
8446     {
8447       theDi << "DeflType:           absolute\n"
8448             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
8449     }
8450     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
8451     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
8452     return 0;
8453   }
8454
8455   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8456   {
8457     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8458     anArg.UpperCase();
8459     if (anArg == "-ABSDEFL"
8460      || anArg == "-ABSOLUTEDEFLECTION"
8461      || anArg == "-DEFL"
8462      || anArg == "-DEFLECTION")
8463     {
8464       if (++anArgIter >= theArgsNb)
8465       {
8466         std::cout << "Error: wrong syntax at " << anArg << "\n";
8467         return 1;
8468       }
8469       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
8470       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
8471     }
8472     else if (anArg == "-RELDEFL"
8473           || anArg == "-RELATIVEDEFLECTION"
8474           || anArg == "-DEVCOEFF"
8475           || anArg == "-DEVIATIONCOEFF"
8476           || anArg == "-DEVIATIONCOEFFICIENT")
8477     {
8478       if (++anArgIter >= theArgsNb)
8479       {
8480         std::cout << "Error: wrong syntax at " << anArg << "\n";
8481         return 1;
8482       }
8483       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
8484       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
8485     }
8486     else if (anArg == "-ANGDEFL"
8487           || anArg == "-ANGULARDEFL"
8488           || anArg == "-ANGULARDEFLECTION")
8489     {
8490       if (++anArgIter >= theArgsNb)
8491       {
8492         std::cout << "Error: wrong syntax at " << anArg << "\n";
8493         return 1;
8494       }
8495       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
8496       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
8497     }
8498     else if (anArg == "-AUTOTR"
8499           || anArg == "-AUTOTRIANG"
8500           || anArg == "-AUTOTRIANGULATION")
8501     {
8502       if (++anArgIter >= theArgsNb)
8503       {
8504         std::cout << "Error: wrong syntax at " << anArg << "\n";
8505         return 1;
8506       }
8507       TCollection_AsciiString aValue (theArgVec[anArgIter]);
8508       aValue.LowerCase();
8509       if (aValue == "on"
8510        || aValue == "1")
8511       {
8512         aDefParams->SetAutoTriangulation (Standard_True);
8513       }
8514       else if (aValue == "off"
8515             || aValue == "0")
8516       {
8517         aDefParams->SetAutoTriangulation (Standard_False);
8518       }
8519     }
8520     else
8521     {
8522       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
8523     }
8524   }
8525
8526   return 0;
8527 }
8528
8529 //! Auxiliary method
8530 inline void addLight (const Handle(V3d_Light)& theLightNew,
8531                       const Standard_Boolean   theIsGlobal)
8532 {
8533   if (theLightNew.IsNull())
8534   {
8535     return;
8536   }
8537
8538   if (theIsGlobal)
8539   {
8540     ViewerTest::GetViewerFromContext()->SetLightOn (theLightNew);
8541   }
8542   else
8543   {
8544     ViewerTest::CurrentView()->SetLightOn (theLightNew);
8545   }
8546 }
8547
8548 //! Auxiliary method
8549 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
8550 {
8551   TCollection_AsciiString anArgNextCase (theArgNext);
8552   anArgNextCase.UpperCase();
8553   if (anArgNextCase.Length() > 5
8554    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
8555   {
8556     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
8557   }
8558   else
8559   {
8560     return theArgNext.IntegerValue();
8561   }
8562 }
8563
8564 //===============================================================================================
8565 //function : VLight
8566 //purpose  :
8567 //===============================================================================================
8568 static int VLight (Draw_Interpretor& theDi,
8569                    Standard_Integer  theArgsNb,
8570                    const char**      theArgVec)
8571 {
8572   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
8573   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
8574   if (aView.IsNull()
8575    || aViewer.IsNull())
8576   {
8577     std::cerr << "No active viewer!\n";
8578     return 1;
8579   }
8580
8581   Standard_Real anXYZ[3]   = {};
8582   Standard_Real anAtten[2] = {};
8583   if (theArgsNb < 2)
8584   {
8585     // print lights info
8586     Standard_Integer aLightId = 0;
8587     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
8588     {
8589       Handle(V3d_Light) aLight = aLightIter.Value();
8590       const Quantity_Color aColor = aLight->Color();
8591       theDi << "Light" << aLightId << "\n";
8592       switch (aLight->Type())
8593       {
8594         case V3d_AMBIENT:
8595         {
8596           theDi << "  Type:       Ambient\n";
8597           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8598           break;
8599         }
8600         case V3d_DIRECTIONAL:
8601         {
8602           Handle(V3d_DirectionalLight) aLightDir = Handle(V3d_DirectionalLight)::DownCast (aLight);
8603           theDi << "  Type:       Directional\n";
8604           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8605           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8606           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8607           if (!aLightDir.IsNull())
8608           {
8609             aLightDir->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8610             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8611             aLightDir->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8612             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8613           }
8614           break;
8615         }
8616         case V3d_POSITIONAL:
8617         {
8618           Handle(V3d_PositionalLight) aLightPos = Handle(V3d_PositionalLight)::DownCast (aLight);
8619           theDi << "  Type:       Positional\n";
8620           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8621           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8622           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
8623           if (!aLightPos.IsNull())
8624           {
8625             aLightPos->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8626             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8627             aLightPos->Attenuation (anAtten[0], anAtten[1]);
8628             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8629           }
8630           break;
8631         }
8632         case V3d_SPOT:
8633         {
8634           Handle(V3d_SpotLight) aLightSpot = Handle(V3d_SpotLight)::DownCast (aLight);
8635           theDi << "  Type:       Spot\n";
8636           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
8637           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
8638           if (!aLightSpot.IsNull())
8639           {
8640             aLightSpot->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
8641             theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8642             aLightSpot->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
8643             theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
8644             aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8645             theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
8646             theDi << "  Angle:      " << (aLightSpot->Angle() * 180.0 / M_PI) << "\n";
8647             theDi << "  Exponent:   " << aLightSpot->Concentration() << "\n";
8648           }
8649           break;
8650         }
8651         default:
8652         {
8653           theDi << "  Type:       UNKNOWN\n";
8654           break;
8655         }
8656       }
8657       theDi << "  Color:     " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << "\n";
8658     }
8659   }
8660
8661   Handle(V3d_Light) aLightNew;
8662   Handle(V3d_Light) aLightOld;
8663   Standard_Boolean  isGlobal = Standard_True;
8664   Standard_Boolean  toCreate = Standard_False;
8665   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8666   {
8667     Handle(V3d_Light)            aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
8668     Handle(V3d_AmbientLight)     aLightAmb  = Handle(V3d_AmbientLight)    ::DownCast (aLightCurr);
8669     Handle(V3d_DirectionalLight) aLightDir  = Handle(V3d_DirectionalLight)::DownCast (aLightCurr);
8670     Handle(V3d_PositionalLight)  aLightPos  = Handle(V3d_PositionalLight) ::DownCast (aLightCurr);
8671     Handle(V3d_SpotLight)        aLightSpot = Handle(V3d_SpotLight)       ::DownCast (aLightCurr);
8672
8673     TCollection_AsciiString aName, aValue;
8674     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
8675     TCollection_AsciiString anArgCase (anArg);
8676     anArgCase.UpperCase();
8677     if (anArgCase.IsEqual ("NEW")
8678      || anArgCase.IsEqual ("ADD")
8679      || anArgCase.IsEqual ("CREATE"))
8680     {
8681       toCreate = Standard_True;
8682     }
8683     else if (anArgCase.IsEqual ("GLOB")
8684           || anArgCase.IsEqual ("GLOBAL"))
8685     {
8686       isGlobal = Standard_True;
8687     }
8688     else if (anArgCase.IsEqual ("LOC")
8689           || anArgCase.IsEqual ("LOCAL"))
8690     {
8691       isGlobal = Standard_False;
8692     }
8693     else if (anArgCase.IsEqual ("DEF")
8694           || anArgCase.IsEqual ("DEFAULTS"))
8695     {
8696       toCreate = Standard_False;
8697       aViewer->SetDefaultLights();
8698     }
8699     else if (anArgCase.IsEqual ("CLR")
8700           || anArgCase.IsEqual ("CLEAR"))
8701     {
8702       toCreate = Standard_False;
8703       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
8704       {
8705         Handle(V3d_Light) aLight = aLightIter.Value();
8706         aViewer->DelLight (aLight);
8707         aLightIter = aView->ActiveLightIterator();
8708       }
8709     }
8710     else if (anArgCase.IsEqual ("AMB")
8711           || anArgCase.IsEqual ("AMBIENT")
8712           || anArgCase.IsEqual ("AMBLIGHT"))
8713     {
8714       addLight (aLightNew, isGlobal);
8715       if (!toCreate)
8716       {
8717         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8718         return 1;
8719       }
8720       toCreate  = Standard_False;
8721       aLightNew = new V3d_AmbientLight (aViewer);
8722     }
8723     else if (anArgCase.IsEqual ("DIRECTIONAL")
8724           || anArgCase.IsEqual ("DIRLIGHT"))
8725     {
8726       addLight (aLightNew, isGlobal);
8727       if (!toCreate)
8728       {
8729         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8730         return 1;
8731       }
8732       toCreate  = Standard_False;
8733       aLightNew = new V3d_DirectionalLight (aViewer);
8734     }
8735     else if (anArgCase.IsEqual ("SPOT")
8736           || anArgCase.IsEqual ("SPOTLIGHT"))
8737     {
8738       addLight (aLightNew, isGlobal);
8739       if (!toCreate)
8740       {
8741         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8742         return 1;
8743       }
8744       toCreate  = Standard_False;
8745       aLightNew = new V3d_SpotLight (aViewer, 0.0, 0.0, 0.0);
8746     }
8747     else if (anArgCase.IsEqual ("POSLIGHT")
8748           || anArgCase.IsEqual ("POSITIONAL"))
8749     {
8750       addLight (aLightNew, isGlobal);
8751       if (!toCreate)
8752       {
8753         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8754         return 1;
8755       }
8756       toCreate  = Standard_False;
8757       aLightNew = new V3d_PositionalLight (aViewer, 0.0, 0.0, 0.0);
8758     }
8759     else if (anArgCase.IsEqual ("CHANGE"))
8760     {
8761       addLight (aLightNew, isGlobal);
8762       aLightNew.Nullify();
8763       if (++anArgIt >= theArgsNb)
8764       {
8765         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8766         return 1;
8767       }
8768
8769       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
8770       Standard_Integer aLightIt = 0;
8771       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8772       {
8773         if (aLightIt == aLightId)
8774         {
8775           aLightOld = aLightIter.Value();
8776           break;
8777         }
8778       }
8779
8780       if (aLightOld.IsNull())
8781       {
8782         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
8783         return 1;
8784       }
8785     }
8786     else if (anArgCase.IsEqual ("DEL")
8787           || anArgCase.IsEqual ("DELETE"))
8788     {
8789       Handle(V3d_Light) aLightDel;
8790       if (++anArgIt >= theArgsNb)
8791       {
8792         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8793         return 1;
8794       }
8795
8796       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8797       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
8798       Standard_Integer aLightIt = 0;
8799       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
8800       {
8801         aLightDel = aLightIter.Value();
8802         if (aLightIt == aLightDelId)
8803         {
8804           break;
8805         }
8806       }
8807       if (!aLightDel.IsNull())
8808       {
8809         aViewer->DelLight (aLightDel);
8810       }
8811     }
8812     else if (anArgCase.IsEqual ("COLOR")
8813           || anArgCase.IsEqual ("COLOUR"))
8814     {
8815       if (++anArgIt >= theArgsNb)
8816       {
8817         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8818         return 1;
8819       }
8820
8821       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
8822       anArgNext.UpperCase();
8823       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
8824       if (!aLightCurr.IsNull())
8825       {
8826         aLightCurr->SetColor (aColor);
8827       }
8828     }
8829     else if (anArgCase.IsEqual ("POS")
8830           || anArgCase.IsEqual ("POSITION"))
8831     {
8832       if ((anArgIt + 3) >= theArgsNb)
8833       {
8834         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8835         return 1;
8836       }
8837
8838       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8839       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8840       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8841       if (!aLightDir.IsNull())
8842       {
8843         aLightDir->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8844       }
8845       else if (!aLightPos.IsNull())
8846       {
8847         aLightPos->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8848       }
8849       else if (!aLightSpot.IsNull())
8850       {
8851         aLightSpot->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
8852       }
8853       else
8854       {
8855         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8856         return 1;
8857       }
8858     }
8859     else if (anArgCase.IsEqual ("DIR")
8860           || anArgCase.IsEqual ("DIRECTION"))
8861     {
8862       if ((anArgIt + 3) >= theArgsNb)
8863       {
8864         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8865         return 1;
8866       }
8867
8868       anXYZ[0] = Atof (theArgVec[++anArgIt]);
8869       anXYZ[1] = Atof (theArgVec[++anArgIt]);
8870       anXYZ[2] = Atof (theArgVec[++anArgIt]);
8871       if (!aLightDir.IsNull())
8872       {
8873         aLightDir->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8874       }
8875       else if (!aLightSpot.IsNull())
8876       {
8877         aLightSpot->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
8878       }
8879       else
8880       {
8881         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8882         return 1;
8883       }
8884     }
8885     else if (anArgCase.IsEqual ("SM")
8886           || anArgCase.IsEqual ("SMOOTHNESS"))
8887     {
8888       if (++anArgIt >= theArgsNb)
8889       {
8890         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8891         return 1;
8892       }
8893
8894       Standard_Real aSmoothness = Atof (theArgVec[anArgIt]);
8895
8896       if (fabs (aSmoothness) < Precision::Confusion())
8897       {
8898         aLightCurr->SetIntensity (1.f);
8899       }
8900       else if (fabs (aLightCurr->Smoothness()) < Precision::Confusion())
8901       {
8902         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
8903       }
8904       else
8905       {
8906         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
8907         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
8908       }
8909
8910       if (!aLightPos.IsNull())
8911       {
8912         aLightPos->SetSmoothRadius (aSmoothness);
8913       }
8914       else if (!aLightDir.IsNull())
8915       {
8916         aLightDir->SetSmoothAngle (aSmoothness);
8917       }
8918     }
8919     else if (anArgCase.IsEqual ("INT")
8920           || anArgCase.IsEqual ("INTENSITY"))
8921     {
8922       if (++anArgIt >= theArgsNb)
8923       {
8924         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8925         return 1;
8926       }
8927
8928       Standard_Real aIntensity = Atof (theArgVec[anArgIt]);
8929
8930       if (!aLightCurr.IsNull())
8931       {
8932         aLightCurr->SetIntensity (aIntensity);
8933       }
8934     }
8935     else if (anArgCase.IsEqual ("ANG")
8936           || anArgCase.IsEqual ("ANGLE"))
8937     {
8938       if (++anArgIt >= theArgsNb)
8939       {
8940         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8941         return 1;
8942       }
8943
8944       Standard_Real anAngle = Atof (theArgVec[anArgIt]);
8945
8946       if (!aLightSpot.IsNull())
8947       {
8948         aLightSpot->SetAngle (anAngle / 180.0 * M_PI);
8949       }
8950     }
8951     else if (anArgCase.IsEqual ("CONSTATTEN")
8952           || anArgCase.IsEqual ("CONSTATTENUATION"))
8953     {
8954       if (++anArgIt >= theArgsNb)
8955       {
8956         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8957         return 1;
8958       }
8959
8960       if (!aLightPos.IsNull())
8961       {
8962         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8963         anAtten[0] = Atof (theArgVec[anArgIt]);
8964         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8965       }
8966       else if (!aLightSpot.IsNull())
8967       {
8968         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8969         anAtten[0] = Atof (theArgVec[anArgIt]);
8970         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8971       }
8972       else
8973       {
8974         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8975         return 1;
8976       }
8977     }
8978     else if (anArgCase.IsEqual ("LINATTEN")
8979           || anArgCase.IsEqual ("LINEARATTEN")
8980           || anArgCase.IsEqual ("LINEARATTENUATION"))
8981     {
8982       if (++anArgIt >= theArgsNb)
8983       {
8984         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
8985         return 1;
8986       }
8987
8988       if (!aLightPos.IsNull())
8989       {
8990         aLightPos->Attenuation (anAtten[0], anAtten[1]);
8991         anAtten[1] = Atof (theArgVec[anArgIt]);
8992         aLightPos->SetAttenuation (anAtten[0], anAtten[1]);
8993       }
8994       else if (!aLightSpot.IsNull())
8995       {
8996         aLightSpot->Attenuation (anAtten[0], anAtten[1]);
8997         anAtten[1] = Atof (theArgVec[anArgIt]);
8998         aLightSpot->SetAttenuation (anAtten[0], anAtten[1]);
8999       }
9000       else
9001       {
9002         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9003         return 1;
9004       }
9005     }
9006     else if (anArgCase.IsEqual ("EXP")
9007           || anArgCase.IsEqual ("EXPONENT")
9008           || anArgCase.IsEqual ("SPOTEXP")
9009           || anArgCase.IsEqual ("SPOTEXPONENT"))
9010     {
9011       if (++anArgIt >= theArgsNb)
9012       {
9013         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9014         return 1;
9015       }
9016
9017       if (!aLightSpot.IsNull())
9018       {
9019         aLightSpot->SetConcentration (Atof (theArgVec[anArgIt]));
9020       }
9021       else
9022       {
9023         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9024         return 1;
9025       }
9026     }
9027     else if (anArgCase.IsEqual ("HEAD")
9028           || anArgCase.IsEqual ("HEADLIGHT"))
9029     {
9030       if (++anArgIt >= theArgsNb)
9031       {
9032         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9033         return 1;
9034       }
9035
9036       if (aLightAmb.IsNull()
9037        && !aLightCurr.IsNull())
9038       {
9039         aLightCurr->SetHeadlight (Draw::Atoi (theArgVec[anArgIt]) != 0);
9040       }
9041       else
9042       {
9043         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9044         return 1;
9045       }
9046     }
9047     else
9048     {
9049       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9050     }
9051   }
9052
9053   addLight (aLightNew, isGlobal);
9054   aViewer->UpdateLights();
9055
9056   return 0;
9057 }
9058
9059 //=======================================================================
9060 //function : VRenderParams
9061 //purpose  : Enables/disables rendering features
9062 //=======================================================================
9063
9064 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9065                                        Standard_Integer  theArgNb,
9066                                        const char**      theArgVec)
9067 {
9068   Handle(V3d_View) aView = ViewerTest::CurrentView();
9069   if (aView.IsNull())
9070   {
9071     std::cerr << "Error: no active viewer!\n";
9072     return 1;
9073   }
9074
9075   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9076   TCollection_AsciiString aCmdName (theArgVec[0]);
9077   aCmdName.LowerCase();
9078   if (aCmdName == "vraytrace")
9079   {
9080     if (theArgNb == 1)
9081     {
9082       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9083       return 0;
9084     }
9085     else if (theArgNb == 2)
9086     {
9087       TCollection_AsciiString aValue (theArgVec[1]);
9088       aValue.LowerCase();
9089       if (aValue == "on"
9090        || aValue == "1")
9091       {
9092         aParams.Method = Graphic3d_RM_RAYTRACING;
9093         aView->Redraw();
9094         return 0;
9095       }
9096       else if (aValue == "off"
9097             || aValue == "0")
9098       {
9099         aParams.Method = Graphic3d_RM_RASTERIZATION;
9100         aView->Redraw();
9101         return 0;
9102       }
9103       else
9104       {
9105         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9106         return 1;
9107       }
9108     }
9109     else
9110     {
9111       std::cout << "Error: wrong number of arguments\n";
9112       return 1;
9113     }
9114   }
9115
9116   if (theArgNb < 2)
9117   {
9118     theDI << "renderMode:  ";
9119     switch (aParams.Method)
9120     {
9121       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9122       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9123     }
9124     theDI << "\n";
9125     theDI << "transparency:  ";
9126     switch (aParams.TransparencyMethod)
9127     {
9128       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
9129       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
9130                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
9131     }
9132     theDI << "\n";
9133     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
9134     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
9135     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
9136     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
9137     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
9138     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
9139     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
9140     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
9141     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
9142     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
9143     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
9144     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
9145     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
9146     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
9147     theDI << "shadingModel: ";
9148     switch (aView->ShadingModel())
9149     {
9150       case V3d_COLOR:   theDI << "color";   break;
9151       case V3d_FLAT:    theDI << "flat";    break;
9152       case V3d_GOURAUD: theDI << "gouraud"; break;
9153       case V3d_PHONG:   theDI << "phong";   break;
9154     }
9155     theDI << "\n";
9156     return 0;
9157   }
9158
9159   Standard_Boolean toPrint = Standard_False;
9160   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9161   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9162   {
9163     Standard_CString        anArg (theArgVec[anArgIter]);
9164     TCollection_AsciiString aFlag (anArg);
9165     aFlag.LowerCase();
9166     if (anUpdateTool.parseRedrawMode (aFlag))
9167     {
9168       continue;
9169     }
9170     else if (aFlag == "-echo"
9171           || aFlag == "-print")
9172     {
9173       toPrint = Standard_True;
9174       anUpdateTool.Invalidate();
9175     }
9176     else if (aFlag == "-mode"
9177           || aFlag == "-rendermode"
9178           || aFlag == "-render_mode")
9179     {
9180       if (toPrint)
9181       {
9182         switch (aParams.Method)
9183         {
9184           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9185           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
9186         }
9187         continue;
9188       }
9189       else
9190       {
9191         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9192         return 1;
9193       }
9194     }
9195     else if (aFlag == "-ray"
9196           || aFlag == "-raytrace")
9197     {
9198       if (toPrint)
9199       {
9200         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
9201         continue;
9202       }
9203
9204       aParams.Method = Graphic3d_RM_RAYTRACING;
9205     }
9206     else if (aFlag == "-rast"
9207           || aFlag == "-raster"
9208           || aFlag == "-rasterization")
9209     {
9210       if (toPrint)
9211       {
9212         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
9213         continue;
9214       }
9215
9216       aParams.Method = Graphic3d_RM_RASTERIZATION;
9217     }
9218     else if (aFlag == "-msaa")
9219     {
9220       if (toPrint)
9221       {
9222         theDI << aParams.NbMsaaSamples << " ";
9223         continue;
9224       }
9225       else if (++anArgIter >= theArgNb)
9226       {
9227         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9228         return 1;
9229       }
9230
9231       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
9232       if (aNbSamples < 0)
9233       {
9234         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
9235         return 1;
9236       }
9237       else
9238       {
9239         aParams.NbMsaaSamples = aNbSamples;
9240       }
9241     }
9242     else if (aFlag == "-oit")
9243     {
9244       if (toPrint)
9245       {
9246         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
9247         {
9248           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
9249         }
9250         else
9251         {
9252           theDI << "off" << " ";
9253         }
9254         continue;
9255       }
9256       else if (++anArgIter >= theArgNb)
9257       {
9258         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9259         return 1;
9260       }
9261
9262       TCollection_AsciiString aParam = theArgVec[anArgIter];
9263       aParam.LowerCase();
9264       if (aParam.IsRealValue())
9265       {
9266         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
9267         if (aWeight < 0.f || aWeight > 1.f)
9268         {
9269           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
9270           return 1;
9271         }
9272
9273         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
9274         aParams.OitDepthFactor     = aWeight;
9275       }
9276       else if (aParam == "off")
9277       {
9278         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
9279       }
9280       else
9281       {
9282         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9283         return 1;
9284       }
9285     }
9286     else if (aFlag == "-rendscale"
9287           || aFlag == "-renderscale"
9288           || aFlag == "-renderresolutionscale")
9289     {
9290       if (toPrint)
9291       {
9292         theDI << aParams.RenderResolutionScale << " ";
9293         continue;
9294       }
9295       else if (++anArgIter >= theArgNb)
9296       {
9297         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9298         return 1;
9299       }
9300
9301       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
9302       if (aScale < 0.01)
9303       {
9304         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
9305         return 1;
9306       }
9307       else
9308       {
9309         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
9310       }
9311     }
9312     else if (aFlag == "-raydepth"
9313           || aFlag == "-ray_depth")
9314     {
9315       if (toPrint)
9316       {
9317         theDI << aParams.RaytracingDepth << " ";
9318         continue;
9319       }
9320       else if (++anArgIter >= theArgNb)
9321       {
9322         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9323         return 1;
9324       }
9325
9326       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
9327
9328       // We allow RaytracingDepth be more than 10 in case of GI enabled
9329       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
9330       {
9331         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
9332         return 1;
9333       }
9334       else
9335       {
9336         aParams.RaytracingDepth = aDepth;
9337       }
9338     }
9339     else if (aFlag == "-shad"
9340           || aFlag == "-shadows")
9341     {
9342       if (toPrint)
9343       {
9344         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
9345         continue;
9346       }
9347
9348       Standard_Boolean toEnable = Standard_True;
9349       if (++anArgIter < theArgNb
9350       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9351       {
9352         --anArgIter;
9353       }
9354       aParams.IsShadowEnabled = toEnable;
9355     }
9356     else if (aFlag == "-refl"
9357           || aFlag == "-reflections")
9358     {
9359       if (toPrint)
9360       {
9361         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
9362         continue;
9363       }
9364
9365       Standard_Boolean toEnable = Standard_True;
9366       if (++anArgIter < theArgNb
9367       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9368       {
9369         --anArgIter;
9370       }
9371       aParams.IsReflectionEnabled = toEnable;
9372     }
9373     else if (aFlag == "-fsaa")
9374     {
9375       if (toPrint)
9376       {
9377         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
9378         continue;
9379       }
9380
9381       Standard_Boolean toEnable = Standard_True;
9382       if (++anArgIter < theArgNb
9383       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9384       {
9385         --anArgIter;
9386       }
9387       aParams.IsAntialiasingEnabled = toEnable;
9388     }
9389     else if (aFlag == "-gleam")
9390     {
9391       if (toPrint)
9392       {
9393         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
9394         continue;
9395       }
9396
9397       Standard_Boolean toEnable = Standard_True;
9398       if (++anArgIter < theArgNb
9399       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9400       {
9401         --anArgIter;
9402       }
9403       aParams.IsTransparentShadowEnabled = toEnable;
9404     }
9405     else if (aFlag == "-gi")
9406     {
9407       if (toPrint)
9408       {
9409         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
9410         continue;
9411       }
9412
9413       Standard_Boolean toEnable = Standard_True;
9414       if (++anArgIter < theArgNb
9415       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9416       {
9417         --anArgIter;
9418       }
9419       aParams.IsGlobalIlluminationEnabled = toEnable;
9420       if (!toEnable)
9421       {
9422         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
9423       }
9424     }
9425     else if (aFlag == "-blockedrng"
9426           || aFlag == "-brng")
9427     {
9428       if (toPrint)
9429       {
9430         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
9431         continue;
9432       }
9433
9434       Standard_Boolean toEnable = Standard_True;
9435       if (++anArgIter < theArgNb
9436         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9437       {
9438         --anArgIter;
9439       }
9440       aParams.CoherentPathTracingMode = toEnable;
9441     }
9442     else if (aFlag == "-maxrad")
9443     {
9444       if (toPrint)
9445       {
9446         theDI << aParams.RadianceClampingValue << " ";
9447         continue;
9448       }
9449       else if (++anArgIter >= theArgNb)
9450       {
9451         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9452         return 1;
9453       }
9454
9455       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
9456       if (!aMaxRadStr.IsRealValue())
9457       {
9458         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9459         return 1;
9460       }
9461
9462       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
9463       if (aMaxRadiance <= 0.0)
9464       {
9465         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
9466         return 1;
9467       }
9468       else
9469       {
9470         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
9471       }
9472     }
9473     else if (aFlag == "-iss")
9474     {
9475       if (toPrint)
9476       {
9477         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
9478         continue;
9479       }
9480
9481       Standard_Boolean toEnable = Standard_True;
9482       if (++anArgIter < theArgNb
9483         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9484       {
9485         --anArgIter;
9486       }
9487       aParams.AdaptiveScreenSampling = toEnable;
9488     }
9489     else if (aFlag == "-issd")
9490     {
9491       if (toPrint)
9492       {
9493         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
9494         continue;
9495       }
9496
9497       Standard_Boolean toEnable = Standard_True;
9498       if (++anArgIter < theArgNb
9499         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9500       {
9501         --anArgIter;
9502       }
9503       aParams.ShowSamplingTiles = toEnable;
9504     }
9505     else if (aFlag == "-nbtiles")
9506     {
9507       if (toPrint)
9508       {
9509         theDI << aParams.NbRayTracingTiles << " ";
9510         continue;
9511       }
9512       else if (++anArgIter >= theArgNb)
9513       {
9514         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9515         return 1;
9516       }
9517
9518       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
9519
9520       if (aNbTiles < 64)
9521       {
9522         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
9523         std::cerr << "Specify value in range [64, 1024].\n";
9524         return 1;
9525       }
9526       else
9527       {
9528         aParams.NbRayTracingTiles = aNbTiles;
9529       }
9530     }
9531     else if (aFlag == "-env")
9532     {
9533       if (toPrint)
9534       {
9535         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
9536         continue;
9537       }
9538
9539       Standard_Boolean toEnable = Standard_True;
9540       if (++anArgIter < theArgNb
9541         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9542       {
9543         --anArgIter;
9544       }
9545       aParams.UseEnvironmentMapBackground = toEnable;
9546     }
9547     else if (aFlag == "-twoside")
9548     {
9549       if (toPrint)
9550       {
9551         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
9552         continue;
9553       }
9554
9555       Standard_Boolean toEnable = Standard_True;
9556       if (++anArgIter < theArgNb
9557         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9558       {
9559         --anArgIter;
9560       }
9561       aParams.TwoSidedBsdfModels = toEnable;
9562     }
9563     else if (aFlag == "-shademodel"
9564           || aFlag == "-shadingmodel"
9565           || aFlag == "-shading")
9566     {
9567       if (toPrint)
9568       {
9569         switch (aView->ShadingModel())
9570         {
9571           case V3d_COLOR:   theDI << "color ";   break;
9572           case V3d_FLAT:    theDI << "flat ";    break;
9573           case V3d_GOURAUD: theDI << "gouraud "; break;
9574           case V3d_PHONG:   theDI << "phong ";   break;
9575         }
9576         continue;
9577       }
9578
9579       if (++anArgIter >= theArgNb)
9580       {
9581         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9582       }
9583
9584       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9585       aMode.LowerCase();
9586       if (aMode == "color"
9587        || aMode == "none")
9588       {
9589         aView->SetShadingModel (V3d_COLOR);
9590       }
9591       else if (aMode == "flat"
9592             || aMode == "facet")
9593       {
9594         aView->SetShadingModel (V3d_FLAT);
9595       }
9596       else if (aMode == "gouraud"
9597             || aMode == "vertex"
9598             || aMode == "vert")
9599       {
9600         aView->SetShadingModel (V3d_GOURAUD);
9601       }
9602       else if (aMode == "phong"
9603             || aMode == "fragment"
9604             || aMode == "frag"
9605             || aMode == "pixel")
9606       {
9607         aView->SetShadingModel (V3d_PHONG);
9608       }
9609       else
9610       {
9611         std::cout << "Error: unknown shading model '" << aMode << "'\n";
9612         return 1;
9613       }
9614     }
9615     else if (aFlag == "-resolution")
9616     {
9617       if (++anArgIter >= theArgNb)
9618       {
9619         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
9620         return 1;
9621       }
9622
9623       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
9624       if (aResolution.IsIntegerValue())
9625       {
9626         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
9627       }
9628       else
9629       {
9630         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9631         return 1;
9632       }
9633     }
9634     else if (aFlag == "-rebuildglsl"
9635           || aFlag == "-rebuild")
9636     {
9637       if (toPrint)
9638       {
9639         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
9640         continue;
9641       }
9642
9643       Standard_Boolean toEnable = Standard_True;
9644       if (++anArgIter < theArgNb
9645           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9646       {
9647         --anArgIter;
9648       }
9649       aParams.RebuildRayTracingShaders = toEnable;
9650     }
9651     else if (aFlag == "-focal")
9652     {
9653       if (++anArgIter >= theArgNb)
9654       {
9655         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9656         return 1;
9657       }
9658
9659       TCollection_AsciiString aParam (theArgVec[anArgIter]);
9660       if (aParam.IsRealValue())
9661       {
9662         float aFocalDist = static_cast<float> (aParam.RealValue());
9663         if (aFocalDist < 0)
9664         {
9665           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
9666           return 1;
9667         }
9668         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
9669       }
9670       else
9671       {
9672         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9673         return 1;
9674       }
9675     }
9676     else if (aFlag == "-aperture")
9677     {
9678       if (++anArgIter >= theArgNb)
9679       {
9680         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9681         return 1;
9682       }
9683
9684       TCollection_AsciiString aParam(theArgVec[anArgIter]);
9685       if (aParam.IsRealValue())
9686       {
9687         float aApertureSize = static_cast<float> (aParam.RealValue());
9688         if (aApertureSize < 0)
9689         {
9690           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
9691           return 1;
9692         }
9693         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
9694       }
9695       else
9696       {
9697         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9698         return 1;
9699       }
9700     }
9701     else if (aFlag == "-exposure")
9702     {
9703       if (++anArgIter >= theArgNb)
9704       {
9705         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9706         return 1;
9707       }
9708
9709       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
9710       if (anExposure.IsRealValue())
9711       {
9712         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
9713       }
9714       else
9715       {
9716         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9717         return 1;
9718       }
9719     }
9720     else if (aFlag == "-whitepoint")
9721     {
9722       if (++anArgIter >= theArgNb)
9723       {
9724         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9725         return 1;
9726       }
9727
9728       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
9729       if (aWhitePoint.IsRealValue())
9730       {
9731         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
9732       }
9733       else
9734       {
9735         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9736         return 1;
9737       }
9738     }
9739     else if (aFlag == "-tonemapping")
9740     {
9741       if (++anArgIter >= theArgNb)
9742       {
9743         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
9744         return 1;
9745       }
9746
9747       TCollection_AsciiString aMode (theArgVec[anArgIter]);
9748       aMode.LowerCase();
9749
9750       if (aMode == "disabled")
9751       {
9752         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
9753       }
9754       else if (aMode == "filmic")
9755       {
9756         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
9757       }
9758       else
9759       {
9760         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
9761         return 1;
9762       }
9763     }
9764     else
9765     {
9766       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
9767       return 1;
9768     }
9769   }
9770
9771   return 0;
9772 }
9773
9774 //=======================================================================
9775 //function : VProgressiveMode
9776 //purpose  :
9777 //=======================================================================
9778 #if defined(_WIN32)
9779 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
9780                                           Standard_Integer  /*theNbArgs*/,
9781                                           const char**      /*theArgs*/)
9782 {
9783   Handle(V3d_View) aView = ViewerTest::CurrentView();
9784   if (aView.IsNull())
9785   {
9786     std::cerr << "Error: no active viewer!\n";
9787     return 1;
9788   }
9789
9790   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
9791
9792   for (;;)
9793   {
9794     aView->Redraw();
9795
9796     Standard_Boolean toExit = Standard_False;
9797
9798     MSG aMsg;
9799     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
9800     {
9801       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
9802       {
9803         toExit = Standard_True;
9804       }
9805
9806       TranslateMessage (&aMsg);
9807       DispatchMessageW (&aMsg);
9808     }
9809
9810     if (toExit)
9811     {
9812       break;
9813     }
9814   }
9815
9816   return 0;
9817 }
9818 #endif
9819
9820 //=======================================================================
9821 //function : VFrustumCulling
9822 //purpose  : enables/disables view volume's culling.
9823 //=======================================================================
9824 static int VFrustumCulling (Draw_Interpretor& theDI,
9825                             Standard_Integer  theArgNb,
9826                             const char**      theArgVec)
9827 {
9828   Handle(V3d_View) aView = ViewerTest::CurrentView();
9829   if (aView.IsNull())
9830   {
9831     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
9832     return 1;
9833   }
9834
9835   if (theArgNb < 2)
9836   {
9837     theDI << (aView->IsCullingEnabled() ? "on" : "off");
9838     return 0;
9839   }
9840   else if (theArgNb != 2)
9841   {
9842     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
9843     return 1;
9844   }
9845
9846   TCollection_AsciiString aModeStr (theArgVec[1]);
9847   aModeStr.LowerCase();
9848   Standard_Boolean toEnable = 0;
9849   if (aModeStr == "on")
9850   {
9851     toEnable = 1;
9852   }
9853   else if (aModeStr == "off")
9854   {
9855     toEnable = 0;
9856   }
9857   else
9858   {
9859     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9860   }
9861
9862   aView->SetFrustumCulling (toEnable);
9863   aView->Redraw();
9864   return 0;
9865 }
9866
9867 //=======================================================================
9868 //function : VHighlightSelected
9869 //purpose  : 
9870 //=======================================================================
9871 static int VHighlightSelected (Draw_Interpretor& theDI,
9872                                Standard_Integer  theArgNb,
9873                                const char**      theArgVec)
9874 {
9875   if (ViewerTest::GetAISContext().IsNull())
9876   {
9877     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
9878     return 1;
9879   }
9880
9881   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9882
9883   if (theArgNb < 2)
9884   {
9885     theDI << (aContext->ToHilightSelected() ? "on" : "off");
9886     return 0;
9887   }
9888
9889   if (theArgNb != 2)
9890   {
9891     std::cout  << theArgVec[0] << " error : wrong number of parameters."
9892           << "Type 'help" << theArgVec[0] << "' for more information.";
9893     return 1;
9894   }
9895
9896   // Parse parameter
9897   TCollection_AsciiString aMode (theArgVec[1]);
9898   aMode.LowerCase();
9899   Standard_Boolean toEnable = Standard_False;
9900   if (aMode.IsEqual ("on"))
9901   {
9902     toEnable = Standard_True;
9903   }
9904   else if (aMode.IsEqual ("off"))
9905   {
9906     toEnable = Standard_False;
9907   }
9908   else
9909   {
9910     toEnable = Draw::Atoi (theArgVec[1]) != 0;
9911   }
9912
9913   if (toEnable != aContext->ToHilightSelected())
9914   {
9915     aContext->SetToHilightSelected (toEnable);
9916
9917     // Move cursor to null position and  back to process updating of detection
9918     // and highlighting of selected object immediatly.
9919     Standard_Integer aPixX = 0;
9920     Standard_Integer aPixY = 0;
9921     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
9922
9923     anEventManager->GetCurrentPosition (aPixX, aPixY);
9924     anEventManager->MoveTo (0, 0);
9925     anEventManager->MoveTo (aPixX, aPixY);
9926   }
9927
9928   return 0;
9929 }
9930
9931 //=======================================================================
9932 //function : VXRotate
9933 //purpose  :
9934 //=======================================================================
9935 static Standard_Integer VXRotate (Draw_Interpretor& di,
9936                                    Standard_Integer argc,
9937                                    const char ** argv)
9938 {
9939   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9940   if (aContext.IsNull())
9941   {
9942     di << argv[0] << "ERROR : use 'vinit' command before \n";
9943     return 1;
9944   }
9945   
9946   if (argc != 3)
9947   {
9948     di << "ERROR : Usage : " << argv[0] << " name angle\n";
9949     return 1;
9950   }
9951
9952   TCollection_AsciiString aName (argv[1]);
9953   Standard_Real anAngle = Draw::Atof (argv[2]);
9954
9955   // find object
9956   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
9957   Handle(AIS_InteractiveObject) anIObj;
9958   if (!aMap.IsBound2 (aName) )
9959   {
9960     di << "Use 'vdisplay' before\n";
9961     return 1;
9962   }
9963   else
9964   {
9965     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
9966
9967     gp_Trsf aTransform;
9968     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
9969     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
9970
9971     aContext->SetLocation (anIObj, aTransform);
9972     aContext->UpdateCurrentViewer();
9973   }
9974
9975   return 0;
9976 }
9977
9978 //===============================================================================================
9979 //class   : ViewerTest_AISManipulator
9980 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
9981 //===============================================================================================
9982 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
9983
9984 class ViewerTest_AISManipulator : public AIS_Manipulator
9985 {
9986 public:
9987
9988   ViewerTest_AISManipulator() : AIS_Manipulator()
9989   {
9990     GetMapOfAISManipulators().Add (this);
9991   }
9992
9993   virtual ~ViewerTest_AISManipulator()
9994   {
9995     GetMapOfAISManipulators().Remove (this);
9996   }
9997
9998   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
9999 };
10000
10001 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10002 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10003
10004 //===============================================================================================
10005 //function : VManipulator
10006 //purpose  :
10007 //===============================================================================================
10008 static int VManipulator (Draw_Interpretor& theDi,
10009                          Standard_Integer  theArgsNb,
10010                          const char**      theArgVec)
10011 {
10012   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10013   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10014   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
10015   if (aView.IsNull()
10016    || aViewer.IsNull())
10017   {
10018     std::cerr << "No active viewer!\n";
10019     return 1;
10020   }
10021
10022   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
10023   Standard_Integer anArgIter = 1;
10024   for (; anArgIter < theArgsNb; ++anArgIter)
10025   {
10026     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
10027   }
10028
10029   ViewerTest_CmdParser aCmd;
10030   aCmd.AddDescription ("Manages manipulator for interactive objects:");
10031   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
10032   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
10033   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
10034   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
10035   aCmd.AddOption ("detach",         "...       - detach manipulator");
10036
10037   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
10038   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
10039   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
10040
10041   aCmd.AddOption ("move",   "... x y z - move object");
10042   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
10043   aCmd.AddOption ("scale",  "... factor - scale object");
10044
10045   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
10046   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
10047   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
10048   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
10049   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
10050   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
10051   aCmd.AddOption ("size",              "... size - set size of manipulator");
10052   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
10053
10054   aCmd.Parse (theArgsNb, theArgVec);
10055
10056   if (aCmd.HasOption ("help"))
10057   {
10058     theDi.PrintHelp (theArgVec[0]);
10059     return 0;
10060   }
10061
10062   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
10063
10064   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
10065
10066   if (aName.IsEmpty())
10067   {
10068     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
10069     return 1;
10070   }
10071
10072   // ----------------------------------
10073   // detach existing manipulator object
10074   // ----------------------------------
10075
10076   if (aCmd.HasOption ("detach"))
10077   {
10078     if (!aMapAIS.IsBound2 (aName))
10079     {
10080       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
10081       return 1;
10082     }
10083
10084     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10085     if (aManipulator.IsNull())
10086     {
10087       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10088       return 1;
10089     }
10090
10091     aManipulator->Detach();
10092     aMapAIS.UnBind2 (aName);
10093     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
10094
10095     return 0;
10096   }
10097
10098   // -----------------------------------------------
10099   // find or create manipulator if it does not exist
10100   // -----------------------------------------------
10101
10102   Handle(AIS_Manipulator) aManipulator;
10103   if (!aMapAIS.IsBound2 (aName))
10104   {
10105     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
10106
10107     aManipulator = new ViewerTest_AISManipulator();
10108     aMapAIS.Bind (aManipulator, aName);
10109   }
10110   else
10111   {
10112     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
10113     if (aManipulator.IsNull())
10114     {
10115       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
10116       return 1;
10117     }
10118   }
10119
10120   // -----------------------------------------
10121   // change properties of manipulator instance
10122   // -----------------------------------------
10123
10124   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
10125   {
10126     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
10127   }
10128   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
10129   {
10130     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
10131   }
10132   if (aCmd.HasOption ("followRotation", 1, Standard_True))
10133   {
10134     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
10135   }
10136   if (aCmd.HasOption ("gap", 1, Standard_True))
10137   {
10138     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
10139   }
10140   if (aCmd.HasOption ("part", 3, Standard_True))
10141   {
10142     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
10143     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
10144     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
10145     if (aMode < 1 || aMode > 3)
10146     {
10147       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
10148       return 1;
10149     }
10150
10151     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
10152   }
10153   if (aCmd.HasOption ("pos", 3, Standard_True))
10154   {
10155     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
10156     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
10157     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
10158
10159     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
10160   }
10161   if (aCmd.HasOption ("size", 1, Standard_True))
10162   {
10163     aManipulator->SetSize (aCmd.ArgFloat ("size"));
10164   }
10165   if (aCmd.HasOption ("zoomable", 1, Standard_True))
10166   {
10167     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
10168
10169     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
10170     {
10171       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
10172       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
10173     }
10174   }
10175
10176   // ---------------------------------------------------
10177   // attach, detach or access manipulator from an object
10178   // ---------------------------------------------------
10179
10180   if (aCmd.HasOption ("attach"))
10181   {
10182     // Find an object and attach manipulator to it
10183     if (!aCmd.HasOption ("attach", 1, Standard_True))
10184     {
10185       return 1;
10186     }
10187
10188     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
10189     if (!aMapAIS.IsBound2 (anObjName))
10190     {
10191       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
10192       return 1;
10193     }
10194
10195     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
10196     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
10197     for (; anIt.More(); anIt.Next())
10198     {
10199       if (anIt.Value()->IsAttached()
10200        && anIt.Value()->Object() == anObject)
10201       {
10202         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
10203         return 1;
10204       }
10205     }
10206
10207     AIS_Manipulator::OptionsForAttach anOptions;
10208     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
10209     {
10210       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
10211     }
10212     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
10213     {
10214       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
10215     }
10216     if (aCmd.HasOption ("enableModes", 1, Standard_True))
10217     {
10218       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
10219     }
10220
10221     aManipulator->Attach (anObject, anOptions);
10222   }
10223
10224   // --------------------------------------
10225   // apply transformation using manipulator
10226   // --------------------------------------
10227
10228   if (aCmd.HasOption ("startTransform", 2, Standard_True))
10229   {
10230     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
10231   }
10232   if (aCmd.HasOption ("transform", 2, Standard_True))
10233   {
10234     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
10235   }
10236   if (aCmd.HasOption ("stopTransform"))
10237   {
10238     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
10239
10240     aManipulator->StopTransform (toApply);
10241   }
10242
10243   gp_Trsf aT;
10244   if (aCmd.HasOption ("move", 3, Standard_True))
10245   {
10246     aT.SetTranslationPart (aCmd.ArgVec ("move"));
10247   }
10248   if (aCmd.HasOption ("rotate", 7, Standard_True))
10249   {
10250     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
10251   }
10252   if (aCmd.HasOption ("scale", 1))
10253   {
10254     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
10255   }
10256
10257   if (aT.Form() != gp_Identity)
10258   {
10259     aManipulator->Transform (aT);
10260   }
10261
10262   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
10263
10264   return 0;
10265 }
10266
10267 //===============================================================================================
10268 //function : VSelectionProperties
10269 //purpose  :
10270 //===============================================================================================
10271 static int VSelectionProperties (Draw_Interpretor& theDi,
10272                                  Standard_Integer  theArgsNb,
10273                                  const char**      theArgVec)
10274 {
10275   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10276   if (aCtx.IsNull())
10277   {
10278     std::cerr << "No active viewer!\n";
10279     return 1;
10280   }
10281
10282   Standard_Boolean toPrint  = theArgsNb == 1;
10283   Standard_Boolean toRedraw = Standard_False;
10284   Standard_Integer anArgIter = 1;
10285   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
10286   if (anArgIter < theArgsNb)
10287   {
10288     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
10289     anArgFirst.LowerCase();
10290     ++anArgIter;
10291     if (anArgFirst == "dynhighlight"
10292      || anArgFirst == "dynhilight"
10293      || anArgFirst == "dynamichighlight"
10294      || anArgFirst == "dynamichilight")
10295     {
10296       aType = Prs3d_TypeOfHighlight_Dynamic;
10297     }
10298     else if (anArgFirst == "localdynhighlight"
10299           || anArgFirst == "localdynhilight"
10300           || anArgFirst == "localdynamichighlight"
10301           || anArgFirst == "localdynamichilight")
10302     {
10303       aType = Prs3d_TypeOfHighlight_LocalDynamic;
10304     }
10305     else if (anArgFirst == "selhighlight"
10306           || anArgFirst == "selhilight"
10307           || anArgFirst == "selectedhighlight"
10308           || anArgFirst == "selectedhilight")
10309     {
10310       aType = Prs3d_TypeOfHighlight_Selected;
10311     }
10312     else if (anArgFirst == "localselhighlight"
10313           || anArgFirst == "localselhilight"
10314           || anArgFirst == "localselectedhighlight"
10315           || anArgFirst == "localselectedhilight")
10316     {
10317       aType = Prs3d_TypeOfHighlight_LocalSelected;
10318     }
10319     else
10320     {
10321       --anArgIter;
10322     }
10323   }
10324   for (; anArgIter < theArgsNb; ++anArgIter)
10325   {
10326     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10327     anArg.LowerCase();
10328     if (anArg == "-help")
10329     {
10330       theDi.PrintHelp (theArgVec[0]);
10331       return 0;
10332     }
10333     else if (anArg == "-print")
10334     {
10335       toPrint = Standard_True;
10336     }
10337     else if (anArg == "-autoactivate")
10338     {
10339       Standard_Boolean toEnable = Standard_True;
10340       if (anArgIter + 1 < theArgsNb
10341        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
10342       {
10343         ++anArgIter;
10344       }
10345       aCtx->SetAutoActivateSelection (toEnable);
10346     }
10347     else if (anArg == "-pickstrategy"
10348           || anArg == "-pickingstrategy")
10349     {
10350       if (++anArgIter >= theArgsNb)
10351       {
10352         std::cout << "Syntax error: type of highlighting is undefined\n";
10353         return 1;
10354       }
10355
10356       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
10357       TCollection_AsciiString aVal (theArgVec[anArgIter]);
10358       aVal.LowerCase();
10359       if (aVal == "first"
10360        || aVal == "firstaccepted"
10361        || aVal == "firstacceptable")
10362       {
10363         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
10364       }
10365       else if (aVal == "topmost"
10366             || aVal == "onlyTopmost")
10367       {
10368         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
10369       }
10370       else
10371       {
10372         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
10373         return 1;
10374       }
10375
10376       aCtx->SetPickingStrategy (aStrategy);
10377     }
10378     else if (anArg == "-pixtol"
10379           && anArgIter + 1 < theArgsNb)
10380     {
10381       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
10382     }
10383     else if ((anArg == "-mode"
10384            || anArg == "-dispmode")
10385           && anArgIter + 1 < theArgsNb)
10386     {
10387       if (aType == Prs3d_TypeOfHighlight_None)
10388       {
10389         std::cout << "Syntax error: type of highlighting is undefined\n";
10390         return 1;
10391       }
10392
10393       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
10394       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10395       aStyle->SetDisplayMode (aDispMode);
10396       toRedraw = Standard_True;
10397     }
10398     else if (anArg == "-layer"
10399           && anArgIter + 1 < theArgsNb)
10400     {
10401       if (aType == Prs3d_TypeOfHighlight_None)
10402       {
10403         std::cout << "Syntax error: type of highlighting is undefined\n";
10404         return 1;
10405       }
10406
10407       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
10408       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
10409       {
10410         TColStd_SequenceOfInteger aLayers;
10411         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
10412         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
10413         {
10414           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
10415           return 1;
10416         }
10417       }
10418
10419       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10420       aStyle->SetZLayer (aNewLayer);
10421       toRedraw = Standard_True;
10422     }
10423     else if (anArg == "-hicolor"
10424           || anArg == "-selcolor"
10425           || anArg == "-color")
10426     {
10427       if (anArg.StartsWith ("-hi"))
10428       {
10429         aType = Prs3d_TypeOfHighlight_Dynamic;
10430       }
10431       else if (anArg.StartsWith ("-sel"))
10432       {
10433         aType = Prs3d_TypeOfHighlight_Selected;
10434       }
10435       else if (aType == Prs3d_TypeOfHighlight_None)
10436       {
10437         std::cout << "Syntax error: type of highlighting is undefined\n";
10438         return 1;
10439       }
10440
10441       Quantity_Color aColor;
10442       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
10443                                                            theArgVec + anArgIter + 1,
10444                                                            aColor);
10445       if (aNbParsed == 0)
10446       {
10447         std::cout << "Syntax error: need more arguments.\n";
10448         return 1;
10449       }
10450       anArgIter += aNbParsed;
10451
10452       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10453       aStyle->SetColor (aColor);
10454       toRedraw = Standard_True;
10455     }
10456     else if ((anArg == "-transp"
10457            || anArg == "-transparency"
10458            || anArg == "-hitransp"
10459            || anArg == "-seltransp"
10460            || anArg == "-hitransplocal"
10461            || anArg == "-seltransplocal")
10462           && anArgIter + 1 < theArgsNb)
10463     {
10464       if (anArg.StartsWith ("-hi"))
10465       {
10466         aType = Prs3d_TypeOfHighlight_Dynamic;
10467       }
10468       else if (anArg.StartsWith ("-sel"))
10469       {
10470         aType = Prs3d_TypeOfHighlight_Selected;
10471       }
10472       else if (aType == Prs3d_TypeOfHighlight_None)
10473       {
10474         std::cout << "Syntax error: type of highlighting is undefined\n";
10475         return 1;
10476       }
10477
10478       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
10479       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10480       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
10481       toRedraw = Standard_True;
10482     }
10483     else if ((anArg == "-mat"
10484            || anArg == "-material")
10485           && anArgIter + 1 < theArgsNb)
10486     {
10487       if (aType == Prs3d_TypeOfHighlight_None)
10488       {
10489         std::cout << "Syntax error: type of highlighting is undefined\n";
10490         return 1;
10491       }
10492
10493       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
10494       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
10495       if (aMatName != Graphic3d_NOM_DEFAULT)
10496       {
10497         ++anArgIter;
10498         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
10499         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
10500         Graphic3d_MaterialAspect aMat (aMatName);
10501         aMat.SetColor (aStyle->Color());
10502         aMat.SetTransparency (aStyle->Transparency());
10503         anAspect->SetFrontMaterial (aMat);
10504         anAspect->SetInteriorColor (aStyle->Color());
10505         aStyle->SetBasicFillAreaAspect (anAspect);
10506       }
10507       else
10508       {
10509         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
10510       }
10511       toRedraw = Standard_True;
10512     }
10513     else
10514     {
10515       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
10516     }
10517   }
10518
10519   if (toPrint)
10520   {
10521     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
10522     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
10523     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
10524     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
10525     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
10526     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
10527     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
10528     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
10529     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
10530     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
10531     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
10532     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
10533   }
10534
10535   if (aCtx->NbSelected() != 0 && toRedraw)
10536   {
10537     aCtx->HilightSelected (Standard_True);
10538   }
10539
10540   return 0;
10541 }
10542
10543 //===============================================================================================
10544 //function : VDumpSelectionImage
10545 //purpose  :
10546 //===============================================================================================
10547 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
10548                                 Standard_Integer  theArgsNb,
10549                                 const char**      theArgVec)
10550 {
10551   if (theArgsNb < 2)
10552   {
10553     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
10554     return 1;
10555   }
10556
10557   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
10558   if (aContext.IsNull())
10559   {
10560     std::cout << "Error: no active view.\n";
10561     return 1;
10562   }
10563
10564   TCollection_AsciiString aFile;
10565   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10566   Image_Format anImgFormat = Image_Format_BGR;
10567   Standard_Integer aPickedIndex = 1;
10568   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10569   {
10570     TCollection_AsciiString aParam (theArgVec[anArgIter]);
10571     aParam.LowerCase();
10572     if (aParam == "-type")
10573     {
10574       if (++anArgIter >= theArgsNb)
10575       {
10576         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
10577         return 1;
10578       }
10579
10580       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10581       aValue.LowerCase();
10582       if (aValue == "depth"
10583        || aValue == "normdepth"
10584        || aValue == "normalizeddepth")
10585       {
10586         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
10587         anImgFormat = Image_Format_GrayF;
10588       }
10589       if (aValue == "depthinverted"
10590        || aValue == "normdepthinverted"
10591        || aValue == "normalizeddepthinverted"
10592        || aValue == "inverted")
10593       {
10594         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
10595         anImgFormat = Image_Format_GrayF;
10596       }
10597       else if (aValue == "unnormdepth"
10598             || aValue == "unnormalizeddepth")
10599       {
10600         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
10601         anImgFormat = Image_Format_GrayF;
10602       }
10603       else if (aValue == "objectcolor"
10604             || aValue == "object"
10605             || aValue == "color")
10606       {
10607         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
10608       }
10609       else if (aValue == "entitycolor"
10610             || aValue == "entity")
10611       {
10612         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
10613       }
10614       else if (aValue == "ownercolor"
10615             || aValue == "owner")
10616       {
10617         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
10618       }
10619       else if (aValue == "selectionmodecolor"
10620             || aValue == "selectionmode"
10621             || aValue == "selmodecolor"
10622             || aValue == "selmode")
10623       {
10624         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
10625       }
10626     }
10627     else if (aParam == "-picked"
10628           || aParam == "-pickeddepth"
10629           || aParam == "-pickedindex")
10630     {
10631       if (++anArgIter >= theArgsNb)
10632       {
10633         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
10634         return 1;
10635       }
10636
10637       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
10638     }
10639     else if (aFile.IsEmpty())
10640     {
10641       aFile = theArgVec[anArgIter];
10642     }
10643     else
10644     {
10645       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
10646       return 1;
10647     }
10648   }
10649   if (aFile.IsEmpty())
10650   {
10651     std::cout << "Syntax error: image file name is missing.\n";
10652     return 1;
10653   }
10654
10655   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
10656   Standard_Integer aWidth = 0, aHeight = 0;
10657   aView->Window()->Size (aWidth, aHeight);
10658
10659   Image_AlienPixMap aPixMap;
10660   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
10661   {
10662     std::cout << "Error: can't allocate image.\n";
10663     return 1;
10664   }
10665   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
10666   {
10667     std::cout << "Error: can't generate selection image.\n";
10668     return 1;
10669   }
10670   if (!aPixMap.Save (aFile))
10671   {
10672     std::cout << "Error: can't save selection image.\n";
10673     return 0;
10674   }
10675   return 0;
10676 }
10677
10678 //=======================================================================
10679 //function : ViewerCommands
10680 //purpose  :
10681 //=======================================================================
10682
10683 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
10684 {
10685
10686   const char *group = "ZeViewer";
10687   theCommands.Add("vinit",
10688 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10689     "[name=view_name] [display=display_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10690 #else
10691     "[name=view_name] [l=leftPx t=topPx] [w=widthPx h=heightPx]\n"
10692 #endif
10693     " - Creates new View window with specified name view_name.\n"
10694     "By default the new view is created in the viewer and in"
10695     " graphic driver shared with active view.\n"
10696     " - name = {driverName/viewerName/viewName | viewerName/viewName | viewName}.\n"
10697     "If driverName isn't specified the driver will be shared with active view.\n"
10698     "If viewerName isn't specified the viewer will be shared with active view.\n"
10699 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
10700     " - display = HostName.DisplayNumber[:ScreenNumber] : if specified"
10701     "is used in creation of graphic driver\n"
10702 #endif
10703     " - l, t: pixel position of left top corner of the window\n"
10704     " - w,h: width and heigth of window respectively.\n"
10705     "Additional commands for operations with views: vclose, vactivate, vviewlist.\n",
10706     __FILE__,VInit,group);
10707   theCommands.Add("vclose" ,
10708     "[view_id [keep_context=0|1]]\n"
10709     "or vclose ALL - to remove all created views\n"
10710     " - removes view(viewer window) defined by its view_id.\n"
10711     " - keep_context: by default 0; if 1 and the last view is deleted"
10712     " the current context is not removed.",
10713     __FILE__,VClose,group);
10714   theCommands.Add("vactivate" ,
10715     "view_id"
10716     " - activates view(viewer window) defined by its view_id",
10717     __FILE__,VActivate,group);
10718   theCommands.Add("vviewlist",
10719     "vviewlist [format={tree, long}]"
10720     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
10721     " - format: format of result output, if tree the output is a tree view;"
10722     "otherwise it's a list of full view names. By default format = tree",
10723     __FILE__,VViewList,group);
10724   theCommands.Add("vhelp" ,
10725     "vhelp            : display help on the viewer commands",
10726     __FILE__,VHelp,group);
10727   theCommands.Add("vtop" ,
10728     "vtop or <T>      : Top view. Orientation +X+Y" ,
10729     __FILE__,VTop,group);
10730   theCommands.Add("vbottom" ,
10731     "vbottom          : Bottom view. Orientation +X-Y" ,
10732     __FILE__,VBottom,group);
10733   theCommands.Add("vleft" ,
10734     "vleft            : Left view. Orientation -Y+Z" ,
10735     __FILE__,VLeft,group);
10736   theCommands.Add("vright" ,
10737     "vright           : Right view. Orientation +Y+Z" ,
10738     __FILE__,VRight,group);
10739   theCommands.Add("vaxo" ,
10740     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
10741     __FILE__,VAxo,group);
10742   theCommands.Add("vfront" ,
10743     "vfront           : Front view. Orientation +X+Z" ,
10744     __FILE__,VFront,group);
10745   theCommands.Add("vback" ,
10746     "vback            : Back view. Orientation -X+Z" ,
10747     __FILE__,VBack,group);
10748   theCommands.Add("vpick" ,
10749     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
10750     VPick,group);
10751   theCommands.Add("vfit",
10752     "vfit or <F> [-selected] [-noupdate]"
10753     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
10754     __FILE__,VFit,group);
10755   theCommands.Add ("vfitarea",
10756     "vfitarea x1 y1 x2 y2"
10757     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
10758     "\n\t\t: Fit view to show area located between two points"
10759     "\n\t\t: given in world 2D or 3D corrdinates.",
10760     __FILE__, VFitArea, group);
10761   theCommands.Add ("vzfit", "vzfit [scale]\n"
10762     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
10763     "   \"scale\" - specifies factor to scale computed z range.\n",
10764     __FILE__, VZFit, group);
10765   theCommands.Add("vrepaint",
10766             "vrepaint [-immediate]"
10767     "\n\t\t: force redraw",
10768     __FILE__,VRepaint,group);
10769   theCommands.Add("vclear",
10770     "vclear          : vclear"
10771     "\n\t\t: remove all the object from the viewer",
10772     __FILE__,VClear,group);
10773   theCommands.Add("vsetbg",
10774     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
10775     __FILE__,VSetBg,group);
10776   theCommands.Add("vsetbgmode",
10777     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
10778     __FILE__,VSetBgMode,group);
10779   theCommands.Add("vsetgradientbg",
10780     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
10781     __FILE__,VSetGradientBg,group);
10782   theCommands.Add("vsetgrbgmode",
10783     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
10784     __FILE__,VSetGradientBgMode,group);
10785   theCommands.Add("vsetcolorbg",
10786     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
10787     __FILE__,VSetColorBg,group);
10788   theCommands.Add("vsetdefaultbg",
10789     "vsetdefaultbg r g b\n"
10790     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
10791     "\n\t\t: Set default viewer background fill color (flat/gradient).",
10792     __FILE__,VSetDefaultBg,group);
10793   theCommands.Add("vscale",
10794     "vscale          : vscale X Y Z",
10795     __FILE__,VScale,group);
10796   theCommands.Add("vzbufftrihedron",
10797             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
10798     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
10799     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
10800     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
10801     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
10802     "\n\t\t: Displays a trihedron",
10803     __FILE__,VZBuffTrihedron,group);
10804   theCommands.Add("vrotate",
10805     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
10806     "\n                : Option -mouseStart starts rotation according to the mouse position"
10807     "\n                : Option -mouseMove continues rotation with angle computed"
10808     "\n                : from last and new mouse position."
10809     "\n                : vrotate AX AY AZ [X Y Z]",
10810     __FILE__,VRotate,group);
10811   theCommands.Add("vzoom",
10812     "vzoom           : vzoom coef",
10813     __FILE__,VZoom,group);
10814   theCommands.Add("vpan",
10815     "vpan            : vpan dx dy",
10816     __FILE__,VPan,group);
10817   theCommands.Add("vexport",
10818     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
10819     " : exports the view to a vector file of a given format"
10820     " : notice that EMF format requires patched gl2ps",
10821     __FILE__,VExport,group);
10822   theCommands.Add("vcolorscale",
10823     "vcolorscale name [-noupdate|-update] [-demo]"
10824     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
10825     "\n\t\t:       [-font HeightFont=20]"
10826     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
10827     "\n\t\t:       [-smoothTransition {on|off}=off]"
10828     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
10829     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
10830     "\n\t\t:       [-textpos {left|right|center|none}=right]"
10831     "\n\t\t:       [-labelAtBorder {on|off}=on]"
10832     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
10833     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
10834     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
10835     "\n\t\t:       [-xy Left=0 Bottom=0]"
10836     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
10837     "\n\t\t:  -colors   - set colors for all intervals"
10838     "\n\t\t:  -color    - set color for specific interval"
10839     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
10840     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
10841     "\n\t\t:              at border means the value inbetween neighbor intervals,"
10842     "\n\t\t:              at center means the center value within current interval"
10843     "\n\t\t:  -labels   - set labels for all intervals"
10844     "\n\t\t:  -freeLabels - same as -labels but does not require"
10845     "\n\t\t:              matching the number of intervals"
10846     "\n\t\t:  -label    - set label for specific interval"
10847     "\n\t\t:  -title    - set title"
10848     "\n\t\t:  -reversed - setup smooth color transition between intervals"
10849     "\n\t\t:  -smoothTransition - swap colorscale direction"
10850     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
10851     __FILE__, VColorScale, group);
10852   theCommands.Add("vgraduatedtrihedron",
10853     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
10854     "\t[-namefont Name] [-valuesfont Name]\n"
10855     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
10856     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
10857     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
10858     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
10859     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
10860     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
10861     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
10862     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
10863     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
10864     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
10865     " - Displays or erases graduated trihedron"
10866     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
10867     " - namefont - font of axes names. Default: Arial\n"
10868     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
10869     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
10870     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
10871     " - valuesfont - font of axes values. Default: Arial\n"
10872     " - xcolor, ycolor, zcolor - color of axis and values\n"
10873     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
10874     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
10875     __FILE__,VGraduatedTrihedron,group);
10876   theCommands.Add("vtile" ,
10877             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
10878     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
10879     "\n\t\t:  -totalSize the size of virtual bigger viewport"
10880     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
10881     "\n\t\t:  -lowerLeft tile offset as lower left corner"
10882     "\n\t\t:  -upperLeft tile offset as upper left corner",
10883     __FILE__, VTile, group);
10884   theCommands.Add("vzlayer",
10885               "vzlayer [layerId]"
10886       "\n\t\t:         [-add|-delete|-get|-settings]"
10887       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
10888       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
10889       "\n\t\t: ZLayer list management:"
10890       "\n\t\t:   -add      add new z layer to viewer and print its id"
10891       "\n\t\t:   -delete   delete z layer"
10892       "\n\t\t:   -get      print sequence of z layers"
10893       "\n\t\t:   -settings print status of z layer settings"
10894       "\n\t\t:   -disable  disables given setting"
10895       "\n\t\t:   -enable   enables  given setting",
10896     __FILE__,VZLayer,group);
10897   theCommands.Add("vlayerline",
10898     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
10899     __FILE__,VLayerLine,group);
10900   theCommands.Add ("vgrid",
10901     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
10902     " : Mode - rectangular or circular"
10903     " : Type - lines or points",
10904     __FILE__, VGrid, group);
10905   theCommands.Add ("vpriviledgedplane",
10906     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
10907     "\n\t\t:   Ox, Oy, Oz - plane origin"
10908     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
10909     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
10910     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
10911     __FILE__, VPriviledgedPlane, group);
10912   theCommands.Add ("vconvert",
10913     "vconvert v [Mode={window|view}]"
10914     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
10915     "\n\t\t: vconvert x y z [Mode={window|grid}]"
10916     "\n\t\t:   window - convert to window coordinates, pixels"
10917     "\n\t\t:   view   - convert to view projection plane"
10918     "\n\t\t:   grid   - convert to model coordinates, given on grid"
10919     "\n\t\t:   ray    - convert projection ray to model coordiantes"
10920     "\n\t\t: - vconvert v window : convert view to window;"
10921     "\n\t\t: - vconvert v view   : convert window to view;"
10922     "\n\t\t: - vconvert x y window : convert view to window;"
10923     "\n\t\t: - vconvert x y view : convert window to view;"
10924     "\n\t\t: - vconvert x y : convert window to model;"
10925     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
10926     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
10927     "\n\t\t: - vconvert x y z window : convert model to window;"
10928     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
10929     "\n\t\t: Converts the given coordinates to window/view/model space.",
10930     __FILE__, VConvert, group);
10931   theCommands.Add ("vfps",
10932     "vfps [framesNb=100] : estimate average frame rate for active view",
10933     __FILE__, VFps, group);
10934   theCommands.Add ("vgldebug",
10935             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
10936     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
10937     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
10938     "\n\t\t: Debug context can be requested only on Windows"
10939     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
10940     "\n\t\t:  -sync     - request synchronized debug GL context"
10941     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
10942     "\n\t\t:              which are suppressed by default,"
10943     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
10944     "\n\t\t:              which are suppressed by default",
10945     __FILE__, VGlDebug, group);
10946   theCommands.Add ("vvbo",
10947     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
10948     __FILE__, VVbo, group);
10949   theCommands.Add ("vstereo",
10950             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
10951     "\n\t\t:         [-anaglyph Filter]"
10952     "\n\t\t: Control stereo output mode. Available modes for -mode:"
10953     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
10954     "\n\t\t:                     requires driver support."
10955     "\n\t\t:                     Should be called BEFORE vinit!"
10956     "\n\t\t:  anaglyph         - Anaglyph glasses"
10957     "\n\t\t:  rowInterlaced    - row-interlaced display"
10958     "\n\t\t:  columnInterlaced - column-interlaced display"
10959     "\n\t\t:  chessBoard       - chess-board output"
10960     "\n\t\t:  sideBySide       - horizontal pair"
10961     "\n\t\t:  overUnder        - vertical   pair"
10962     "\n\t\t: Available Anaglyph filters for -anaglyph:"
10963     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
10964     "\n\t\t:  greenMagentaSimple",
10965     __FILE__, VStereo, group);
10966   theCommands.Add ("vcaps",
10967             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
10968     "\n\t\t:       [-compatibleProfile {0|1}]"
10969     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
10970     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
10971     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
10972     "\n\t\t: Modify particular graphic driver options:"
10973     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
10974     "\n\t\t:             built-in GLSL programs"
10975     "\n\t\t:            (requires compatible profile)"
10976     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
10977     "\n\t\t:             arrays to GPU memory)"
10978     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
10979     "\n\t\t:  vsync    - switch VSync on or off"
10980     "\n\t\t:  winBuffer - allow using window buffer for rendering"
10981     "\n\t\t: Context creation options:"
10982     "\n\t\t:  softMode          - software OpenGL implementation"
10983     "\n\t\t:  compatibleProfile - backward-compatible profile"
10984     "\n\t\t:  quadbuffer        - QuadBuffer"
10985     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
10986     "\n\t\t: rendering paths producing the same visual result when"
10987     "\n\t\t: possible."
10988     "\n\t\t: Command is intended for testing old hardware compatibility.",
10989     __FILE__, VCaps, group);
10990   theCommands.Add ("vmemgpu",
10991     "vmemgpu [f]: print system-dependent GPU memory information if available;"
10992     " with f option returns free memory in bytes",
10993     __FILE__, VMemGpu, group);
10994   theCommands.Add ("vreadpixel",
10995     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
10996     " : Read pixel value for active view",
10997     __FILE__, VReadPixel, group);
10998   theCommands.Add("diffimage",
10999     "diffimage     : diffimage imageFile1 imageFile2 toleranceOfColor(0..1) blackWhite(1|0) borderFilter(1|0) [diffImageFile]",
11000     __FILE__, VDiffImage, group);
11001   theCommands.Add ("vselect",
11002     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
11003     "- emulates different types of selection:\n"
11004     "- 1) single click selection\n"
11005     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
11006     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
11007     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
11008     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
11009     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
11010     " (partial inclusion - overlap - is not allowed by default)\n"
11011     "- 5) any of these selections with shift button pressed",
11012     __FILE__, VSelect, group);
11013   theCommands.Add ("vmoveto",
11014     "vmoveto x y"
11015     "- emulates cursor movement to pixel postion (x,y)",
11016     __FILE__, VMoveTo, group);
11017   theCommands.Add ("vviewparams",
11018               "vviewparams [-args] [-scale [s]]"
11019       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
11020       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
11021       "\n\t\t: Manage current view parameters or prints all"
11022       "\n\t\t: current values when called without argument."
11023       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
11024       "\n\t\t:   -eye  [x y z] prints or sets eye location"
11025       "\n\t\t:   -at   [x y z] prints or sets center of look"
11026       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
11027       "\n\t\t:   -proj [x y z] prints or sets direction of look"
11028       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
11029       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
11030       "\n\t\t:                 or changes the size of its maximum dimension"
11031       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
11032     __FILE__, VViewParams, group);
11033
11034   theCommands.Add("vanimation", "Alias for vanim",
11035     __FILE__, VAnimation, group);
11036
11037   theCommands.Add("vanim",
11038             "List existing animations:"
11039     "\n\t\t:  vanim"
11040     "\n\t\t: Animation playback:"
11041     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
11042     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
11043     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
11044     "\n\t\t:   -freeLook skip camera animations"
11045     "\n\t\t:   -lockLoop disable any interactions"
11046     "\n\t\t:"
11047     "\n\t\t: Animation definition:"
11048     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
11049     "\n\t\t:        [start TimeSec] [duration TimeSec]"
11050     "\n\t\t:"
11051     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
11052     "\n\t\t: specifies nested animations."
11053     "\n\t\t: There is no syntax to explicitly add new animation,"
11054     "\n\t\t: and all non-existing animations within the name will be"
11055     "\n\t\t: implicitly created on first use (including parents)."
11056     "\n\t\t:"
11057     "\n\t\t: Each animation might define the SINGLE action (see below),"
11058     "\n\t\t: like camera transition, object transformation or custom callback."
11059     "\n\t\t: Child animations can be used for defining concurrent actions."
11060     "\n\t\t:"
11061     "\n\t\t: Camera animation:"
11062     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
11063     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
11064     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
11065     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
11066     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
11067     "\n\t\t:   -atX    camera Center positions pair"
11068     "\n\t\t:   -upX    camera Up directions pair"
11069     "\n\t\t:   -scaleX camera Scale factors pair"
11070     "\n\t\t: Object animation:"
11071     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
11072     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
11073     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
11074     "\n\t\t:   -locX   object Location points pair (translation)"
11075     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
11076     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
11077     "\n\t\t: Custom callback:"
11078     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
11079     "\n\t\t:   %Pts        overall animation presentation timestamp"
11080     "\n\t\t:   %LocalPts   local animation timestamp"
11081     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
11082     __FILE__, VAnimation, group);
11083
11084   theCommands.Add("vchangeselected",
11085     "vchangeselected shape"
11086     "- adds to shape to selection or remove one from it",
11087                 __FILE__, VChangeSelected, group);
11088   theCommands.Add ("vnbselected",
11089     "vnbselected"
11090     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
11091   theCommands.Add ("vcamera",
11092               "vcamera [-ortho] [-projtype]"
11093       "\n\t\t:         [-persp]"
11094       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
11095       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
11096       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
11097       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
11098       "\n\t\t: Manage camera parameters."
11099       "\n\t\t: Prints current value when option called without argument."
11100       "\n\t\t: Orthographic camera:"
11101       "\n\t\t:   -ortho      activate orthographic projection"
11102       "\n\t\t: Perspective camera:"
11103       "\n\t\t:   -persp      activate perspective  projection (mono)"
11104       "\n\t\t:   -fovy       field of view in y axis, in degrees"
11105       "\n\t\t:   -distance   distance of eye from camera center"
11106       "\n\t\t: Stereoscopic camera:"
11107       "\n\t\t:   -stereo     perspective  projection (stereo)"
11108       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
11109       "\n\t\t:   -rightEye   perspective  projection (right eye)"
11110       "\n\t\t:   -iod        intraocular distance value"
11111       "\n\t\t:   -iodType    distance type, absolute or relative"
11112       "\n\t\t:   -zfocus     stereographic focus value"
11113       "\n\t\t:   -zfocusType focus type, absolute or relative",
11114     __FILE__, VCamera, group);
11115   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
11116     "- vautozfit [on={1|0}] [scale]\n"
11117     "    Prints or changes parameters of automatic z-fit mode:\n"
11118     "   \"on\" - turns automatic z-fit on or off\n"
11119     "   \"scale\" - specifies factor to scale computed z range.\n",
11120     __FILE__, VAutoZFit, group);
11121   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
11122     "   vzrange                - without parameters shows current values\n"
11123     "   vzrange [znear] [zfar] - applies provided values to view",
11124     __FILE__,VZRange, group);
11125   theCommands.Add ("vpurgedisplay",
11126     "vpurgedisplay"
11127     "- removes structures which don't belong to objects displayed in neutral point",
11128     __FILE__, VPurgeDisplay, group);
11129   theCommands.Add("vsetviewsize",
11130     "vsetviewsize size",
11131     __FILE__,VSetViewSize,group);
11132   theCommands.Add("vmoveview",
11133     "vmoveview Dx Dy Dz [Start = 1|0]",
11134     __FILE__,VMoveView,group);
11135   theCommands.Add("vtranslateview",
11136     "vtranslateview Dx Dy Dz [Start = 1|0)]",
11137     __FILE__,VTranslateView,group);
11138   theCommands.Add("vturnview",
11139     "vturnview Ax Ay Az [Start = 1|0]",
11140     __FILE__,VTurnView,group);
11141   theCommands.Add("vtextureenv",
11142     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
11143     "or user-defined file and optionally applying texture mapping parameters\n"
11144     "                  Usage:\n"
11145     "                  vtextureenv off - disables environment mapping\n"
11146     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
11147     "                              std_texture = (0..7)\n"
11148     "                              rep         = {clamp|repeat}\n"
11149     "                              mod         = {decal|modulate}\n"
11150     "                              flt         = {nearest|bilinear|trilinear}\n"
11151     "                              ss, st      - scale factors for s and t texture coordinates\n"
11152     "                              ts, tt      - translation for s and t texture coordinates\n"
11153     "                              rot         - texture rotation angle in degrees",
11154     __FILE__, VTextureEnv, group);
11155   theCommands.Add("vhlr" ,
11156     "is_enabled={on|off} [show_hidden={1|0}]"
11157     " - Hidden line removal algorithm:"
11158     " - is_enabled: if is on HLR algorithm is applied\n"
11159     " - show_hidden: if equals to 1, hidden lines are drawn as dotted ones.\n",
11160     __FILE__,VHLR,group);
11161   theCommands.Add("vhlrtype" ,
11162     "algo_type={algo|polyalgo} [shape_1 ... shape_n]"
11163     " - Changes the type of HLR algorithm using for shapes."
11164     " - algo_type: if equals to algo, exact HLR algorithm is applied;\n"
11165     "   if equals to polyalgo, polygonal HLR algorithm is applied."
11166     "If shapes are not given HLR algoithm of given type is applied"
11167     " to all shapes in the view\n",
11168     __FILE__,VHLRType,group);
11169   theCommands.Add("vclipplane",
11170               "vclipplane planeName [{0|1}]"
11171       "\n\t\t:   [-equation A B C D]"
11172       "\n\t\t:   [-set|-unset [objects|views]]"
11173       "\n\t\t:   [-maxPlanes]"
11174       "\n\t\t:   [-capping {0|1}]"
11175       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
11176       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
11177       "\n\t\t:       [-texRotate Angle]"
11178       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
11179       "\n\t\t:       [-useObjShader {0|1}]"
11180       "\n\t\t: Clipping planes management:"
11181       "\n\t\t:   -maxPlanes   print plane limit for view"
11182       "\n\t\t:   -delete      delete plane with given name"
11183       "\n\t\t:   {off|on|0|1} turn clipping on/off"
11184       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
11185       "\n\t\t:                applied to active View when list is omitted"
11186       "\n\t\t:   -equation A B C D change plane equation"
11187       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
11188       "\n\t\t: Capping options:"
11189       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
11190       "\n\t\t:   -color R G B          set capping color"
11191       "\n\t\t:   -texName Texture      set capping texture"
11192       "\n\t\t:   -texScale SX SY       set capping tex scale"
11193       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
11194       "\n\t\t:   -texRotate Angle      set capping tex rotation"
11195       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
11196       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
11197       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
11198       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
11199       __FILE__, VClipPlane, group);
11200   theCommands.Add("vdefaults",
11201                "vdefaults [-absDefl value]"
11202        "\n\t\t:           [-devCoeff value]"
11203        "\n\t\t:           [-angDefl value]"
11204        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
11205     , __FILE__, VDefaults, group);
11206   theCommands.Add("vlight",
11207     "tool to manage light sources, without arguments shows list of lights."
11208     "\n    Main commands: "
11209     "\n      'clear' to clear lights"
11210     "\n      '{def}aults' to load deafault lights"
11211     "\n      'add' (or 'new') <type> to add any light source"
11212     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
11213     "\n      'change' <lightId> to edit light source with specified lightId"
11214     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
11215     "\n        {pos}ition X Y Z"
11216     "\n        {dir}ection X Y Z (for directional light or for spotlight)"
11217     "\n        color colorName"
11218     "\n        {head}light 0|1"
11219     "\n        {sm}oothness value"
11220     "\n        {int}ensity value"
11221     "\n        {constAtten}uation value"
11222     "\n        {linearAtten}uation value"
11223     "\n        angle angleDeg"
11224     "\n        {spotexp}onent value"
11225     "\n        local|global"
11226     "\n\n        example: vlight add positional head 1 pos 0 1 1 color red"
11227     "\n        example: vlight change 0 direction 0 -1 0 linearAttenuation 0.2",
11228     __FILE__, VLight, group);
11229   theCommands.Add("vraytrace",
11230             "vraytrace [0|1]"
11231     "\n\t\t: Turns on/off ray-tracing renderer."
11232     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
11233     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
11234     __FILE__, VRenderParams, group);
11235   theCommands.Add("vrenderparams",
11236     "\n    Manages rendering parameters: "
11237     "\n      '-raster'                   Disables GPU ray-tracing"
11238     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
11239     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
11240     "\n      '-rendScale    value        Rendering resolution scale factor"
11241     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
11242     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
11243     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
11244     "\n      '-reflections  on|off'      Enables/disables specular reflections"
11245     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
11246     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
11247     "\n      '-gi           on|off'      Enables/disables global illumination effects"
11248     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
11249     "\n      '-env          on|off'      Enables/disables environment map background"
11250     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
11251     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
11252     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
11253     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
11254     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
11255     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
11256     "\n      '-shadingModel model'       Controls shading model from enumeration"
11257     "\n                                  color, flat, gouraud, phong"
11258     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
11259     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
11260     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
11261     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
11262     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
11263     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
11264     "\n    Unlike vcaps, these parameters dramatically change visual properties."
11265     "\n    Command is intended to control presentation quality depending on"
11266     "\n    hardware capabilities and performance.",
11267     __FILE__, VRenderParams, group);
11268   theCommands.Add("vfrustumculling",
11269     "vfrustumculling [toEnable]: enables/disables objects clipping",
11270     __FILE__,VFrustumCulling,group);
11271   theCommands.Add("vhighlightselected",
11272     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
11273     "Without arguments it shows if highlighting of selected objects is enabled now.",
11274     __FILE__,VHighlightSelected,group);
11275   theCommands.Add ("vplace",
11276             "vplace dx dy"
11277     "\n\t\t: Places the point (in pixels) at the center of the window",
11278     __FILE__, VPlace, group);
11279   theCommands.Add("vxrotate",
11280     "vxrotate",
11281     __FILE__,VXRotate,group);
11282
11283     theCommands.Add("vmanipulator",
11284       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
11285       "\n    tool to create and manage AIS manipulators."
11286       "\n    Options: "
11287       "\n      '-attach AISObject'                 attach manipulator to AISObject"
11288       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
11289       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
11290       "\n      '-enableModes    {0|1}'             enable modes when attaching"
11291       "\n      '-detach'                           detach manipulator"
11292       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
11293       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
11294       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
11295       "\n      '-move x y z'                     - move attached object"
11296       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
11297       "\n      '-scale factor'                   - scale attached object"
11298       "\n      '-autoActivate      {0|1}'        - set activation on detection"
11299       "\n      '-followTranslation {0|1}'        - set following translation transform"
11300       "\n      '-followRotation    {0|1}'        - set following rotation transform"
11301       "\n      '-gap value'                      - set gap between sub-parts"
11302       "\n      '-part axis mode    {0|1}'        - set visual part"
11303       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
11304       "\n      '-size value'                     - set size of manipulator"
11305       "\n      '-zoomable {0|1}'                 - set zoom persistence",
11306     __FILE__, VManipulator, group);
11307
11308   theCommands.Add("vselprops",
11309     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
11310     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
11311     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
11312     "\n    -pickStrategy {first|topmost} : defines picking strategy"
11313     "\n                            'first'   to pick first acceptable (default)"
11314     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
11315     "\n    -pixTol    value        : sets up pixel tolerance"
11316     "\n    -dispMode  dispMode     : sets display mode for highlighting"
11317     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
11318     "\n    -color     {name|r g b} : sets highlight color"
11319     "\n    -transp    value        : sets transparency coefficient for highlight"
11320     "\n    -material  material     : sets highlight material"
11321     "\n    -print                  : prints current state of all mentioned parameters",
11322     __FILE__, VSelectionProperties, group);
11323
11324   theCommands.Add ("vseldump",
11325                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
11326                    "\n\t\t: Generate an image based on detection results:"
11327                    "\n\t\t:   depth       normalized depth values"
11328                    "\n\t\t:   unnormDepth unnormalized depth values"
11329                    "\n\t\t:   object      color of detected object"
11330                    "\n\t\t:   owner       color of detected owner"
11331                    "\n\t\t:   selMode     color of selection mode"
11332                    "\n\t\t:   entity      color of etected entity",
11333                    __FILE__, VDumpSelectionImage, group);
11334
11335 #if defined(_WIN32)
11336   theCommands.Add("vprogressive",
11337     "vprogressive",
11338     __FILE__, VProgressiveMode, group);
11339 #endif
11340 }