0029517: Visualization - introduce AlphaMode property defining alpha value handling...
[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 <Draw_ProgressIndicator.hxx>
31 #include <Graphic3d_ArrayOfPolylines.hxx>
32 #include <Graphic3d_AspectMarker3d.hxx>
33 #include <Graphic3d_ExportFormat.hxx>
34 #include <Graphic3d_NameOfTextureEnv.hxx>
35 #include <Graphic3d_GraduatedTrihedron.hxx>
36 #include <Graphic3d_TextureEnv.hxx>
37 #include <Graphic3d_TextureParams.hxx>
38 #include <Graphic3d_TypeOfTextureFilter.hxx>
39 #include <Graphic3d_AspectFillArea3d.hxx>
40 #include <ViewerTest.hxx>
41 #include <ViewerTest_AutoUpdater.hxx>
42 #include <ViewerTest_EventManager.hxx>
43 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
44 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
45 #include <ViewerTest_CmdParser.hxx>
46 #include <V3d_AmbientLight.hxx>
47 #include <V3d_DirectionalLight.hxx>
48 #include <V3d_PositionalLight.hxx>
49 #include <V3d_SpotLight.hxx>
50 #include <Message_ProgressSentry.hxx>
51 #include <NCollection_DoubleMap.hxx>
52 #include <NCollection_List.hxx>
53 #include <NCollection_Vector.hxx>
54 #include <AIS_InteractiveContext.hxx>
55 #include <Draw_Interpretor.hxx>
56 #include <Draw.hxx>
57 #include <Draw_Appli.hxx>
58 #include <Image_AlienPixMap.hxx>
59 #include <Image_VideoRecorder.hxx>
60 #include <OpenGl_GraphicDriver.hxx>
61 #include <OSD_Timer.hxx>
62 #include <TColStd_HSequenceOfAsciiString.hxx>
63 #include <TColStd_SequenceOfInteger.hxx>
64 #include <TColStd_HSequenceOfReal.hxx>
65 #include <TColgp_Array1OfPnt2d.hxx>
66 #include <TColStd_MapOfAsciiString.hxx>
67 #include <Aspect_TypeOfLine.hxx>
68 #include <Image_Diff.hxx>
69 #include <Aspect_DisplayConnection.hxx>
70 #include <gp_Pnt.hxx>
71 #include <gp_Dir.hxx>
72 #include <gp_Pln.hxx>
73 #include <PrsMgr_PresentableObject.hxx>
74 #include <Graphic3d_ClipPlane.hxx>
75 #include <NCollection_DataMap.hxx>
76 #include <Graphic3d_Texture2Dmanual.hxx>
77 #include <Prs3d_ShadingAspect.hxx>
78 #include <Prs3d_Drawer.hxx>
79 #include <Prs3d_LineAspect.hxx>
80 #include <Prs3d_Root.hxx>
81 #include <Prs3d_Text.hxx>
82 #include <Select3D_SensitivePrimitiveArray.hxx>
83
84 #ifdef _WIN32
85 #undef DrawText
86 #endif
87
88 #include <cstdlib>
89
90 #if defined(_WIN32)
91   #include <WNT_WClass.hxx>
92   #include <WNT_Window.hxx>
93 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
94   #include <Cocoa_Window.hxx>
95 #else
96   #include <Xw_Window.hxx>
97   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
98   #include <X11/Xutil.h>
99   #include <tk.h>
100 #endif
101
102 // Auxiliary definitions
103 static const char THE_KEY_DELETE = 127;
104 static const char THE_KEY_ESCAPE = 27;
105
106 //==============================================================================
107 //  VIEWER GLOBAL VARIABLES
108 //==============================================================================
109
110 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
111 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
112
113 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
114 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
115
116 extern int VErase (Draw_Interpretor& theDI,
117                    Standard_Integer  theArgNb,
118                    const char**      theArgVec);
119
120 #if defined(_WIN32)
121 static Handle(WNT_Window)& VT_GetWindow() {
122   static Handle(WNT_Window) WNTWin;
123   return WNTWin;
124 }
125 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
126 static Handle(Cocoa_Window)& VT_GetWindow()
127 {
128   static Handle(Cocoa_Window) aWindow;
129   return aWindow;
130 }
131 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
132 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
133 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
134
135 #else
136 static Handle(Xw_Window)& VT_GetWindow(){
137   static Handle(Xw_Window) XWWin;
138   return XWWin;
139 }
140
141 static void VProcessEvents(ClientData,int);
142 #endif
143
144 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
145 {
146   static Handle(Aspect_DisplayConnection) aDisplayConnection;
147   return aDisplayConnection;
148 }
149
150 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
151 {
152   GetDisplayConnection() = theDisplayConnection;
153 }
154
155 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
156 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
157 {
158   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
159 #if defined(_WIN32)
160   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
161   if (!aWindow.IsNull())
162     return aWindow->HWindow();
163 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
164   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
165   if (!aWindow.IsNull())
166   return aWindow->XWindow();
167 #endif
168   return aWindowHandle;
169 }
170 #endif
171
172 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
173 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
174 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
175 static OpenGl_Caps ViewerTest_myDefaultCaps;
176
177 static void OSWindowSetup();
178
179 static struct
180 {
181   Quantity_Color FlatColor;
182   Quantity_Color GradientColor1;
183   Quantity_Color GradientColor2;
184   Aspect_GradientFillMethod FillMethod;
185 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
186
187 //==============================================================================
188 //  EVENT GLOBAL VARIABLES
189 //==============================================================================
190
191 static int Start_Rot = 0;
192 Standard_Boolean HasHlrOnBeforeRotation = Standard_False;
193 int X_Motion = 0; // Current cursor position
194 int Y_Motion = 0;
195 int X_ButtonPress = 0; // Last ButtonPress position
196 int Y_ButtonPress = 0;
197 Standard_Boolean IsDragged = Standard_False;
198 Standard_Boolean DragFirst = Standard_False;
199 Standard_Boolean TheIsAnimating = Standard_False;
200 Standard_Boolean Draw_ToExitOnCloseView = Standard_False;
201 Standard_Boolean Draw_ToCloseViewOnEsc  = Standard_False;
202
203
204 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
205 {
206   static Handle(AIS_RubberBand) aBand;
207   if (aBand.IsNull())
208   {
209     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
210     aBand->SetDisplayMode (0);
211   }
212   return aBand;
213 }
214
215 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
216
217 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
218 {
219   static ViewerTest_MapOfAISManipulators aMap;
220   return aMap;
221 }
222
223 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
224 {
225   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
226   for (; anIt.More(); anIt.Next())
227   {
228     if (anIt.Value()->HasActiveMode())
229     {
230       return anIt.Value();
231     }
232   }
233   return NULL;
234 }
235
236 //==============================================================================
237
238 #ifdef _WIN32
239 static LRESULT WINAPI ViewerWindowProc(
240                                        HWND hwnd,
241                                        UINT uMsg,
242                                        WPARAM wParam,
243                                        LPARAM lParam );
244 static LRESULT WINAPI AdvViewerWindowProc(
245   HWND hwnd,
246   UINT uMsg,
247   WPARAM wParam,
248   LPARAM lParam );
249 #endif
250
251
252 //==============================================================================
253 //function : WClass
254 //purpose  :
255 //==============================================================================
256
257 const Handle(Standard_Transient)& ViewerTest::WClass()
258 {
259   static Handle(Standard_Transient) theWClass;
260 #if defined(_WIN32)
261   if (theWClass.IsNull())
262   {
263     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
264                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
265                                 ::LoadCursor (NULL, IDC_ARROW));
266   }
267 #endif
268   return theWClass;
269 }
270
271 //==============================================================================
272 //function : CreateName
273 //purpose  : Create numerical name for new object in theMap
274 //==============================================================================
275 template <typename ObjectType>
276 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
277                                     const TCollection_AsciiString& theDefaultString)
278 {
279   if (theObjectMap.IsEmpty())
280     return theDefaultString + TCollection_AsciiString(1);
281
282   Standard_Integer aNextKey = 1;
283   Standard_Boolean isFound = Standard_False;
284   while (!isFound)
285   {
286     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
287     // Look for objects with default names
288     if (theObjectMap.IsBound1(aStringKey))
289     {
290       aNextKey++;
291     }
292     else
293       isFound = Standard_True;
294   }
295
296   return theDefaultString + TCollection_AsciiString(aNextKey);
297 }
298
299 //==============================================================================
300 //structure : ViewerTest_Names
301 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
302 //==============================================================================
303 struct ViewerTest_Names
304 {
305 private:
306   TCollection_AsciiString myDriverName;
307   TCollection_AsciiString myViewerName;
308   TCollection_AsciiString myViewName;
309
310 public:
311
312   const TCollection_AsciiString& GetDriverName () const
313   {
314     return myDriverName;
315   }
316   void SetDriverName (const TCollection_AsciiString& theDriverName)
317   {
318     myDriverName = theDriverName;
319   }
320   const TCollection_AsciiString& GetViewerName () const
321   {
322     return myViewerName;
323   }
324   void SetViewerName (const TCollection_AsciiString& theViewerName)
325   {
326     myViewerName = theViewerName;
327   }
328   const TCollection_AsciiString& GetViewName () const
329   {
330     return myViewName;
331   }
332   void SetViewName (const TCollection_AsciiString& theViewName)
333   {
334     myViewName = theViewName;
335   }
336
337   //===========================================================================
338   //function : Constructor for ViewerTest_Names
339   //purpose  : Get view, viewer, driver names from custom string
340   //===========================================================================
341
342   ViewerTest_Names (const TCollection_AsciiString& theInputString)
343   {
344     TCollection_AsciiString aName(theInputString);
345     if (theInputString.IsEmpty())
346     {
347       // Get current configuration
348       if (ViewerTest_myDrivers.IsEmpty())
349         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
350           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
351       else
352         myDriverName = ViewerTest_myDrivers.Find2
353         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
354
355       if(ViewerTest_myContexts.IsEmpty())
356       {
357         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
358           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
359       }
360       else
361       {
362         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
363       }
364
365       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
366     }
367     else
368     {
369       // There is at least view name
370       Standard_Integer aParserNumber = 0;
371       for (Standard_Integer i = 0; i < 3; ++i)
372       {
373         Standard_Integer aParserPos = aName.SearchFromEnd("/");
374         if(aParserPos != -1)
375         {
376           aParserNumber++;
377           aName.Split(aParserPos-1);
378         }
379         else
380           break;
381       }
382       if (aParserNumber == 0)
383       {
384         // Only view name
385         if (!ViewerTest::GetAISContext().IsNull())
386         {
387           myDriverName = ViewerTest_myDrivers.Find2
388           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
389           myViewerName = ViewerTest_myContexts.Find2
390           (ViewerTest::GetAISContext());
391         }
392         else
393         {
394           // There is no opened contexts here, need to create names for viewer and driver
395           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
396             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
397
398           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
399             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
400         }
401         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
402       }
403       else if (aParserNumber == 1)
404       {
405         // Here is viewerName/viewName
406         if (!ViewerTest::GetAISContext().IsNull())
407           myDriverName = ViewerTest_myDrivers.Find2
408           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
409         else
410         {
411           // There is no opened contexts here, need to create name for driver
412           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
413             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
414         }
415         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
416
417         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
418       }
419       else
420       {
421         //Here is driverName/viewerName/viewName
422         myDriverName = TCollection_AsciiString(aName);
423
424         TCollection_AsciiString aViewerName(theInputString);
425         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
426         myViewerName = TCollection_AsciiString(aViewerName);
427
428         myViewName = TCollection_AsciiString(theInputString);
429       }
430     }
431   }
432 };
433
434 //==============================================================================
435 //function : FindContextByView
436 //purpose  : Find AIS_InteractiveContext by View
437 //==============================================================================
438
439 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
440 {
441   Handle(AIS_InteractiveContext) anAISContext;
442
443   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
444        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
445   {
446     if (anIter.Value()->CurrentViewer() == theView->Viewer())
447        return anIter.Key2();
448   }
449   return anAISContext;
450 }
451
452
453 //==============================================================================
454 //function : SetWindowTitle
455 //purpose  : Set window title
456 //==============================================================================
457
458 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
459                      Standard_CString theTitle)
460 {
461 #if defined(_WIN32)
462   const TCollection_ExtendedString theTitleW (theTitle);
463   SetWindowTextW ((HWND )Handle(WNT_Window)::DownCast(theWindow)->HWindow(), theTitleW.ToWideString());
464 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
465   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
466 #else
467   if(GetDisplayConnection()->GetDisplay())
468   {
469     Window aWindow =
470       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
471     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
472   }
473 #endif
474 }
475
476 //==============================================================================
477 //function : IsWindowOverlapped
478 //purpose  : Check if theWindow overlapp another view
479 //==============================================================================
480
481 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
482                                      const Standard_Integer thePxTop,
483                                      const Standard_Integer thePxRight,
484                                      const Standard_Integer thePxBottom,
485                                      TCollection_AsciiString& theViewId)
486 {
487   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
488       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
489   {
490     Standard_Integer aTop = 0,
491       aLeft = 0,
492       aRight = 0,
493       aBottom = 0;
494     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
495     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
496         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
497         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
498         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
499     {
500       theViewId = anIter.Key1();
501       return Standard_True;
502     }
503   }
504   return Standard_False;
505 }
506
507 // Workaround: to create and delete non-orthographic views outside ViewerTest
508 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
509 {
510   ViewerTest_myViews.UnBind1 (theName);
511 }
512
513 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
514                                const Handle(V3d_View)& theView)
515 {
516   ViewerTest_myViews.Bind (theName, theView);
517 }
518
519 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
520 {
521   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
522 }
523 //==============================================================================
524 //function : ViewerInit
525 //purpose  : Create the window viewer and initialize all the global variable
526 //==============================================================================
527
528 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
529                                                 const Standard_Integer thePxTop,
530                                                 const Standard_Integer thePxWidth,
531                                                 const Standard_Integer thePxHeight,
532                                                 Standard_CString theViewName,
533                                                 Standard_CString theDisplayName)
534 {
535   // Default position and dimension of the viewer window.
536   // Note that left top corner is set to be sufficiently small to have
537   // window fit in the small screens (actual for remote desktops, see #23003).
538   // The position corresponds to the window's client area, thus some
539   // gap is added for window frame to be visible.
540   Standard_Integer aPxLeft   = 20;
541   Standard_Integer aPxTop    = 40;
542   Standard_Integer aPxWidth  = 409;
543   Standard_Integer aPxHeight = 409;
544   Standard_Boolean toCreateViewer = Standard_False;
545
546   Handle(OpenGl_GraphicDriver) aGraphicDriver;
547   ViewerTest_Names aViewNames(theViewName);
548   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
549     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
550
551   if (thePxLeft != 0)
552     aPxLeft = thePxLeft;
553   if (thePxTop != 0)
554     aPxTop = thePxTop;
555   if (thePxWidth != 0)
556     aPxWidth = thePxWidth;
557   if (thePxHeight != 0)
558     aPxHeight = thePxHeight;
559
560   // Get graphic driver (create it or get from another view)
561   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
562   {
563     // Get connection string
564   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
565     TCollection_AsciiString aDisplayName(theDisplayName);
566     if (!aDisplayName.IsEmpty())
567       SetDisplayConnection (new Aspect_DisplayConnection ());
568     else
569       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
570   #else
571     (void)theDisplayName; // avoid warning on unused argument
572     SetDisplayConnection (new Aspect_DisplayConnection ());
573   #endif
574
575     if (Draw_VirtualWindows)
576     {
577       // don't waste the time waiting for VSync when window is not displayed on the screen
578       ViewerTest_myDefaultCaps.swapInterval = 0;
579       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
580       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
581     }
582     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
583     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
584
585     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
586     toCreateViewer = Standard_True;
587   }
588   else
589   {
590     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
591   }
592
593   //Dispose the window if input parameters are default
594   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
595   {
596     Standard_Integer aTop = 0,
597                      aLeft = 0,
598                      aRight = 0,
599                      aBottom = 0,
600                      aScreenWidth = 0,
601                      aScreenHeight = 0;
602
603     // Get screen resolution
604 #if defined(_WIN32) || defined(__WIN32__)
605     RECT aWindowSize;
606     GetClientRect(GetDesktopWindow(), &aWindowSize);
607     aScreenHeight = aWindowSize.bottom;
608     aScreenWidth = aWindowSize.right;
609 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
610     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
611 #else
612     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
613     aScreenWidth = WidthOfScreen(aScreen);
614     aScreenHeight = HeightOfScreen(aScreen);
615 #endif
616
617     TCollection_AsciiString anOverlappedViewId("");
618
619     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
620     {
621       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
622
623       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
624         && aRight + 2*aPxWidth + 40 > aScreenWidth)
625       {
626         if (aBottom + aPxHeight + 40 > aScreenHeight)
627         {
628           aPxLeft = 20;
629           aPxTop = 40;
630           break;
631         }
632         aPxLeft = 20;
633         aPxTop = aBottom + 40;
634       }
635       else
636         aPxLeft = aRight + 20;
637     }
638   }
639
640   // Get viewer name
641   TCollection_AsciiString aTitle("3D View - ");
642   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
643
644   // Change name of current active window
645   if (!ViewerTest::CurrentView().IsNull())
646   {
647     TCollection_AsciiString anActiveWindowTitle("3D View - ");
648     anActiveWindowTitle = anActiveWindowTitle
649       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
650     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
651   }
652
653   // Create viewer
654   Handle(V3d_Viewer) a3DViewer;
655   // If it's the single view, we first look for empty context
656   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
657   {
658     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
659       anIter(ViewerTest_myContexts);
660     if (anIter.More())
661       ViewerTest::SetAISContext (anIter.Value());
662     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
663   }
664   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
665   {
666     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
667     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
668   }
669   else if (a3DViewer.IsNull())
670   {
671     toCreateViewer = Standard_True;
672     a3DViewer = new V3d_Viewer(aGraphicDriver);
673     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
674     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
675                                            ViewerTest_DefaultBackground.GradientColor2,
676                                            ViewerTest_DefaultBackground.FillMethod);
677   }
678
679   // AIS context setup
680   if (ViewerTest::GetAISContext().IsNull() ||
681       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
682   {
683     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
684     ViewerTest::SetAISContext (aContext);
685     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
686   }
687   else
688   {
689     ViewerTest::ResetEventManager();
690   }
691
692   // Create window
693 #if defined(_WIN32)
694   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
695                                     Handle(WNT_WClass)::DownCast (WClass()),
696                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
697                                     aPxLeft, aPxTop,
698                                     aPxWidth, aPxHeight,
699                                     Quantity_NOC_BLACK);
700 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
701   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
702                                      aPxLeft, aPxTop,
703                                      aPxWidth, aPxHeight);
704   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
705 #else
706   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
707                                   aTitle.ToCString(),
708                                   aPxLeft, aPxTop,
709                                   aPxWidth, aPxHeight);
710 #endif
711   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
712
713   // View setup
714   Handle(V3d_View) aView = a3DViewer->CreateView();
715   aView->SetWindow (VT_GetWindow());
716   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
717
718   ViewerTest::CurrentView(aView);
719   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
720
721   // Setup for X11 or NT
722   OSWindowSetup();
723
724   // Set parameters for V3d_View and V3d_Viewer
725   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
726   aV3dView->SetComputedMode(Standard_False);
727
728   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
729   if (toCreateViewer)
730   {
731     a3DViewer->SetDefaultLights();
732     a3DViewer->SetLightOn();
733   }
734
735   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
736   #if TCL_MAJOR_VERSION  < 8
737   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
738       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
739   #else
740   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
741       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
742   #endif
743   #endif
744
745   VT_GetWindow()->Map();
746
747   // Set the handle of created view in the event manager
748   ViewerTest::ResetEventManager();
749
750   ViewerTest::CurrentView()->Redraw();
751
752   aView.Nullify();
753   a3DViewer.Nullify();
754
755   return aViewNames.GetViewName();
756 }
757
758 //==============================================================================
759 //function : RedrawAllViews
760 //purpose  : Redraw all created views
761 //==============================================================================
762 void ViewerTest::RedrawAllViews()
763 {
764   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
765   for (; aViewIt.More(); aViewIt.Next())
766   {
767     const Handle(V3d_View)& aView = aViewIt.Key2();
768     aView->Redraw();
769   }
770 }
771
772 //==============================================================================
773 //function : Vinit
774 //purpose  : Create the window viewer and initialize all the global variable
775 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
776 //==============================================================================
777
778 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
779 {
780   TCollection_AsciiString aViewName, aDisplayName;
781   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
782   TCollection_AsciiString aName, aValue;
783   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
784   {
785     const TCollection_AsciiString anArg = theArgVec[anArgIt];
786     TCollection_AsciiString anArgCase = anArg;
787     anArgCase.LowerCase();
788     if (anArgIt + 1 < theArgsNb
789      && anArgCase == "-name")
790     {
791       aViewName = theArgVec[++anArgIt];
792     }
793     else if (anArgIt + 1 < theArgsNb
794           && (anArgCase == "-left"
795            || anArgCase == "-l"))
796     {
797       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
798     }
799     else if (anArgIt + 1 < theArgsNb
800           && (anArgCase == "-top"
801            || anArgCase == "-t"))
802     {
803       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
804     }
805     else if (anArgIt + 1 < theArgsNb
806           && (anArgCase == "-width"
807            || anArgCase == "-w"))
808     {
809       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
810     }
811     else if (anArgIt + 1 < theArgsNb
812           && (anArgCase == "-height"
813            || anArgCase == "-h"))
814     {
815       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
816     }
817     else if (anArgCase == "-exitonclose")
818     {
819       Draw_ToExitOnCloseView = true;
820       if (anArgIt + 1 < theArgsNb
821        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToExitOnCloseView))
822       {
823         ++anArgIt;
824       }
825     }
826     else if (anArgCase == "-closeonescape"
827           || anArgCase == "-closeonesc")
828     {
829       Draw_ToCloseViewOnEsc = true;
830       if (anArgIt + 1 < theArgsNb
831        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], Draw_ToCloseViewOnEsc))
832       {
833         ++anArgIt;
834       }
835     }
836     else if (anArgIt + 1 < theArgsNb
837           && (anArgCase == "-disp"
838            || anArgCase == "-display"))
839     {
840       aDisplayName = theArgVec[++anArgIt];
841     }
842     // old syntax
843     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
844     {
845       aName.LowerCase();
846       if (aName == "name")
847       {
848         aViewName = aValue;
849       }
850       else if (aName == "l"
851             || aName == "left")
852       {
853         aPxLeft = aValue.IntegerValue();
854       }
855       else if (aName == "t"
856             || aName == "top")
857       {
858         aPxTop = aValue.IntegerValue();
859       }
860       else if (aName == "disp"
861             || aName == "display")
862       {
863         aDisplayName = aValue;
864       }
865       else if (aName == "w"
866             || aName == "width")
867       {
868         aPxWidth = aValue.IntegerValue();
869       }
870       else if (aName == "h"
871             || aName == "height")
872       {
873         aPxHeight = aValue.IntegerValue();
874       }
875       else
876       {
877         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
878         return 1;
879       }
880     }
881     else if (aViewName.IsEmpty())
882     {
883       aViewName = anArg;
884     }
885     else
886     {
887       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
888       return 1;
889     }
890   }
891
892 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
893   if (!aDisplayName.IsEmpty())
894   {
895     aDisplayName.Clear();
896     std::cout << "Warning: display parameter will be ignored.\n";
897   }
898 #endif
899
900   ViewerTest_Names aViewNames (aViewName);
901   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
902   {
903     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
904     theDi.Eval (aCommand.ToCString());
905     return 0;
906   }
907
908   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
909                                                             aViewName.ToCString(),
910                                                             aDisplayName.ToCString());
911   theDi << aViewId;
912   return 0;
913 }
914
915 //! Parse HLR algo type.
916 static Standard_Boolean parseHlrAlgoType (const char* theName,
917                                           Prs3d_TypeOfHLR& theType)
918 {
919   TCollection_AsciiString aName (theName);
920   aName.LowerCase();
921   if (aName == "polyalgo")
922   {
923     theType = Prs3d_TOH_PolyAlgo;
924   }
925   else if (aName == "algo")
926   {
927     theType = Prs3d_TOH_Algo;
928   }
929   else
930   {
931     return Standard_False;
932   }
933   return Standard_True;
934 }
935
936 //==============================================================================
937 //function : VHLR
938 //purpose  : hidden lines removal algorithm
939 //==============================================================================
940
941 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
942 {
943   const Handle(V3d_View) aView = ViewerTest::CurrentView();
944   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
945   if (aView.IsNull())
946   {
947     std::cerr << "Error: No opened viewer!\n";
948     return 1;
949   }
950
951   Standard_Boolean hasHlrOnArg = Standard_False;
952   Standard_Boolean hasShowHiddenArg = Standard_False;
953   Standard_Boolean isHLROn = Standard_False;
954   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
955   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
956   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
957   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
958   {
959     TCollection_AsciiString anArg (argv[anArgIter]);
960     anArg.LowerCase();
961     if (anUpdateTool.parseRedrawMode (anArg))
962     {
963       continue;
964     }
965     else if (anArg == "-showhidden"
966           && anArgIter + 1 < argc
967           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
968     {
969       ++anArgIter;
970       hasShowHiddenArg = Standard_True;
971       continue;
972     }
973     else if ((anArg == "-type"
974            || anArg == "-algo"
975            || anArg == "-algotype")
976           && anArgIter + 1 < argc
977           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
978     {
979       ++anArgIter;
980       continue;
981     }
982     else if (!hasHlrOnArg
983           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
984     {
985       hasHlrOnArg = Standard_True;
986       continue;
987     }
988     // old syntax
989     else if (!hasShowHiddenArg
990           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
991     {
992       hasShowHiddenArg = Standard_True;
993       continue;
994     }
995     else
996     {
997       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
998       return 1;
999     }
1000   }
1001   if (!hasHlrOnArg)
1002   {
1003     di << "HLR:        " << aView->ComputedMode() << "\n";
1004     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1005     di << "HlrAlgo:    ";
1006     switch (aCtx->DefaultDrawer()->TypeOfHLR())
1007     {
1008       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
1009       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1010       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
1011     }
1012     anUpdateTool.Invalidate();
1013     return 0;
1014   }
1015
1016   Standard_Boolean toRecompute = Standard_False;
1017   if (aTypeOfHLR != Prs3d_TOH_NotSet
1018    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
1019   {
1020     toRecompute = Standard_True;
1021     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1022   }
1023   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1024   {
1025     toRecompute = Standard_True;
1026     if (toShowHidden)
1027     {
1028       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
1029     }
1030     else
1031     {
1032       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
1033     }
1034   }
1035
1036   // redisplay shapes
1037   if (aView->ComputedMode() && isHLROn && toRecompute)
1038   {
1039     AIS_ListOfInteractive aListOfShapes;
1040     aCtx->DisplayedObjects (aListOfShapes);
1041     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
1042     {
1043       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
1044       {
1045         aCtx->Redisplay (aShape, Standard_False);
1046       }
1047     }
1048   }
1049
1050   aView->SetComputedMode (isHLROn);
1051   return 0;
1052 }
1053
1054 //==============================================================================
1055 //function : VHLRType
1056 //purpose  : change type of using HLR algorithm
1057 //==============================================================================
1058
1059 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1060 {
1061   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1062   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1063   if (aView.IsNull())
1064   {
1065     std::cerr << "Error: No opened viewer!\n";
1066     return 1;
1067   }
1068
1069   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1070   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1071   AIS_ListOfInteractive aListOfShapes;
1072   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
1073   {
1074     TCollection_AsciiString anArg (argv[anArgIter]);
1075     anArg.LowerCase();
1076     if (anUpdateTool.parseRedrawMode (anArg))
1077     {
1078       continue;
1079     }
1080     else if ((anArg == "-type"
1081            || anArg == "-algo"
1082            || anArg == "-algotype")
1083           && anArgIter + 1 < argc
1084           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1085     {
1086       ++anArgIter;
1087       continue;
1088     }
1089     // old syntax
1090     else if (aTypeOfHLR == Prs3d_TOH_NotSet
1091           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1092     {
1093       continue;
1094     }
1095     else
1096     {
1097       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1098       TCollection_AsciiString aName (argv[anArgIter]);
1099       if (!aMap.IsBound2 (aName))
1100       {
1101         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
1102         return 1;
1103       }
1104
1105       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1106       if (aShape.IsNull())
1107       {
1108         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
1109         return 1;
1110       }
1111       aListOfShapes.Append (aShape);
1112       continue;
1113     }
1114   }
1115   if (aTypeOfHLR == Prs3d_TOH_NotSet)
1116   {
1117     std::cout << "Syntax error: wrong number of arguments!\n";
1118     return 1;
1119   }
1120
1121   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1122   if (isGlobal)
1123   {
1124     aCtx->DisplayedObjects (aListOfShapes);
1125     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1126   }
1127
1128   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1129   {
1130     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1131     if (aShape.IsNull())
1132     {
1133       continue;
1134     }
1135
1136     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1137                             && aView->ComputedMode();
1138     if (!isGlobal
1139      || aShape->TypeOfHLR() != aTypeOfHLR)
1140     {
1141       aShape->SetTypeOfHLR (aTypeOfHLR);
1142     }
1143     if (toUpdateShape)
1144     {
1145       aCtx->Redisplay (aShape, Standard_False);
1146     }
1147   }
1148   return 0;
1149 }
1150
1151 //==============================================================================
1152 //function : FindViewIdByWindowHandle
1153 //purpose  : Find theView Id in the map of views by window handle
1154 //==============================================================================
1155 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1156 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
1157 {
1158   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
1159        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1160   {
1161     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
1162     if (aWindowHandle == theWindowHandle)
1163       return anIter.Key1();
1164   }
1165   return TCollection_AsciiString("");
1166 }
1167 #endif
1168
1169 //==============================================================================
1170 //function : ActivateView
1171 //purpose  : Make the view active
1172 //==============================================================================
1173
1174 void ActivateView (const TCollection_AsciiString& theViewName)
1175 {
1176   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1177   if (!aView.IsNull())
1178   {
1179     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
1180     if (!anAISContext.IsNull())
1181     {
1182       if (!ViewerTest::CurrentView().IsNull())
1183       {
1184         TCollection_AsciiString aTitle("3D View - ");
1185         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1186         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1187       }
1188
1189       ViewerTest::CurrentView (aView);
1190       ViewerTest::SetAISContext (anAISContext);
1191       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ") + theViewName + "(*)";
1192       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1193 #if defined(_WIN32)
1194       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1195 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1196       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1197 #else
1198       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1199 #endif
1200       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1201       ViewerTest::CurrentView()->Redraw();
1202     }
1203   }
1204 }
1205
1206 //==============================================================================
1207 //function : RemoveView
1208 //purpose  :
1209 //==============================================================================
1210 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1211                              const Standard_Boolean  theToRemoveContext)
1212 {
1213   if (!ViewerTest_myViews.IsBound2 (theView))
1214   {
1215     return;
1216   }
1217
1218   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1219   RemoveView (aViewName, theToRemoveContext);
1220 }
1221
1222 //==============================================================================
1223 //function : RemoveView
1224 //purpose  : Close and remove view from display, clear maps if neccessary
1225 //==============================================================================
1226 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1227 {
1228   if (!ViewerTest_myViews.IsBound1(theViewName))
1229   {
1230     cout << "Wrong view name\n";
1231     return;
1232   }
1233
1234   // Activate another view if it's active now
1235   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1236   {
1237     if (ViewerTest_myViews.Extent() > 1)
1238     {
1239       TCollection_AsciiString aNewViewName;
1240       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1241            anIter.More(); anIter.Next())
1242       {
1243         if (anIter.Key1() != theViewName)
1244         {
1245           aNewViewName = anIter.Key1();
1246           break;
1247         }
1248       }
1249       ActivateView (aNewViewName);
1250     }
1251     else
1252     {
1253       Handle(V3d_View) anEmptyView;
1254 #if defined(_WIN32) || defined(__WIN32__)
1255       Handle(WNT_Window) anEmptyWindow;
1256 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1257       Handle(Cocoa_Window) anEmptyWindow;
1258 #else
1259       Handle(Xw_Window) anEmptyWindow;
1260 #endif
1261       VT_GetWindow() = anEmptyWindow;
1262       ViewerTest::CurrentView (anEmptyView);
1263       if (isContextRemoved)
1264       {
1265         Handle(AIS_InteractiveContext) anEmptyContext;
1266         ViewerTest::SetAISContext(anEmptyContext);
1267       }
1268     }
1269   }
1270
1271   // Delete view
1272   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1273   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1274
1275   // Remove view resources
1276   ViewerTest_myViews.UnBind1(theViewName);
1277   aView->Window()->Unmap();
1278   aView->Remove();
1279
1280 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1281   XFlush (GetDisplayConnection()->GetDisplay());
1282 #endif
1283
1284   // Keep context opened only if the closed view is last to avoid
1285   // unused empty contexts
1286   if (!aCurrentContext.IsNull())
1287   {
1288     // Check if there are more difined views in the viewer
1289     aCurrentContext->CurrentViewer()->InitDefinedViews();
1290     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1291     {
1292       // Remove driver if there is no viewers that use it
1293       Standard_Boolean isRemoveDriver = Standard_True;
1294       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1295           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1296       {
1297         if (aCurrentContext != anIter.Key2() &&
1298           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1299         {
1300           isRemoveDriver = Standard_False;
1301           break;
1302         }
1303       }
1304
1305       aCurrentContext->RemoveAll (Standard_False);
1306       if(isRemoveDriver)
1307       {
1308         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1309       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1310         #if TCL_MAJOR_VERSION  < 8
1311         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1312         #else
1313         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1314         #endif
1315       #endif
1316       }
1317
1318       ViewerTest_myContexts.UnBind2(aCurrentContext);
1319     }
1320   }
1321   cout << "3D View - " << theViewName << " was deleted.\n";
1322   if (Draw_ToExitOnCloseView)
1323   {
1324     Draw_Interprete ("exit");
1325   }
1326 }
1327
1328 //==============================================================================
1329 //function : VClose
1330 //purpose  : Remove the view defined by its name
1331 //==============================================================================
1332
1333 static int VClose (Draw_Interpretor& /*theDi*/,
1334                    Standard_Integer  theArgsNb,
1335                    const char**      theArgVec)
1336 {
1337   NCollection_List<TCollection_AsciiString> aViewList;
1338   if (theArgsNb > 1)
1339   {
1340     TCollection_AsciiString anArg (theArgVec[1]);
1341     anArg.UpperCase();
1342     if (anArg.IsEqual ("ALL")
1343      || anArg.IsEqual ("*"))
1344     {
1345       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1346            anIter.More(); anIter.Next())
1347       {
1348         aViewList.Append (anIter.Key1());
1349       }
1350       if (aViewList.IsEmpty())
1351       {
1352         std::cout << "No view to close\n";
1353         return 0;
1354       }
1355     }
1356     else
1357     {
1358       ViewerTest_Names aViewName (theArgVec[1]);
1359       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1360       {
1361         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1362         return 1;
1363       }
1364       aViewList.Append (aViewName.GetViewName());
1365     }
1366   }
1367   else
1368   {
1369     // close active view
1370     if (ViewerTest::CurrentView().IsNull())
1371     {
1372       std::cerr << "No active view!\n";
1373       return 1;
1374     }
1375     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1376   }
1377
1378   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1379   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1380        anIter.More(); anIter.Next())
1381   {
1382     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1383   }
1384
1385   return 0;
1386 }
1387
1388 //==============================================================================
1389 //function : VActivate
1390 //purpose  : Activate the view defined by its ID
1391 //==============================================================================
1392
1393 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1394 {
1395   if (theArgsNb > 2)
1396   {
1397     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1398     << "Usage: " << theArgVec[0] << " ViewID\n";
1399     return 1;
1400   }
1401   if(theArgsNb == 1)
1402   {
1403     theDi.Eval("vviewlist");
1404     return 0;
1405   }
1406
1407   TCollection_AsciiString aNameString(theArgVec[1]);
1408   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1409   {
1410     TCollection_AsciiString aTitle("3D View - ");
1411     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1412     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1413     Handle(V3d_View) anEmptyView;
1414 #if defined(_WIN32) || defined(__WIN32__)
1415     Handle(WNT_Window) anEmptyWindow;
1416 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1417     Handle(Cocoa_Window) anEmptyWindow;
1418 #else
1419     Handle(Xw_Window) anEmptyWindow;
1420 #endif
1421     VT_GetWindow() = anEmptyWindow;
1422     ViewerTest::CurrentView (anEmptyView);
1423     ViewerTest::ResetEventManager();
1424     theDi << theArgVec[0] << ": all views are inactive\n";
1425     return 0;
1426   }
1427
1428   ViewerTest_Names aViewNames(aNameString);
1429
1430   // Check if this view exists in the viewer with the driver
1431   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1432   {
1433     theDi << "Wrong view name\n";
1434     return 1;
1435   }
1436
1437   // Check if it is active already
1438   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1439   {
1440     theDi << theArgVec[0] << ": the view is active already\n";
1441     return 0;
1442   }
1443
1444   ActivateView (aViewNames.GetViewName());
1445   return 0;
1446 }
1447
1448 //==============================================================================
1449 //function : VViewList
1450 //purpose  : Print current list of views per viewer and graphic driver ID
1451 //           shared between viewers
1452 //==============================================================================
1453
1454 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1455 {
1456   if (theArgsNb > 2)
1457   {
1458     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1459           << "Usage: " << theArgVec[0] << " name";
1460     return 1;
1461   }
1462   if (ViewerTest_myContexts.Size() < 1)
1463     return 0;
1464
1465   Standard_Boolean isTreeView =
1466     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1467
1468   if (isTreeView)
1469   {
1470     theDi << theArgVec[0] <<":\n";
1471   }
1472
1473   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
1474        aDriverIter.More(); aDriverIter.Next())
1475   {
1476     if (isTreeView)
1477       theDi << aDriverIter.Key1() << ":\n";
1478
1479     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1480       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1481     {
1482       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1483       {
1484         if (isTreeView)
1485         {
1486           TCollection_AsciiString aContextName(aContextIter.Key1());
1487           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1488         }
1489
1490         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
1491              aViewIter.More(); aViewIter.Next())
1492         {
1493           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1494           {
1495             TCollection_AsciiString aViewName(aViewIter.Key1());
1496             if (isTreeView)
1497             {
1498               if (aViewIter.Value() == ViewerTest::CurrentView())
1499                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1500               else
1501                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1502             }
1503             else
1504             {
1505               theDi << aViewName << " ";
1506             }
1507           }
1508         }
1509       }
1510     }
1511   }
1512   return 0;
1513 }
1514
1515 //==============================================================================
1516 //function : VT_ProcessKeyPress
1517 //purpose  : Handle KeyPress event from a CString
1518 //==============================================================================
1519 void VT_ProcessKeyPress (const char* buf_ret)
1520 {
1521   //cout << "KeyPress" << endl;
1522   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1523   // Letter in alphabetic order
1524
1525   if (!strcasecmp (buf_ret, "A"))
1526   {
1527     // AXO
1528     aView->SetProj(V3d_XposYnegZpos);
1529   }
1530   else if (!strcasecmp (buf_ret, "D"))
1531   {
1532     // Reset
1533     aView->Reset();
1534   }
1535   else if (!strcasecmp (buf_ret, "F"))
1536   {
1537     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1538     {
1539       ViewerTest::GetAISContext()->FitSelected (aView);
1540     }
1541     else
1542     {
1543       // FitAll
1544       aView->FitAll();
1545     }
1546   }
1547   else if (!strcasecmp (buf_ret, "H"))
1548   {
1549     // HLR
1550     std::cout << "HLR" << std::endl;
1551     aView->SetComputedMode (!aView->ComputedMode());
1552     aView->Redraw();
1553   }
1554   else if (!strcasecmp (buf_ret, "P"))
1555   {
1556     // Type of HLR
1557     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1558     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1559       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1560     else
1561       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1562     if (aContext->NbSelected()==0)
1563     {
1564       AIS_ListOfInteractive aListOfShapes;
1565       aContext->DisplayedObjects(aListOfShapes);
1566       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1567         anIter.More(); anIter.Next())
1568       {
1569         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1570         if (aShape.IsNull())
1571           continue;
1572         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1573           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1574         else
1575           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1576         aContext->Redisplay (aShape, Standard_False);
1577       }
1578     }
1579     else
1580     {
1581       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1582       {
1583         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1584         if (aShape.IsNull())
1585           continue;
1586         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1587           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1588         else
1589           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1590         aContext->Redisplay (aShape, Standard_False);
1591       }
1592     }
1593
1594     aContext->UpdateCurrentViewer();
1595
1596   }
1597   else if (!strcasecmp (buf_ret, "S"))
1598   {
1599     std::cout << "setup Shaded display mode" << std::endl;
1600
1601     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1602     if(Ctx->NbSelected()==0)
1603       Ctx->SetDisplayMode (AIS_Shaded, Standard_True);
1604     else{
1605       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1606         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1607       Ctx->UpdateCurrentViewer();
1608     }
1609   }
1610   else if (!strcasecmp (buf_ret, "U"))
1611   {
1612     // Unset display mode
1613     std::cout << "reset display mode to defaults" << std::endl;
1614
1615     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1616     if(Ctx->NbSelected()==0)
1617       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1618     else{
1619       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1620         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1621       Ctx->UpdateCurrentViewer();
1622     }
1623
1624   }
1625   else if (!strcasecmp (buf_ret, "T"))
1626   {
1627     // Top
1628     aView->SetProj(V3d_Zpos);
1629   }
1630   else if (!strcasecmp (buf_ret, "B"))
1631   {
1632     // Bottom
1633     aView->SetProj(V3d_Zneg);
1634   }
1635   else if (!strcasecmp (buf_ret, "L"))
1636   {
1637     // Left
1638     aView->SetProj(V3d_Xneg);
1639   }
1640   else if (!strcasecmp (buf_ret, "R"))
1641   {
1642     // Right
1643     aView->SetProj(V3d_Xpos);
1644   }
1645   else if (!strcasecmp (buf_ret, "W"))
1646   {
1647     std::cout << "setup WireFrame display mode" << std::endl;
1648     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1649     if(Ctx->NbSelected()==0)
1650       Ctx->SetDisplayMode (AIS_WireFrame, Standard_True);
1651     else{
1652       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1653         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1654       Ctx->UpdateCurrentViewer();
1655     }
1656   }
1657   else if (!strcasecmp (buf_ret, ","))
1658   {
1659     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1660   }
1661   else if (!strcasecmp (buf_ret, "."))
1662   {
1663     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1664   }
1665   else if (!strcasecmp (buf_ret, "/"))
1666   {
1667     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1668     if (aCamera->IsStereo())
1669     {
1670       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1671       aView->Redraw();
1672     }
1673   }
1674   else if (!strcasecmp (buf_ret, "*"))
1675   {
1676     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1677     if (aCamera->IsStereo())
1678     {
1679       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1680       aView->Redraw();
1681     }
1682   }
1683   else if (*buf_ret == THE_KEY_DELETE)
1684   {
1685     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1686     if (!aCtx.IsNull()
1687      && aCtx->NbSelected() > 0)
1688     {
1689       Draw_Interprete ("verase");
1690     }
1691   }
1692   else if (*buf_ret == THE_KEY_ESCAPE)
1693   {
1694     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1695     if (!aCtx.IsNull()
1696      && Draw_ToCloseViewOnEsc)
1697     {
1698       Draw_Interprete (Draw_ToExitOnCloseView ? "exit" : "vclose");
1699     }
1700   }
1701   else
1702   {
1703     // Number
1704     Standard_Integer Num = Draw::Atoi(buf_ret);
1705     if(Num>=0 && Num<=7)
1706       ViewerTest::StandardModeActivation(Num);
1707   }
1708 }
1709
1710 //==============================================================================
1711 //function : VT_ProcessExpose
1712 //purpose  : Redraw the View on an Expose Event
1713 //==============================================================================
1714 void VT_ProcessExpose()
1715 {
1716   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1717   if (!aView3d.IsNull())
1718   {
1719     aView3d->Redraw();
1720   }
1721 }
1722
1723 //==============================================================================
1724 //function : VT_ProcessConfigure
1725 //purpose  : Resize the View on an Configure Event
1726 //==============================================================================
1727 void VT_ProcessConfigure()
1728 {
1729   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1730   if (aView3d.IsNull())
1731   {
1732     return;
1733   }
1734
1735   aView3d->MustBeResized();
1736   aView3d->Update();
1737   aView3d->Redraw();
1738 }
1739
1740 //==============================================================================
1741 //function : VT_ProcessButton1Press
1742 //purpose  : Picking
1743 //==============================================================================
1744 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1745                                          const char**     theArgVec,
1746                                          Standard_Boolean theToPick,
1747                                          Standard_Boolean theIsShift)
1748 {
1749   if (TheIsAnimating)
1750   {
1751     TheIsAnimating = Standard_False;
1752     return Standard_False;
1753   }
1754
1755   if (theToPick)
1756   {
1757     Standard_Real X, Y, Z;
1758     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1759
1760     Draw::Set (theArgVec[1], X);
1761     Draw::Set (theArgVec[2], Y);
1762     Draw::Set (theArgVec[3], Z);
1763   }
1764
1765   if (theIsShift)
1766   {
1767     ViewerTest::CurrentEventManager()->ShiftSelect();
1768   }
1769   else
1770   {
1771     ViewerTest::CurrentEventManager()->Select();
1772   }
1773
1774   return Standard_False;
1775 }
1776
1777 //==============================================================================
1778 //function : VT_ProcessButton1Release
1779 //purpose  : End selecting
1780 //==============================================================================
1781 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1782 {
1783   if (IsDragged)
1784   {
1785     IsDragged = Standard_False;
1786     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1787     if (theIsShift)
1788     {
1789       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1790                        X_Motion, Y_Motion);
1791     }
1792     else
1793     {
1794       EM->Select (X_ButtonPress, Y_ButtonPress,
1795                   X_Motion, Y_Motion);
1796     }
1797   }
1798 }
1799
1800 //==============================================================================
1801 //function : VT_ProcessButton3Press
1802 //purpose  : Start Rotation
1803 //==============================================================================
1804 void VT_ProcessButton3Press()
1805 {
1806   Start_Rot = 1;
1807   HasHlrOnBeforeRotation = ViewerTest::CurrentView()->ComputedMode();
1808   if (HasHlrOnBeforeRotation)
1809   {
1810     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1811   }
1812   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1813 }
1814
1815 //==============================================================================
1816 //function : VT_ProcessButton3Release
1817 //purpose  : End rotation
1818 //==============================================================================
1819 void VT_ProcessButton3Release()
1820 {
1821   if (Start_Rot)
1822   {
1823     Start_Rot = 0;
1824     if (HasHlrOnBeforeRotation)
1825     {
1826       HasHlrOnBeforeRotation = Standard_False;
1827       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1828       ViewerTest::CurrentView()->Redraw();
1829     }
1830   }
1831 }
1832
1833 //==============================================================================
1834 //function : ProcessControlButton1Motion
1835 //purpose  : Zoom
1836 //==============================================================================
1837
1838 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1839 static void ProcessControlButton1Motion()
1840 {
1841   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1842
1843   X_ButtonPress = X_Motion;
1844   Y_ButtonPress = Y_Motion;
1845 }
1846 #endif
1847
1848 //==============================================================================
1849 //function : VT_ProcessControlButton2Motion
1850 //purpose  : Panning
1851 //==============================================================================
1852 void VT_ProcessControlButton2Motion()
1853 {
1854   Standard_Integer aDx = X_Motion - X_ButtonPress;
1855   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1856
1857   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1858
1859   ViewerTest::CurrentView()->Pan (aDx, aDy);
1860
1861   X_ButtonPress = X_Motion;
1862   Y_ButtonPress = Y_Motion;
1863 }
1864
1865 //==============================================================================
1866 //function : VT_ProcessControlButton3Motion
1867 //purpose  : Rotation
1868 //==============================================================================
1869 void VT_ProcessControlButton3Motion()
1870 {
1871   if (Start_Rot)
1872   {
1873     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1874   }
1875 }
1876
1877 //==============================================================================
1878 //function : VT_ProcessMotion
1879 //purpose  :
1880 //==============================================================================
1881 void VT_ProcessMotion()
1882 {
1883   //pre-hilights detected objects at mouse position
1884
1885   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1886   EM->MoveTo(X_Motion, Y_Motion);
1887 }
1888
1889
1890 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1891 {
1892   Xpix = X_Motion;Ypix=Y_Motion;
1893 }
1894
1895 //==============================================================================
1896 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1897 //purpose  : Switches to an axonometric, top, left and other views
1898 //==============================================================================
1899
1900 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1901 {
1902   if ( ViewerTest::CurrentView().IsNull() )
1903   {
1904     di<<"Call vinit before this command, please\n";
1905     return 1;
1906   }
1907
1908   ViewerTest::CurrentView()->SetProj(ori);
1909   return 0;
1910 }
1911
1912 //==============================================================================
1913 //function : VAxo
1914 //purpose  : Switch to an Axonometric view
1915 //Draw arg : No args
1916 //==============================================================================
1917
1918 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1919 {
1920   return ViewProject(di, V3d_XposYnegZpos);
1921 }
1922
1923 //==============================================================================
1924 //function : VTop
1925 //purpose  : Switch to a Top View
1926 //Draw arg : No args
1927 //==============================================================================
1928
1929 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1930 {
1931   return ViewProject(di, V3d_Zpos);
1932 }
1933
1934 //==============================================================================
1935 //function : VBottom
1936 //purpose  : Switch to a Bottom View
1937 //Draw arg : No args
1938 //==============================================================================
1939
1940 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1941 {
1942   return ViewProject(di, V3d_Zneg);
1943 }
1944
1945 //==============================================================================
1946 //function : VLeft
1947 //purpose  : Switch to a Left View
1948 //Draw arg : No args
1949 //==============================================================================
1950
1951 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1952 {
1953   return ViewProject(di, V3d_Xneg);
1954 }
1955
1956 //==============================================================================
1957 //function : VRight
1958 //purpose  : Switch to a Right View
1959 //Draw arg : No args
1960 //==============================================================================
1961
1962 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1963 {
1964   return ViewProject(di, V3d_Xpos);
1965 }
1966
1967 //==============================================================================
1968 //function : VFront
1969 //purpose  : Switch to a Front View
1970 //Draw arg : No args
1971 //==============================================================================
1972
1973 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1974 {
1975   return ViewProject(di, V3d_Yneg);
1976 }
1977
1978 //==============================================================================
1979 //function : VBack
1980 //purpose  : Switch to a Back View
1981 //Draw arg : No args
1982 //==============================================================================
1983
1984 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1985 {
1986   return ViewProject(di, V3d_Ypos);
1987 }
1988
1989 //==============================================================================
1990 //function : VHelp
1991 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1992 //Draw arg : No args
1993 //==============================================================================
1994
1995 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1996 {
1997
1998   di << "Q : Quit the application\n";
1999
2000   di << "=========================\n";
2001   di << "F : FitAll\n";
2002   di << "T : TopView\n";
2003   di << "B : BottomView\n";
2004   di << "R : RightView\n";
2005   di << "L : LeftView\n";
2006   di << "A : AxonometricView\n";
2007   di << "D : ResetView\n";
2008
2009   di << "=========================\n";
2010   di << "S : Shading\n";
2011   di << "W : Wireframe\n";
2012   di << "H : HidelLineRemoval\n";
2013   di << "U : Unset display mode\n";
2014   di << "Delete : Remove selection from viewer\n";
2015
2016   di << "=========================\n";
2017   di << "Selection mode \n";
2018   di << "0 : Shape\n";
2019   di << "1 : Vertex\n";
2020   di << "2 : Edge\n";
2021   di << "3 : Wire\n";
2022   di << "4 : Face\n";
2023   di << "5 : Shell\n";
2024   di << "6 : Solid\n";
2025   di << "7 : Compound\n";
2026
2027   di << "=========================\n";
2028   di << "Z : Switch Z clipping On/Off\n";
2029   di << ", : Hilight next detected\n";
2030   di << ". : Hilight previous detected\n";
2031
2032   return 0;
2033 }
2034
2035 #ifdef _WIN32
2036
2037 static Standard_Boolean Ppick = 0;
2038 static Standard_Integer Pargc = 0;
2039 static const char**           Pargv = NULL;
2040
2041
2042 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
2043                                           UINT Msg,
2044                                           WPARAM wParam,
2045                                           LPARAM lParam )
2046 {
2047   if (!ViewerTest_myViews.IsEmpty()) {
2048
2049     WPARAM fwKeys = wParam;
2050
2051     switch( Msg ) {
2052     case WM_CLOSE:
2053        {
2054          // Delete view from map of views
2055          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
2056          return 0;
2057        }
2058        break;
2059     case WM_ACTIVATE:
2060       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
2061         || ViewerTest::CurrentView().IsNull())
2062       {
2063         // Activate inactive window
2064         if(GetWindowHandle(VT_GetWindow()) != hwnd)
2065         {
2066           ActivateView (FindViewIdByWindowHandle(hwnd));
2067         }
2068       }
2069       break;
2070
2071     case WM_LBUTTONUP:
2072       if (IsDragged && !DragFirst)
2073       {
2074         if (!GetActiveAISManipulator().IsNull())
2075         {
2076           GetActiveAISManipulator()->StopTransform();
2077           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2078         }
2079
2080         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2081         {
2082           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2083           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2084         }
2085
2086         VT_ProcessButton1Release ((fwKeys & MK_SHIFT) != 0);
2087       }
2088       IsDragged = Standard_False;
2089       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2090
2091     case WM_RBUTTONUP:
2092       if (IsDragged && !DragFirst)
2093       {
2094         if (!GetActiveAISManipulator().IsNull())
2095         {
2096           GetActiveAISManipulator()->StopTransform (Standard_False);
2097           ViewerTest::GetAISContext()->ClearSelected (Standard_True);
2098         }
2099         IsDragged = Standard_False;
2100       }
2101       return ViewerWindowProc (hwnd, Msg, wParam, lParam);
2102
2103     case WM_LBUTTONDOWN:
2104       if (!GetActiveAISManipulator().IsNull())
2105       {
2106         IsDragged = ( fwKeys == MK_LBUTTON );
2107       }
2108       else
2109       {
2110         IsDragged = ( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) );
2111       }
2112
2113       if (IsDragged)
2114       {
2115         DragFirst = Standard_True;
2116         X_ButtonPress = LOWORD(lParam);
2117         Y_ButtonPress = HIWORD(lParam);
2118       }
2119       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2120
2121     case WM_MOUSEMOVE:
2122       if (IsDragged)
2123       {
2124         X_Motion = LOWORD (lParam);
2125         Y_Motion = HIWORD (lParam);
2126         if (!GetActiveAISManipulator().IsNull())
2127         {
2128           if (DragFirst)
2129           {
2130             GetActiveAISManipulator()->StartTransform (X_ButtonPress, Y_ButtonPress, ViewerTest::CurrentView());
2131           }
2132           else
2133           {
2134             GetActiveAISManipulator()->Transform (X_Motion, Y_Motion, ViewerTest::CurrentView());
2135             ViewerTest::GetAISContext()->CurrentViewer()->Redraw();
2136           }
2137         }
2138         else
2139         {
2140           bool toRedraw = false;
2141           if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2142           {
2143             ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2144             toRedraw = true;
2145           }
2146
2147           RECT aRect;
2148           if (GetClientRect (hwnd, &aRect))
2149           {
2150             int aHeight = aRect.bottom - aRect.top;
2151             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2152             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2153             toRedraw = true;
2154           }
2155           if (toRedraw)
2156           {
2157             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2158           }
2159         }
2160
2161         DragFirst = Standard_False;
2162       }
2163       else
2164         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2165       break;
2166
2167     default:
2168       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2169     }
2170     return 0;
2171   }
2172   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
2173 }
2174
2175
2176 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
2177                                        UINT Msg,
2178                                        WPARAM wParam,
2179                                        LPARAM lParam )
2180 {
2181   static int Up = 1;
2182   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2183   if (aView.IsNull())
2184   {
2185     return DefWindowProcW (hwnd, Msg, wParam, lParam);
2186   }
2187
2188     PAINTSTRUCT    ps;
2189
2190     switch( Msg ) {
2191     case WM_PAINT:
2192       BeginPaint(hwnd, &ps);
2193       EndPaint(hwnd, &ps);
2194       VT_ProcessExpose();
2195       break;
2196
2197     case WM_SIZE:
2198       VT_ProcessConfigure();
2199       break;
2200     case WM_MOVE:
2201     case WM_MOVING:
2202     case WM_SIZING:
2203       switch (aView->RenderingParams().StereoMode)
2204       {
2205         case Graphic3d_StereoMode_RowInterlaced:
2206         case Graphic3d_StereoMode_ColumnInterlaced:
2207         case Graphic3d_StereoMode_ChessBoard:
2208           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2209           break;
2210         default:
2211           break;
2212       }
2213       break;
2214
2215     case WM_KEYDOWN:
2216       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2217       {
2218         char c[2];
2219         c[0] = (char) wParam;
2220         c[1] = '\0';
2221         if (wParam == VK_DELETE)
2222         {
2223           c[0] = THE_KEY_DELETE;
2224         }
2225         else if (wParam == VK_ESCAPE)
2226         {
2227           c[0] = THE_KEY_ESCAPE;
2228         }
2229         // comma
2230         else if (wParam == VK_OEM_COMMA)
2231         {
2232           c[0] = ',';
2233         }
2234         // dot
2235         else if (wParam == VK_OEM_PERIOD)
2236         {
2237           c[0] = '.';
2238         }
2239         else if (wParam == VK_DIVIDE)
2240         {
2241           c[0] = '/';
2242         }
2243         // dot
2244         else if (wParam == VK_MULTIPLY)
2245         {
2246           c[0] = '*';
2247         }
2248         VT_ProcessKeyPress (c);
2249       }
2250       break;
2251
2252     case WM_LBUTTONUP:
2253     case WM_MBUTTONUP:
2254     case WM_RBUTTONUP:
2255       Up = 1;
2256       VT_ProcessButton3Release();
2257       break;
2258
2259     case WM_LBUTTONDOWN:
2260     case WM_MBUTTONDOWN:
2261     case WM_RBUTTONDOWN:
2262       {
2263         WPARAM fwKeys = wParam;
2264
2265         Up = 0;
2266
2267         X_ButtonPress = LOWORD(lParam);
2268         Y_ButtonPress = HIWORD(lParam);
2269
2270         if (Msg == WM_LBUTTONDOWN)
2271         {
2272           if ((fwKeys & MK_CONTROL) != 0)
2273           {
2274             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2275           }
2276           else
2277           {
2278             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT) != 0);
2279           }
2280         }
2281         else if (Msg == WM_RBUTTONDOWN)
2282         {
2283           // Start rotation
2284           VT_ProcessButton3Press();
2285         }
2286       }
2287       break;
2288
2289     case WM_MOUSEWHEEL:
2290     {
2291       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2292       if (wParam & MK_CONTROL)
2293       {
2294         if (aView->Camera()->IsStereo())
2295         {
2296           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2297           if (aFocus > 0.2
2298            && aFocus < 2.0)
2299           {
2300             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2301             aView->Redraw();
2302           }
2303         }
2304       }
2305       else
2306       {
2307         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2308       }
2309       break;
2310     }
2311
2312     case WM_MOUSEMOVE:
2313       {
2314         //cout << "\t WM_MOUSEMOVE" << endl;
2315         WPARAM fwKeys = wParam;
2316         X_Motion = LOWORD(lParam);
2317         Y_Motion = HIWORD(lParam);
2318
2319         if ( Up &&
2320           (fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON )) != 0 )
2321           {
2322             Up = 0;
2323             X_ButtonPress = LOWORD(lParam);
2324             Y_ButtonPress = HIWORD(lParam);
2325
2326             if ((fwKeys & MK_RBUTTON) != 0) {
2327               // Start rotation
2328               VT_ProcessButton3Press();
2329             }
2330           }
2331
2332           if ((fwKeys & MK_CONTROL) != 0)
2333           {
2334             if ((fwKeys & MK_LBUTTON) != 0)
2335             {
2336               ProcessControlButton1Motion();
2337             }
2338             else if ((fwKeys & MK_MBUTTON) != 0
2339                  || ((fwKeys & MK_LBUTTON) != 0
2340                   && (fwKeys & MK_RBUTTON) != 0))
2341             {
2342               VT_ProcessControlButton2Motion();
2343             }
2344             else if ((fwKeys & MK_RBUTTON) != 0)
2345             {
2346               VT_ProcessControlButton3Motion();
2347             }
2348           }
2349           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2350           {
2351             VT_ProcessMotion();
2352           }
2353       }
2354       break;
2355
2356     default:
2357       return DefWindowProcW (hwnd, Msg, wParam, lParam);
2358     }
2359     return 0L;
2360 }
2361
2362 //==============================================================================
2363 //function : ViewerMainLoop
2364 //purpose  : Get a Event on the view and dispatch it
2365 //==============================================================================
2366
2367
2368 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2369 {
2370   Ppick = (argc > 0)? 1 : 0;
2371   Pargc = argc;
2372   Pargv = argv;
2373
2374   if ( Ppick ) {
2375     MSG msg;
2376     msg.wParam = 1;
2377
2378     cout << "Start picking" << endl;
2379
2380     while ( Ppick == 1 ) {
2381       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2382       if (GetMessageW (&msg, NULL, 0, 0))
2383       {
2384         TranslateMessage (&msg);
2385         DispatchMessageW (&msg);
2386       }
2387     }
2388
2389     cout << "Picking done" << endl;
2390   }
2391
2392   return Ppick;
2393 }
2394
2395 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2396
2397 int min( int a, int b )
2398 {
2399   if( a<b )
2400     return a;
2401   else
2402     return b;
2403 }
2404
2405 int max( int a, int b )
2406 {
2407   if( a>b )
2408     return a;
2409   else
2410     return b;
2411 }
2412
2413 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2414
2415 {
2416   static XEvent aReport;
2417   Standard_Boolean pick = argc > 0;
2418   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2419   XNextEvent (aDisplay, &aReport);
2420
2421   // Handle event for the chosen display connection
2422   switch (aReport.type) {
2423       case ClientMessage:
2424         {
2425           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2426           {
2427             // Close the window
2428             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2429           }
2430         }
2431         return 0;
2432      case FocusIn:
2433       {
2434          // Activate inactive view
2435          Window aWindow = GetWindowHandle(VT_GetWindow());
2436          if(aWindow != aReport.xfocus.window)
2437          {
2438            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2439          }
2440       }
2441       break;
2442       case Expose:
2443         {
2444           VT_ProcessExpose();
2445         }
2446         break;
2447       case ConfigureNotify:
2448         {
2449           VT_ProcessConfigure();
2450         }
2451         break;
2452       case KeyPress:
2453         {
2454
2455           KeySym ks_ret ;
2456           char buf_ret[11] ;
2457           int ret_len ;
2458           XComposeStatus status_in_out;
2459
2460           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2461             (char *) buf_ret , 10 ,
2462             &ks_ret , &status_in_out ) ;
2463
2464
2465           buf_ret[ret_len] = '\0' ;
2466
2467           if (ret_len)
2468           {
2469             VT_ProcessKeyPress (buf_ret);
2470           }
2471         }
2472         break;
2473       case ButtonPress:
2474         {
2475           X_ButtonPress = aReport.xbutton.x;
2476           Y_ButtonPress = aReport.xbutton.y;
2477
2478           if (aReport.xbutton.button == Button1)
2479           {
2480             if (aReport.xbutton.state & ControlMask)
2481             {
2482               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2483             }
2484             else
2485             {
2486               IsDragged = Standard_True;
2487               DragFirst = Standard_True;
2488             }
2489           }
2490           else if (aReport.xbutton.button == Button3)
2491           {
2492             // Start rotation
2493             VT_ProcessButton3Press();
2494           }
2495         }
2496         break;
2497       case ButtonRelease:
2498         {
2499           if( IsDragged )
2500           {
2501             if( !DragFirst )
2502             {
2503               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2504               {
2505                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2506                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2507               }
2508             }
2509
2510             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2511             if( aContext.IsNull() )
2512             {
2513               cout << "The context is null. Please use vinit before createmesh" << endl;
2514               return 0;
2515             }
2516
2517             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2518             if( aReport.xbutton.button==1 )
2519               if( DragFirst )
2520                 if( ShiftPressed )
2521                 {
2522                   aContext->ShiftSelect (Standard_True);
2523                 }
2524                 else
2525                 {
2526                   aContext->Select (Standard_True);
2527                 }
2528               else
2529                 if( ShiftPressed )
2530                 {
2531                   aContext->ShiftSelect(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2532                                         Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2533                                         ViewerTest::CurrentView(), Standard_True);
2534                 }
2535                 else
2536                 {
2537                   aContext->Select(Min(X_ButtonPress, X_Motion), Min(Y_ButtonPress, Y_Motion),
2538                                    Max(X_ButtonPress, X_Motion), Max(Y_ButtonPress, Y_Motion),
2539                                    ViewerTest::CurrentView(), Standard_True);
2540                 }
2541             else
2542               VT_ProcessButton3Release();
2543
2544             IsDragged = Standard_False;
2545           }
2546           else
2547             VT_ProcessButton3Release();
2548         }
2549         break;
2550       case MotionNotify:
2551         {
2552           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2553           {
2554             break;
2555           }
2556           if( IsDragged )
2557           {
2558             if( !DragFirst )
2559             {
2560               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2561               {
2562                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2563               }
2564             }
2565
2566             X_Motion = aReport.xmotion.x;
2567             Y_Motion = aReport.xmotion.y;
2568             DragFirst = Standard_False;
2569
2570             Window aWindow = GetWindowHandle(VT_GetWindow());
2571             Window aRoot;
2572             int anX, anY;
2573             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2574             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2575             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2576             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2577             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2578           }
2579           else
2580           {
2581             X_Motion = aReport.xmotion.x;
2582             Y_Motion = aReport.xmotion.y;
2583
2584             // remove all the ButtonMotionMaskr
2585             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2586
2587             if ( aReport.xmotion.state & ControlMask ) {
2588               if ( aReport.xmotion.state & Button1Mask ) {
2589                 ProcessControlButton1Motion();
2590               }
2591               else if ( aReport.xmotion.state & Button2Mask ) {
2592                 VT_ProcessControlButton2Motion();
2593               }
2594               else if ( aReport.xmotion.state & Button3Mask ) {
2595                 VT_ProcessControlButton3Motion();
2596               }
2597             }
2598             else
2599             {
2600               VT_ProcessMotion();
2601             }
2602           }
2603         }
2604         break;
2605 }
2606 return pick;
2607 }
2608
2609 //==============================================================================
2610 //function : VProcessEvents
2611 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2612 //       event in the Viewer window
2613 //==============================================================================
2614
2615 static void VProcessEvents(ClientData,int)
2616 {
2617   NCollection_Vector<int> anEventNumbers;
2618   // Get number of messages from every display
2619   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2620        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2621   {
2622     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2623   }
2624     // Handle events for every display
2625   int anEventIter = 0;
2626   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2627        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2628   {
2629     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2630          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2631     {
2632       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2633       int anEventResult = ViewerMainLoop( 0, NULL);
2634       // If window is closed or context was not found finish current event processing loop
2635       if (!anEventResult)
2636         return;
2637     }
2638   }
2639
2640   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2641
2642 }
2643 #endif
2644
2645 //==============================================================================
2646 //function : OSWindowSetup
2647 //purpose  : Setup for the X11 window to be able to cath the event
2648 //==============================================================================
2649
2650
2651 static void OSWindowSetup()
2652 {
2653 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2654   // X11
2655
2656   Window  window   = VT_GetWindow()->XWindow();
2657   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2658   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2659   XSynchronize(aDisplay, 1);
2660
2661   // X11 : For keyboard on SUN
2662   XWMHints wmhints;
2663   wmhints.flags = InputHint;
2664   wmhints.input = 1;
2665
2666   XSetWMHints( aDisplay, window, &wmhints);
2667
2668   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2669     ButtonPressMask | ButtonReleaseMask |
2670     StructureNotifyMask |
2671     PointerMotionMask |
2672     Button1MotionMask | Button2MotionMask |
2673     Button3MotionMask | FocusChangeMask
2674     );
2675   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2676   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2677
2678   XSynchronize(aDisplay, 0);
2679
2680 #else
2681   // _WIN32
2682 #endif
2683
2684 }
2685
2686 //==============================================================================
2687 //function : VFit
2688 //purpose  :
2689 //==============================================================================
2690
2691 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
2692 {
2693   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2694   if (aView.IsNull())
2695   {
2696     std::cout << "Error: no active viewer!\n";
2697     return 1;
2698   }
2699
2700   Standard_Boolean toFit = Standard_True;
2701   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2702   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2703   {
2704     TCollection_AsciiString anArg (theArgv[anArgIter]);
2705     anArg.LowerCase();
2706     if (anUpdateTool.parseRedrawMode (anArg))
2707     {
2708       continue;
2709     }
2710     else if (anArg == "-selected")
2711     {
2712       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2713       toFit = Standard_False;
2714     }
2715     else
2716     {
2717       std::cout << "Syntax error at '" << anArg << "'\n";
2718     }
2719   }
2720
2721   if (toFit)
2722   {
2723     aView->FitAll (0.01, Standard_False);
2724   }
2725   return 0;
2726 }
2727
2728 //=======================================================================
2729 //function : VFitArea
2730 //purpose  : Fit view to show area located between two points
2731 //         : given in world 2D or 3D coordinates.
2732 //=======================================================================
2733 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2734 {
2735   Handle(V3d_View) aView = ViewerTest::CurrentView();
2736   if (aView.IsNull())
2737   {
2738     std::cerr << theArgVec[0] << "Error: No active view.\n";
2739     return 1;
2740   }
2741
2742   // Parse arguments.
2743   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2744   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2745
2746   if (theArgNb == 5)
2747   {
2748     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2749     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2750     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2751     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2752   }
2753   else if (theArgNb == 7)
2754   {
2755     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2756     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2757     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2758     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2759     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2760     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2761   }
2762   else
2763   {
2764     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2765     theDI.PrintHelp(theArgVec[0]);
2766     return 1;
2767   }
2768
2769   // Convert model coordinates to view space
2770   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2771   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2772   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2773
2774   // Determine fit area
2775   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2776   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2777
2778   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2779
2780   if (aDiagonal < Precision::Confusion())
2781   {
2782     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2783     return 1;
2784   }
2785
2786   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2787   return 0;
2788 }
2789
2790 //==============================================================================
2791 //function : VZFit
2792 //purpose  : ZFitall, no DRAW arguments
2793 //Draw arg : No args
2794 //==============================================================================
2795 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2796 {
2797   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2798
2799   if (aCurrentView.IsNull())
2800   {
2801     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2802     return 1;
2803   }
2804
2805   if (theArgsNb == 1)
2806   {
2807     aCurrentView->ZFitAll();
2808     aCurrentView->Redraw();
2809     return 0;
2810   }
2811
2812   Standard_Real aScale = 1.0;
2813
2814   if (theArgsNb >= 2)
2815   {
2816     aScale = Draw::Atoi (theArgVec[1]);
2817   }
2818
2819   aCurrentView->ZFitAll (aScale);
2820   aCurrentView->Redraw();
2821
2822   return 0;
2823 }
2824
2825 //==============================================================================
2826 //function : VRepaint
2827 //purpose  :
2828 //==============================================================================
2829 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
2830 {
2831   Handle(V3d_View) aView = ViewerTest::CurrentView();
2832   if (aView.IsNull())
2833   {
2834     std::cout << "Error: no active viewer!\n";
2835     return 1;
2836   }
2837
2838   Standard_Boolean isImmediateUpdate = Standard_False;
2839   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2840   {
2841     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2842     anArg.LowerCase();
2843     if (anArg == "-immediate")
2844     {
2845       isImmediateUpdate = Standard_True;
2846       if (anArgIter + 1 < theArgNb
2847        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
2848       {
2849         ++anArgIter;
2850       }
2851     }
2852     else
2853     {
2854       std::cout << "Syntax error at '" << anArg << "'\n";
2855     }
2856   }
2857
2858   if (isImmediateUpdate)
2859   {
2860     aView->RedrawImmediate();
2861   }
2862   else
2863   {
2864     aView->Redraw();
2865   }
2866   return 0;
2867 }
2868
2869 //==============================================================================
2870 //function : VClear
2871 //purpose  : Remove all the object from the viewer
2872 //Draw arg : No args
2873 //==============================================================================
2874
2875 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2876 {
2877   Handle(V3d_View) V = ViewerTest::CurrentView();
2878   if(!V.IsNull())
2879     ViewerTest::Clear();
2880   return 0;
2881 }
2882
2883 //==============================================================================
2884 //function : VPick
2885 //purpose  :
2886 //==============================================================================
2887
2888 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2889 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2890
2891 if ( argc < 4 ) {
2892   di << argv[0] << "Invalid number of arguments\n";
2893   return 1;
2894 }
2895
2896 while (ViewerMainLoop( argc, argv)) {
2897 }
2898
2899 return 0;
2900 }
2901
2902 //==============================================================================
2903 //function : VSetBg
2904 //purpose  : Load image as background
2905 //==============================================================================
2906
2907 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2908 {
2909   if (argc < 2 || argc > 3)
2910   {
2911     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2912     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2913     return 1;
2914   }
2915
2916   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2917   if(AISContext.IsNull())
2918   {
2919     di << "use 'vinit' command before " << argv[0] << "\n";
2920     return 1;
2921   }
2922
2923   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2924   if (argc == 3)
2925   {
2926     const char* szType = argv[2];
2927     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2928     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2929     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2930     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2931     else
2932     {
2933       di << "Wrong fill type : " << szType << "\n";
2934       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2935       return 1;
2936     }
2937   }
2938
2939   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2940   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2941
2942   return 0;
2943 }
2944
2945 //==============================================================================
2946 //function : VSetBgMode
2947 //purpose  : Change background image fill type
2948 //==============================================================================
2949
2950 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2951 {
2952   if (argc != 2)
2953   {
2954     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2955     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2956     return 1;
2957   }
2958
2959   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2960   if(AISContext.IsNull())
2961   {
2962     di << "use 'vinit' command before " << argv[0] << "\n";
2963     return 1;
2964   }
2965   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2966   const char* szType = argv[1];
2967   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2968   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2969   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2970   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2971   else
2972   {
2973     di << "Wrong fill type : " << szType << "\n";
2974     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2975     return 1;
2976   }
2977   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2978   V3dView->SetBgImageStyle(aFillType, Standard_True);
2979   return 0;
2980 }
2981
2982 //==============================================================================
2983 //function : VSetGradientBg
2984 //purpose  : Mount gradient background
2985 //==============================================================================
2986 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2987 {
2988   if (argc != 8 )
2989   {
2990     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2991     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2992     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2993     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2994     return 1;
2995   }
2996
2997   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2998   if(AISContext.IsNull())
2999   {
3000     di << "use 'vinit' command before " << argv[0] << "\n";
3001     return 1;
3002   }
3003   if (argc == 8)
3004   {
3005
3006     Standard_Real R1 = Draw::Atof(argv[1])/255.;
3007     Standard_Real G1 = Draw::Atof(argv[2])/255.;
3008     Standard_Real B1 = Draw::Atof(argv[3])/255.;
3009     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
3010
3011     Standard_Real R2 = Draw::Atof(argv[4])/255.;
3012     Standard_Real G2 = Draw::Atof(argv[5])/255.;
3013     Standard_Real B2 = Draw::Atof(argv[6])/255.;
3014
3015     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
3016     int aType = Draw::Atoi(argv[7]);
3017     if( aType < 0 || aType > 8 )
3018     {
3019       di << "Wrong fill type \n";
3020       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3021       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3022       return 1;
3023     }
3024
3025     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3026
3027     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3028     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
3029   }
3030
3031   return 0;
3032 }
3033
3034 //==============================================================================
3035 //function : VSetGradientBgMode
3036 //purpose  : Change gradient background fill style
3037 //==============================================================================
3038 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3039 {
3040   if (argc != 2 )
3041   {
3042     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
3043     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3044     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3045     return 1;
3046   }
3047
3048   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3049   if(AISContext.IsNull())
3050   {
3051     di << "use 'vinit' command before " << argv[0] << "\n";
3052     return 1;
3053   }
3054   if (argc == 2)
3055   {
3056     int aType = Draw::Atoi(argv[1]);
3057     if( aType < 0 || aType > 8 )
3058     {
3059       di << "Wrong fill type \n";
3060       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
3061       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
3062       return 1;
3063     }
3064
3065     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
3066
3067     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3068     V3dView->SetBgGradientStyle( aMethod, 1 );
3069   }
3070
3071   return 0;
3072 }
3073
3074 //==============================================================================
3075 //function : VSetColorBg
3076 //purpose  : Set color background
3077 //==============================================================================
3078 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3079 {
3080   if (argc != 4 )
3081   {
3082     di << "Usage : " << argv[0] << " R G B : Set color background\n";
3083     di << "R,G,B = [0..255]\n";
3084     return 1;
3085   }
3086
3087   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
3088   if(AISContext.IsNull())
3089   {
3090     di << "use 'vinit' command before " << argv[0] << "\n";
3091     return 1;
3092   }
3093   if (argc == 4)
3094   {
3095
3096     Standard_Real R = Draw::Atof(argv[1])/255.;
3097     Standard_Real G = Draw::Atof(argv[2])/255.;
3098     Standard_Real B = Draw::Atof(argv[3])/255.;
3099     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
3100
3101     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3102     V3dView->SetBackgroundColor( aColor );
3103     V3dView->Update();
3104   }
3105
3106   return 0;
3107 }
3108
3109 //==============================================================================
3110 //function : VSetDefaultBg
3111 //purpose  : Set default viewer background fill color
3112 //==============================================================================
3113 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3114 {
3115   if (theArgNb != 4
3116    && theArgNb != 8)
3117   {
3118     std::cout << "Error: wrong syntax! See usage:\n";
3119     theDI.PrintHelp (theArgVec[0]);
3120     return 1;
3121   }
3122
3123   ViewerTest_DefaultBackground.FillMethod =
3124     theArgNb == 4 ? Aspect_GFM_NONE
3125                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
3126
3127   if (theArgNb == 4)
3128   {
3129     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
3130     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
3131     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
3132     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
3133   }
3134   else
3135   {
3136     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
3137     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
3138     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
3139     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
3140
3141     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
3142     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
3143     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
3144     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
3145   }
3146
3147   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
3148        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
3149   {
3150     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
3151     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
3152     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
3153                                          ViewerTest_DefaultBackground.GradientColor2,
3154                                          ViewerTest_DefaultBackground.FillMethod);
3155   }
3156
3157   return 0;
3158 }
3159
3160 //==============================================================================
3161 //function : VScale
3162 //purpose  : View Scaling
3163 //==============================================================================
3164
3165 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3166 {
3167   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3168   if ( V3dView.IsNull() ) return 1;
3169
3170   if ( argc != 4 ) {
3171     di << argv[0] << "Invalid number of arguments\n";
3172     return 1;
3173   }
3174   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3175   return 0;
3176 }
3177 //==============================================================================
3178 //function : VZBuffTrihedron
3179 //purpose  :
3180 //==============================================================================
3181
3182 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3183                             Standard_Integer  theArgNb,
3184                             const char**      theArgVec)
3185 {
3186   Handle(V3d_View) aView = ViewerTest::CurrentView();
3187   if (aView.IsNull())
3188   {
3189     std::cout << "Error: no active viewer!\n";
3190     return 1;
3191   }
3192
3193   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3194
3195   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3196   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3197   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3198   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3199   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3200   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3201   Standard_Real                 aScale        = 0.1;
3202   Standard_Real                 aSizeRatio    = 0.8;
3203   Standard_Real                 anArrowDiam   = 0.05;
3204   Standard_Integer              aNbFacets     = 12;
3205   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3206   {
3207     Standard_CString        anArg = theArgVec[anArgIter];
3208     TCollection_AsciiString aFlag (anArg);
3209     aFlag.LowerCase();
3210     if (anUpdateTool.parseRedrawMode (aFlag))
3211     {
3212       continue;
3213     }
3214     else if (aFlag == "-on")
3215     {
3216       continue;
3217     }
3218     else if (aFlag == "-off")
3219     {
3220       aView->TriedronErase();
3221       return 0;
3222     }
3223     else if (aFlag == "-pos"
3224           || aFlag == "-position"
3225           || aFlag == "-corner")
3226     {
3227       if (++anArgIter >= theArgNb)
3228       {
3229         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3230         return 1;
3231       }
3232
3233       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3234       aPosName.LowerCase();
3235       if (aPosName == "center")
3236       {
3237         aPosition = Aspect_TOTP_CENTER;
3238       }
3239       else if (aPosName == "left_lower"
3240             || aPosName == "lower_left"
3241             || aPosName == "leftlower"
3242             || aPosName == "lowerleft")
3243       {
3244         aPosition = Aspect_TOTP_LEFT_LOWER;
3245       }
3246       else if (aPosName == "left_upper"
3247             || aPosName == "upper_left"
3248             || aPosName == "leftupper"
3249             || aPosName == "upperleft")
3250       {
3251         aPosition = Aspect_TOTP_LEFT_UPPER;
3252       }
3253       else if (aPosName == "right_lower"
3254             || aPosName == "lower_right"
3255             || aPosName == "rightlower"
3256             || aPosName == "lowerright")
3257       {
3258         aPosition = Aspect_TOTP_RIGHT_LOWER;
3259       }
3260       else if (aPosName == "right_upper"
3261             || aPosName == "upper_right"
3262             || aPosName == "rightupper"
3263             || aPosName == "upperright")
3264       {
3265         aPosition = Aspect_TOTP_RIGHT_UPPER;
3266       }
3267       else
3268       {
3269         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3270         return 1;
3271       }
3272     }
3273     else if (aFlag == "-type")
3274     {
3275       if (++anArgIter >= theArgNb)
3276       {
3277         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3278         return 1;
3279       }
3280
3281       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3282       aTypeName.LowerCase();
3283       if (aTypeName == "wireframe"
3284        || aTypeName == "wire")
3285       {
3286         aVisType = V3d_WIREFRAME;
3287       }
3288       else if (aTypeName == "zbuffer"
3289             || aTypeName == "shaded")
3290       {
3291         aVisType = V3d_ZBUFFER;
3292       }
3293       else
3294       {
3295         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3296       }
3297     }
3298     else if (aFlag == "-scale")
3299     {
3300       if (++anArgIter >= theArgNb)
3301       {
3302         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3303         return 1;
3304       }
3305
3306       aScale = Draw::Atof (theArgVec[anArgIter]);
3307     }
3308     else if (aFlag == "-size"
3309           || aFlag == "-sizeratio")
3310     {
3311       if (++anArgIter >= theArgNb)
3312       {
3313         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3314         return 1;
3315       }
3316
3317       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3318     }
3319     else if (aFlag == "-arrowdiam"
3320           || aFlag == "-arrowdiameter")
3321     {
3322       if (++anArgIter >= theArgNb)
3323       {
3324         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3325         return 1;
3326       }
3327
3328       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3329     }
3330     else if (aFlag == "-nbfacets")
3331     {
3332       if (++anArgIter >= theArgNb)
3333       {
3334         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3335         return 1;
3336       }
3337
3338       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3339     }
3340     else if (aFlag == "-colorlabel"
3341           || aFlag == "-colorlabels")
3342     {
3343       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3344                                                            theArgVec + anArgIter + 1,
3345                                                            aLabelsColor);
3346       if (aNbParsed == 0)
3347       {
3348         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3349         return 1;
3350       }
3351       anArgIter += aNbParsed;
3352     }
3353     else if (aFlag == "-colorarrowx")
3354     {
3355       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3356                                                            theArgVec + anArgIter + 1,
3357                                                            anArrowColorX);
3358       if (aNbParsed == 0)
3359       {
3360         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3361         return 1;
3362       }
3363       anArgIter += aNbParsed;
3364     }
3365     else if (aFlag == "-colorarrowy")
3366     {
3367       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3368                                                            theArgVec + anArgIter + 1,
3369                                                            anArrowColorY);
3370       if (aNbParsed == 0)
3371       {
3372         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3373         return 1;
3374       }
3375       anArgIter += aNbParsed;
3376     }
3377     else if (aFlag == "-colorarrowz")
3378     {
3379       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3380                                                            theArgVec + anArgIter + 1,
3381                                                            anArrowColorZ);
3382       if (aNbParsed == 0)
3383       {
3384         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3385         return 1;
3386       }
3387       anArgIter += aNbParsed;
3388     }
3389     else
3390     {
3391       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3392       return 1;
3393     }
3394   }
3395
3396   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3397                                aSizeRatio, anArrowDiam, aNbFacets);
3398   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3399   aView->ZFitAll();
3400   return 0;
3401 }
3402
3403 //==============================================================================
3404 //function : VRotate
3405 //purpose  : Camera Rotating
3406 //==============================================================================
3407
3408 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3409 {
3410   Handle(V3d_View) aView = ViewerTest::CurrentView();
3411   if (aView.IsNull())
3412   {
3413     std::cout << "No active view!\n";
3414     return 1;
3415   }
3416
3417   Standard_Boolean hasFlags = Standard_False;
3418   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3419   {
3420     Standard_CString        anArg (theArgVec[anArgIter]);
3421     TCollection_AsciiString aFlag (anArg);
3422     aFlag.LowerCase();
3423     if (aFlag == "-mousestart"
3424      || aFlag == "-mousefrom")
3425     {
3426       hasFlags = Standard_True;
3427       if (anArgIter + 2 >= theArgNb)
3428       {
3429         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3430         return 1;
3431       }
3432
3433       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3434       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3435       aView->StartRotation (anX, anY);
3436     }
3437     else if (aFlag == "-mousemove")
3438     {
3439       hasFlags = Standard_True;
3440       if (anArgIter + 2 >= theArgNb)
3441       {
3442         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3443         return 1;
3444       }
3445
3446       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3447       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3448       aView->Rotation (anX, anY);
3449     }
3450     else if (theArgNb != 4
3451           && theArgNb != 7)
3452     {
3453       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3454       return 1;
3455     }
3456   }
3457
3458   if (hasFlags)
3459   {
3460     return 0;
3461   }
3462   else if (theArgNb == 4)
3463   {
3464     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3465     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3466     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3467     aView->Rotate (anAX, anAY, anAZ);
3468     return 0;
3469   }
3470   else if (theArgNb == 7)
3471   {
3472     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3473     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3474     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3475
3476     Standard_Real anX = Draw::Atof (theArgVec[4]);
3477     Standard_Real anY = Draw::Atof (theArgVec[5]);
3478     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3479
3480     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3481     return 0;
3482   }
3483
3484   std::cout << "Error: Invalid number of arguments\n";
3485   return 1;
3486 }
3487
3488 //==============================================================================
3489 //function : VZoom
3490 //purpose  : View zoom in / out (relative to current zoom)
3491 //==============================================================================
3492
3493 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3494   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3495   if ( V3dView.IsNull() ) {
3496     return 1;
3497   }
3498
3499   if ( argc == 2 ) {
3500     Standard_Real coef = Draw::Atof(argv[1]);
3501     if ( coef <= 0.0 ) {
3502       di << argv[1] << "Invalid value\n";
3503       return 1;
3504     }
3505     V3dView->SetZoom( Draw::Atof(argv[1]) );
3506     return 0;
3507   } else {
3508     di << argv[0] << " Invalid number of arguments\n";
3509     return 1;
3510   }
3511 }
3512
3513 //==============================================================================
3514 //function : VPan
3515 //purpose  : View panning (in pixels)
3516 //==============================================================================
3517
3518 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3519   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3520   if ( V3dView.IsNull() ) return 1;
3521
3522   if ( argc == 3 ) {
3523     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3524     return 0;
3525   } else {
3526     di << argv[0] << " Invalid number of arguments\n";
3527     return 1;
3528   }
3529 }
3530
3531 //==============================================================================
3532 //function : VPlace
3533 //purpose  : Place the point (in pixels) at the center of the window
3534 //==============================================================================
3535 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3536 {
3537   Handle(V3d_View) aView = ViewerTest::CurrentView();
3538   if (aView.IsNull())
3539   {
3540     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3541     return 1;
3542   }
3543
3544   if (theArgNb != 3)
3545   {
3546     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3547     return 1;
3548   }
3549
3550   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3551
3552   return 0;
3553 }
3554
3555 //==============================================================================
3556 //function : VExport
3557 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3558 //==============================================================================
3559
3560 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3561 {
3562   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3563   if (V3dView.IsNull())
3564     return 1;
3565
3566   if (argc == 1)
3567   {
3568     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3569     return 1;
3570   }
3571
3572   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3573   TCollection_AsciiString aFormatStr;
3574
3575   TCollection_AsciiString aFileName (argv[1]);
3576   Standard_Integer aLen = aFileName.Length();
3577
3578   if (argc > 2)
3579   {
3580     aFormatStr = TCollection_AsciiString (argv[2]);
3581   }
3582   else if (aLen >= 4)
3583   {
3584     if (aFileName.Value (aLen - 2) == '.')
3585     {
3586       aFormatStr = aFileName.ToCString() + aLen - 2;
3587     }
3588     else if (aFileName.Value (aLen - 3) == '.')
3589     {
3590       aFormatStr = aFileName.ToCString() + aLen - 3;
3591     }
3592     else
3593     {
3594       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3595       return 1;
3596     }
3597   }
3598   else
3599   {
3600     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3601     return 1;
3602   }
3603
3604   aFormatStr.UpperCase();
3605   if (aFormatStr == "PS")
3606     anExpFormat = Graphic3d_EF_PostScript;
3607   else if (aFormatStr == "EPS")
3608     anExpFormat = Graphic3d_EF_EnhPostScript;
3609   else if (aFormatStr == "TEX")
3610     anExpFormat = Graphic3d_EF_TEX;
3611   else if (aFormatStr == "PDF")
3612     anExpFormat = Graphic3d_EF_PDF;
3613   else if (aFormatStr == "SVG")
3614     anExpFormat = Graphic3d_EF_SVG;
3615   else if (aFormatStr == "PGF")
3616     anExpFormat = Graphic3d_EF_PGF;
3617   else if (aFormatStr == "EMF")
3618     anExpFormat = Graphic3d_EF_EMF;
3619   else
3620   {
3621     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3622     return 1;
3623   }
3624
3625   Standard_DISABLE_DEPRECATION_WARNINGS
3626   try
3627   {
3628     if (!V3dView->Export (argv[1], anExpFormat))
3629     {
3630       di << "Error: export of image to " << aFormatStr << " failed!\n";
3631     }
3632   }
3633   catch (Standard_Failure const& anException)
3634   {
3635     di << "Error: export of image to " << aFormatStr << " failed";
3636     di << " (exception: " << anException.GetMessageString() << ")";
3637   }
3638   Standard_ENABLE_DEPRECATION_WARNINGS
3639   return 0;
3640 }
3641
3642 static int VColorScale (Draw_Interpretor& theDI,
3643                         Standard_Integer  theArgNb,
3644                         const char**      theArgVec)
3645 {
3646   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3647   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3648   if (aContext.IsNull())
3649   {
3650     std::cout << "Error: no active view!\n";
3651     return 1;
3652   }
3653   if (theArgNb <= 1)
3654   {
3655     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3656     return 1;
3657   }
3658
3659   Handle(AIS_ColorScale) aColorScale;
3660   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
3661   {
3662     // find existing object
3663     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3664     if (aColorScale.IsNull())
3665     {
3666       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
3667       return 1;
3668     }
3669   }
3670
3671   if (theArgNb <= 2)
3672   {
3673     if (aColorScale.IsNull())
3674     {
3675       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
3676       return 1;
3677     }
3678
3679     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
3680           << "Min range: "            << aColorScale->GetMin() << "\n"
3681           << "Max range: "            << aColorScale->GetMax() << "\n"
3682           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
3683           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
3684           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3685           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
3686           << "Label position: ";
3687     switch (aColorScale->GetLabelPosition())
3688     {
3689       case Aspect_TOCSP_NONE:
3690         theDI << "None\n";
3691         break;
3692       case Aspect_TOCSP_LEFT:
3693         theDI << "Left\n";
3694         break;
3695       case Aspect_TOCSP_RIGHT:
3696         theDI << "Right\n";
3697         break;
3698       case Aspect_TOCSP_CENTER:
3699         theDI << "Center\n";
3700         break;
3701     }
3702     return 0;
3703   }
3704
3705   if (aColorScale.IsNull())
3706   {
3707     aColorScale = new AIS_ColorScale();
3708     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3709     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3710   }
3711
3712   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
3713   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
3714   {
3715     Standard_CString        anArg = theArgVec[anArgIter];
3716     TCollection_AsciiString aFlag (anArg);
3717     aFlag.LowerCase();
3718     if (anUpdateTool.parseRedrawMode (aFlag))
3719     {
3720       continue;
3721     }
3722     else if (aFlag == "-range")
3723     {
3724       if (anArgIter + 3 >= theArgNb)
3725       {
3726         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3727         return 1;
3728       }
3729
3730       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
3731       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
3732       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
3733       if (!aRangeMin.IsRealValue()
3734        || !aRangeMax.IsRealValue())
3735       {
3736         std::cout << "Error: the range values should be real!\n";
3737         return 1;
3738       }
3739       else if (!aNbIntervals.IsIntegerValue())
3740       {
3741         std::cout << "Error: the number of intervals should be integer!\n";
3742         return 1;
3743       }
3744
3745       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3746       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
3747     }
3748     else if (aFlag == "-font")
3749     {
3750       if (anArgIter + 1 >= theArgNb)
3751       {
3752         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3753         return 1;
3754       }
3755       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3756       if (!aFontArg.IsIntegerValue())
3757       {
3758         std::cout << "Error: HeightFont value should be integer!\n";
3759         return 1;
3760       }
3761
3762       aColorScale->SetTextHeight (aFontArg.IntegerValue());
3763       anArgIter += 1;
3764     }
3765     else if (aFlag == "-textpos")
3766     {
3767       if (anArgIter + 1 >= theArgNb)
3768       {
3769         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3770         return 1;
3771       }
3772
3773       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3774       aTextPosArg.LowerCase();
3775       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
3776       if (aTextPosArg == "none")
3777       {
3778         aLabPosition = Aspect_TOCSP_NONE;
3779       }
3780       else if (aTextPosArg == "left")
3781       {
3782         aLabPosition = Aspect_TOCSP_LEFT;
3783       }
3784       else if (aTextPosArg == "right")
3785       {
3786         aLabPosition = Aspect_TOCSP_RIGHT;
3787       }
3788       else if (aTextPosArg == "center")
3789       {
3790         aLabPosition = Aspect_TOCSP_CENTER;
3791       }
3792       else
3793       {
3794         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
3795         return 1;
3796       }
3797       aColorScale->SetLabelPosition (aLabPosition);
3798     }
3799     else if (aFlag == "-logarithmic"
3800           || aFlag == "-log")
3801     {
3802       if (anArgIter + 1 >= theArgNb)
3803       {
3804         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3805         return 1;
3806       }
3807
3808       Standard_Boolean IsLog;
3809       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
3810       {
3811         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3812         return 1;
3813       }
3814       aColorScale->SetLogarithmic (IsLog);
3815     }
3816     else if (aFlag == "-huerange"
3817           || aFlag == "-hue")
3818     {
3819       if (anArgIter + 2 >= theArgNb)
3820       {
3821         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3822         return 1;
3823       }
3824
3825       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3826       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3827       aColorScale->SetHueRange (aHueMin, aHueMax);
3828     }
3829     else if (aFlag == "-colorrange")
3830     {
3831       Quantity_Color aColorMin, aColorMax;
3832       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3833                                                             theArgVec + (anArgIter + 1),
3834                                                             aColorMin);
3835       anArgIter += aNbParsed1;
3836       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3837                                                             theArgVec + (anArgIter + 1),
3838                                                             aColorMax);
3839       anArgIter += aNbParsed2;
3840       if (aNbParsed1 == 0
3841        || aNbParsed2 == 0)
3842       {
3843         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3844         return 1;
3845       }
3846
3847       aColorScale->SetColorRange (aColorMin, aColorMax);
3848     }
3849     else if (aFlag == "-reversed"
3850           || aFlag == "-inverted"
3851           || aFlag == "-topdown"
3852           || aFlag == "-bottomup")
3853     {
3854       Standard_Boolean toEnable = Standard_True;
3855       if (anArgIter + 1 < theArgNb
3856        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
3857       {
3858         ++anArgIter;
3859       }
3860       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3861     }
3862     else if (aFlag == "-smooth"
3863           || aFlag == "-smoothtransition")
3864     {
3865       Standard_Boolean toEnable = Standard_True;
3866       if (anArgIter + 1 < theArgNb
3867        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
3868       {
3869         ++anArgIter;
3870       }
3871       aColorScale->SetSmoothTransition (toEnable);
3872     }
3873     else if (aFlag == "-xy")
3874     {
3875       if (anArgIter + 2 >= theArgNb)
3876       {
3877         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3878         return 1;
3879       }
3880
3881       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3882       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3883       if (!anX.IsIntegerValue()
3884        || !anY.IsIntegerValue())
3885       {
3886         std::cout << "Error: coordinates should be integer values!\n";
3887         return 1;
3888       }
3889
3890       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
3891     }
3892     else if (aFlag == "-width"
3893           || aFlag == "-w"
3894           || aFlag == "-breadth")
3895     {
3896       if (anArgIter + 1 >= theArgNb)
3897       {
3898         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3899         return 1;
3900       }
3901
3902       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3903       if (!aBreadth.IsIntegerValue())
3904       {
3905         std::cout << "Error: a width should be an integer value!\n";
3906         return 1;
3907       }
3908       aColorScale->SetBreadth (aBreadth.IntegerValue());
3909     }
3910     else if (aFlag == "-height"
3911           || aFlag == "-h")
3912     {
3913       if (anArgIter + 1 >= theArgNb)
3914       {
3915         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3916         return 1;
3917       }
3918
3919       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3920       if (!aHeight.IsIntegerValue())
3921       {
3922         std::cout << "Error: a width should be an integer value!\n";
3923         return 1;
3924       }
3925       aColorScale->SetHeight (aHeight.IntegerValue());
3926     }
3927     else if (aFlag == "-color")
3928     {
3929       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3930       {
3931         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
3932         return 1;
3933       }
3934       else if (anArgIter + 2 >= theArgNb)
3935       {
3936         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3937         return 1;
3938       }
3939
3940       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
3941       if (!anInd.IsIntegerValue())
3942       {
3943         std::cout << "Error: Index value should be integer!\n";
3944         return 1;
3945       }
3946       const Standard_Integer anIndex = anInd.IntegerValue();
3947       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
3948       {
3949         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
3950         return 1;
3951       }
3952
3953       Quantity_Color aColor;
3954       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
3955                                                            theArgVec + (anArgIter + 1),
3956                                                            aColor);
3957       if (aNbParsed == 0)
3958       {
3959         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3960         return 1;
3961       }
3962       aColorScale->SetIntervalColor (aColor, anIndex);
3963       aColorScale->SetColorType (Aspect_TOCSD_USER);
3964       anArgIter += aNbParsed;
3965     }
3966     else if (aFlag == "-label")
3967     {
3968       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
3969       {
3970         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
3971         return 1;
3972       }
3973       else if (anArgIter + 2 >= theArgNb)
3974       {
3975         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
3976         return 1;
3977       }
3978
3979       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
3980       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
3981       {
3982         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
3983         return 1;
3984       }
3985
3986       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
3987       aColorScale->SetLabel     (aText, anIndex);
3988       aColorScale->SetLabelType (Aspect_TOCSD_USER);
3989       anArgIter += 2;
3990     }
3991     else if (aFlag == "-labelat"
3992           || aFlag == "-labat"
3993           || aFlag == "-labelatborder"
3994           || aFlag == "-labatborder"
3995           || aFlag == "-labelatcenter"
3996           || aFlag == "-labatcenter")
3997     {
3998       Standard_Boolean toEnable = Standard_True;
3999       if (aFlag == "-labelat"
4000        || aFlag == "-labat")
4001       {
4002         Standard_Integer aLabAtBorder = -1;
4003         if (++anArgIter >= theArgNb)
4004         {
4005           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4006           anAtBorder.LowerCase();
4007           if (anAtBorder == "border")
4008           {
4009             aLabAtBorder = 1;
4010           }
4011           else if (anAtBorder == "center")
4012           {
4013             aLabAtBorder = 0;
4014           }
4015         }
4016         if (aLabAtBorder == -1)
4017         {
4018           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4019           return 1;
4020         }
4021         toEnable = (aLabAtBorder == 1);
4022       }
4023       else if (anArgIter + 1 < theArgNb
4024             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4025       {
4026         ++anArgIter;
4027       }
4028       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4029                                   || aFlag == "-labatcenter"
4030                                    ? !toEnable
4031                                    :  toEnable);
4032     }
4033     else if (aFlag == "-colors")
4034     {
4035       Aspect_SequenceOfColor aSeq;
4036       for (;;)
4037       {
4038         Quantity_Color aColor;
4039         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4040                                                              theArgVec + (anArgIter + 1),
4041                                                              aColor);
4042         if (aNbParsed == 0)
4043         {
4044           break;
4045         }
4046         anArgIter += aNbParsed;
4047         aSeq.Append (aColor);
4048       }
4049       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4050       {
4051         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4052                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4053         return 1;
4054       }
4055
4056       aColorScale->SetColors    (aSeq);
4057       aColorScale->SetColorType (Aspect_TOCSD_USER);
4058     }
4059     else if (aFlag == "-labels"
4060           || aFlag == "-freelabels")
4061     {
4062       if (anArgIter + 1 >= theArgNb)
4063       {
4064         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4065         return 1;
4066       }
4067
4068       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4069                                  ? aColorScale->GetNumberOfIntervals() + 1
4070                                  : aColorScale->GetNumberOfIntervals();
4071       if (aFlag == "-freelabels")
4072       {
4073         ++anArgIter;
4074         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4075       }
4076       if (anArgIter + aNbLabels >= theArgNb)
4077       {
4078         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4079         return 1;
4080       }
4081
4082       TColStd_SequenceOfExtendedString aSeq;
4083       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4084       {
4085         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4086       }
4087       aColorScale->SetLabels (aSeq);
4088       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4089     }
4090     else if (aFlag == "-title")
4091     {
4092       if (anArgIter + 1 >= theArgNb)
4093       {
4094         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4095         return 1;
4096       }
4097
4098       Standard_Boolean isTwoArgs = Standard_False;
4099       if (anArgIter + 2 < theArgNb)
4100       {
4101         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4102         aSecondArg.LowerCase();
4103       Standard_DISABLE_DEPRECATION_WARNINGS
4104         if (aSecondArg == "none")
4105         {
4106           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4107           isTwoArgs = Standard_True;
4108         }
4109         else if (aSecondArg == "left")
4110         {
4111           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4112           isTwoArgs = Standard_True;
4113         }
4114         else if (aSecondArg == "right")
4115         {
4116           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4117           isTwoArgs = Standard_True;
4118         }
4119         else if (aSecondArg == "center")
4120         {
4121           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4122           isTwoArgs = Standard_True;
4123         }
4124       Standard_ENABLE_DEPRECATION_WARNINGS
4125       }
4126
4127       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4128       if (isTwoArgs)
4129       {
4130         anArgIter += 1;
4131       }
4132       anArgIter += 1;
4133     }
4134     else if (aFlag == "-demoversion"
4135           || aFlag == "-demo")
4136     {
4137       aColorScale->SetPosition (0, 0);
4138       aColorScale->SetTextHeight (16);
4139       aColorScale->SetRange (0.0, 100.0);
4140       aColorScale->SetNumberOfIntervals (10);
4141       aColorScale->SetBreadth (0);
4142       aColorScale->SetHeight  (0);
4143       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4144       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4145       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4146     }
4147     else if (aFlag == "-findcolor")
4148     {
4149       if (anArgIter + 1 >= theArgNb)
4150       {
4151         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4152         return 1;
4153       }
4154
4155       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4156
4157       if (!anArg1.IsRealValue())
4158       {
4159         std::cout << "Error: the value should be real!\n";
4160         return 1;
4161       }
4162
4163       Quantity_Color aColor;
4164       aColorScale->FindColor (anArg1.RealValue(), aColor);
4165       theDI << Quantity_Color::StringName (aColor.Name());
4166       return 0;
4167     }
4168     else
4169     {
4170       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4171       return 1;
4172     }
4173   }
4174
4175   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4176   aView->Window()->Size (aWinWidth, aWinHeight);
4177   if (aColorScale->GetBreadth() == 0)
4178   {
4179     aColorScale->SetBreadth (aWinWidth);
4180   }
4181   if (aColorScale->GetHeight() == 0)
4182   {
4183     aColorScale->SetHeight (aWinHeight);
4184   }
4185   aColorScale->SetToUpdate();
4186   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4187   return 0;
4188 }
4189
4190 //==============================================================================
4191 //function : VGraduatedTrihedron
4192 //purpose  : Displays or hides a graduated trihedron
4193 //==============================================================================
4194 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4195                                   Quantity_Color& theColor)
4196 {
4197   Quantity_NameOfColor aColorName;
4198   TCollection_AsciiString aVal = theValue;
4199   aVal.UpperCase();
4200   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4201   {
4202     return Standard_False;
4203   }
4204   theColor = Quantity_Color (aColorName);
4205   return Standard_True;
4206 }
4207
4208 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4209 {
4210   if (theArgNum < 2)
4211   {
4212     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4213               << theArgs[0] <<"' for more information.\n";
4214     return 1;  //TCL_ERROR
4215   }
4216
4217   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4218   TCollection_AsciiString aParseKey;
4219   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4220   {
4221     TCollection_AsciiString anArg (theArgs [anArgIt]);
4222
4223     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4224     {
4225       aParseKey = anArg;
4226       aParseKey.Remove (1);
4227       aParseKey.LowerCase();
4228       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4229       continue;
4230     }
4231
4232     if (aParseKey.IsEmpty())
4233     {
4234       continue;
4235     }
4236
4237     aMapOfArgs(aParseKey)->Append (anArg);
4238   }
4239
4240   // Check parameters
4241   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4242        aMapIt.More(); aMapIt.Next())
4243   {
4244     const TCollection_AsciiString& aKey = aMapIt.Key();
4245     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4246
4247     // Bool key, without arguments
4248     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4249         && anArgs->IsEmpty())
4250     {
4251       continue;
4252     }
4253
4254     // One argument
4255     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4256           && anArgs->Length() == 1)
4257     {
4258       continue;
4259     }
4260
4261     // On/off arguments
4262     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4263         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4264         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4265         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4266         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4267     {
4268       continue;
4269     }
4270
4271     // One string argument
4272     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4273           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4274           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4275     {
4276       continue;
4277     }
4278
4279     // One integer argument
4280     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4281           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4282           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4283           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4284          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4285     {
4286       continue;
4287     }
4288
4289     // One real argument
4290     if ( aKey.IsEqual ("arrowlength")
4291          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4292     {
4293       continue;
4294     }
4295
4296     // Two string arguments
4297     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4298          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4299     {
4300       continue;
4301     }
4302
4303     TCollection_AsciiString aLowerKey;
4304     aLowerKey  = "-";
4305     aLowerKey += aKey;
4306     aLowerKey.LowerCase();
4307     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4308     std::cout << "Type help for more information.\n";
4309     return 1;
4310   }
4311
4312   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4313   if (anAISContext.IsNull())
4314   {
4315     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4316     return 1;
4317   }
4318
4319   Standard_Boolean toDisplay = Standard_True;
4320   Quantity_Color aColor;
4321   Graphic3d_GraduatedTrihedron aTrihedronData;
4322   // Process parameters
4323   Handle(TColStd_HSequenceOfAsciiString) aValues;
4324   if (aMapOfArgs.Find ("off", aValues))
4325   {
4326     toDisplay = Standard_False;
4327   }
4328
4329   // AXES NAMES
4330   if (aMapOfArgs.Find ("xname", aValues))
4331   {
4332     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4333   }
4334   if (aMapOfArgs.Find ("yname", aValues))
4335   {
4336     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4337   }
4338   if (aMapOfArgs.Find ("zname", aValues))
4339   {
4340     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4341   }
4342   if (aMapOfArgs.Find ("xdrawname", aValues))
4343   {
4344     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4345   }
4346   if (aMapOfArgs.Find ("ydrawname", aValues))
4347   {
4348     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4349   }
4350   if (aMapOfArgs.Find ("zdrawname", aValues))
4351   {
4352     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4353   }
4354   if (aMapOfArgs.Find ("xnameoffset", aValues))
4355   {
4356     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4357   }
4358   if (aMapOfArgs.Find ("ynameoffset", aValues))
4359   {
4360     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4361   }
4362   if (aMapOfArgs.Find ("znameoffset", aValues))
4363   {
4364     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4365   }
4366
4367   // COLORS
4368   if (aMapOfArgs.Find ("xnamecolor", aValues))
4369   {
4370     if (!GetColor (aValues->Value(1), aColor))
4371     {
4372       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4373       return 1;
4374     }
4375     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4376   }
4377   if (aMapOfArgs.Find ("ynamecolor", aValues))
4378   {
4379     if (!GetColor (aValues->Value(1), aColor))
4380     {
4381       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4382       return 1;
4383     }
4384     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4385   }
4386   if (aMapOfArgs.Find ("znamecolor", aValues))
4387   {
4388     if (!GetColor (aValues->Value(1), aColor))
4389     {
4390       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4391       return 1;
4392     }
4393     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4394   }
4395   if (aMapOfArgs.Find ("xcolor", aValues))
4396   {
4397     if (!GetColor (aValues->Value(1), aColor))
4398     {
4399       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
4400       return 1;
4401     }
4402     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4403   }
4404   if (aMapOfArgs.Find ("ycolor", aValues))
4405   {
4406     if (!GetColor (aValues->Value(1), aColor))
4407     {
4408       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
4409       return 1;
4410     }
4411     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4412   }
4413   if (aMapOfArgs.Find ("zcolor", aValues))
4414   {
4415     if (!GetColor (aValues->Value(1), aColor))
4416     {
4417       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
4418       return 1;
4419     }
4420     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4421   }
4422
4423   // TICKMARKS
4424   if (aMapOfArgs.Find ("xticks", aValues))
4425   {
4426     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4427   }
4428   if (aMapOfArgs.Find ("yticks", aValues))
4429   {
4430     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4431   }
4432   if (aMapOfArgs.Find ("zticks", aValues))
4433   {
4434     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
4435   }
4436   if (aMapOfArgs.Find ("xticklength", aValues))
4437   {
4438     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4439   }
4440   if (aMapOfArgs.Find ("yticklength", aValues))
4441   {
4442     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4443   }
4444   if (aMapOfArgs.Find ("zticklength", aValues))
4445   {
4446     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
4447   }
4448   if (aMapOfArgs.Find ("xdrawticks", aValues))
4449   {
4450     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4451   }
4452   if (aMapOfArgs.Find ("ydrawticks", aValues))
4453   {
4454     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4455   }
4456   if (aMapOfArgs.Find ("zdrawticks", aValues))
4457   {
4458     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
4459   }
4460
4461   // VALUES
4462   if (aMapOfArgs.Find ("xdrawvalues", aValues))
4463   {
4464     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4465   }
4466   if (aMapOfArgs.Find ("ydrawvalues", aValues))
4467   {
4468     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4469   }
4470   if (aMapOfArgs.Find ("zdrawvalues", aValues))
4471   {
4472     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
4473   }
4474   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4475   {
4476     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4477   }
4478   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4479   {
4480     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4481   }
4482   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4483   {
4484     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4485   }
4486
4487   // ARROWS
4488   if (aMapOfArgs.Find ("arrowlength", aValues))
4489   {
4490     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
4491   }
4492
4493   // FONTS
4494   if (aMapOfArgs.Find ("namefont", aValues))
4495   {
4496     aTrihedronData.SetNamesFont (aValues->Value(1));
4497   }
4498   if (aMapOfArgs.Find ("valuesfont", aValues))
4499   {
4500     aTrihedronData.SetValuesFont (aValues->Value(1));
4501   }
4502
4503   if (aMapOfArgs.Find ("drawgrid", aValues))
4504   {
4505     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4506   }
4507   if (aMapOfArgs.Find ("drawaxes", aValues))
4508   {
4509     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4510   }
4511
4512   // The final step: display of erase trihedron
4513   if (toDisplay)
4514   {
4515     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
4516   }
4517   else
4518   {
4519     ViewerTest::CurrentView()->GraduatedTrihedronErase();
4520   }
4521
4522   ViewerTest::GetAISContext()->UpdateCurrentViewer();
4523   ViewerTest::CurrentView()->Redraw();
4524
4525   return 0;
4526 }
4527
4528 //==============================================================================
4529 //function : VTile
4530 //purpose  :
4531 //==============================================================================
4532 static int VTile (Draw_Interpretor& theDI,
4533                   Standard_Integer  theArgNb,
4534                   const char**      theArgVec)
4535 {
4536   Handle(V3d_View) aView = ViewerTest::CurrentView();
4537   if (aView.IsNull())
4538   {
4539     std::cerr << "Error: no active viewer.\n";
4540     return 1;
4541   }
4542
4543   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4544   if (theArgNb < 2)
4545   {
4546     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4547           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
4548           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
4549     return 0;
4550   }
4551
4552   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4553   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4554   {
4555     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4556     anArg.LowerCase();
4557     if (anArg == "-lowerleft"
4558      || anArg == "-upperleft")
4559     {
4560       if (anArgIter + 3 < theArgNb)
4561       {
4562         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4563         return 1;
4564       }
4565       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4566       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4567       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4568     }
4569     else if (anArg == "-total"
4570           || anArg == "-totalsize"
4571           || anArg == "-viewsize")
4572     {
4573       if (anArgIter + 3 < theArgNb)
4574       {
4575         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4576         return 1;
4577       }
4578       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4579       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4580       if (aTile.TotalSize.x() < 1
4581        || aTile.TotalSize.y() < 1)
4582       {
4583         std::cerr << "Error: total size is incorrect.\n";
4584         return 1;
4585       }
4586     }
4587     else if (anArg == "-tilesize")
4588     {
4589       if (anArgIter + 3 < theArgNb)
4590       {
4591         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
4592         return 1;
4593       }
4594
4595       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4596       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4597       if (aTile.TileSize.x() < 1
4598        || aTile.TileSize.y() < 1)
4599       {
4600         std::cerr << "Error: tile size is incorrect.\n";
4601         return 1;
4602       }
4603     }
4604     else if (anArg == "-unset")
4605     {
4606       aView->Camera()->SetTile (Graphic3d_CameraTile());
4607       aView->Redraw();
4608       return 0;
4609     }
4610   }
4611
4612   if (aTile.TileSize.x() < 1
4613    || aTile.TileSize.y() < 1)
4614   {
4615     std::cerr << "Error: tile size is undefined.\n";
4616     return 1;
4617   }
4618   else if (aTile.TotalSize.x() < 1
4619         || aTile.TotalSize.y() < 1)
4620   {
4621     std::cerr << "Error: total size is undefined.\n";
4622     return 1;
4623   }
4624
4625   aView->Camera()->SetTile (aTile);
4626   aView->Redraw();
4627   return 0;
4628 }
4629
4630 //! Format ZLayer ID.
4631 inline const char* formZLayerId (const Standard_Integer theLayerId)
4632 {
4633   switch (theLayerId)
4634   {
4635     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4636     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4637     case Graphic3d_ZLayerId_Top:     return "[TOP]";
4638     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4639     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
4640     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
4641   }
4642   return "";
4643 }
4644
4645 //! Print the ZLayer information.
4646 inline void printZLayerInfo (Draw_Interpretor& theDI,
4647                              const Graphic3d_ZLayerSettings& theLayer)
4648 {
4649   if (!theLayer.Name().IsEmpty())
4650   {
4651     theDI << "  Name: " << theLayer.Name() << "\n";
4652   }
4653   if (theLayer.IsImmediate())
4654   {
4655     theDI << "  Immediate: TRUE\n";
4656   }
4657   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4658   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
4659   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
4660   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4661   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4662   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4663   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4664   {
4665     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4666   }
4667 }
4668
4669 //==============================================================================
4670 //function : VZLayer
4671 //purpose  : Test z layer operations for v3d viewer
4672 //==============================================================================
4673 static int VZLayer (Draw_Interpretor& theDI,
4674                     Standard_Integer  theArgNb,
4675                     const char**      theArgVec)
4676 {
4677   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
4678   if (aContextAIS.IsNull())
4679   {
4680     std::cout << "No active viewer!\n";
4681     return 1;
4682   }
4683
4684   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
4685   if (theArgNb < 2)
4686   {
4687     TColStd_SequenceOfInteger aLayers;
4688     aViewer->GetAllZLayers (aLayers);
4689     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4690     {
4691       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4692       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4693       printZLayerInfo (theDI, aSettings);
4694     }
4695     return 1;
4696   }
4697
4698   Standard_Integer anArgIter = 1;
4699   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4700   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4701   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
4702   {
4703     ++anArgIter;
4704   }
4705
4706   TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4707   if (aFirstArg.IsIntegerValue())
4708   {
4709     ++anArgIter;
4710     aLayerId = aFirstArg.IntegerValue();
4711   }
4712   else
4713   {
4714     aFirstArg.LowerCase();
4715     if (aFirstArg == "default"
4716      || aFirstArg == "def")
4717     {
4718       aLayerId = Graphic3d_ZLayerId_Default;
4719       ++anArgIter;
4720     }
4721     else if (aFirstArg == "top")
4722     {
4723       aLayerId = Graphic3d_ZLayerId_Top;
4724       ++anArgIter;
4725     }
4726     else if (aFirstArg == "topmost")
4727     {
4728       aLayerId = Graphic3d_ZLayerId_Topmost;
4729       ++anArgIter;
4730     }
4731     else if (aFirstArg == "overlay"
4732           || aFirstArg == "toposd")
4733     {
4734       aLayerId = Graphic3d_ZLayerId_TopOSD;
4735       ++anArgIter;
4736     }
4737     else if (aFirstArg == "underlay"
4738           || aFirstArg == "botosd")
4739     {
4740       aLayerId = Graphic3d_ZLayerId_BotOSD;
4741       ++anArgIter;
4742     }
4743     else
4744     {
4745       TColStd_SequenceOfInteger aLayers;
4746       aViewer->GetAllZLayers (aLayers);
4747       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4748       {
4749         Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4750         if (TCollection_AsciiString::IsSameString (aSettings.Name(), aFirstArg, Standard_False))
4751         {
4752           aLayerId = aLayeriter.Value();
4753           ++anArgIter;
4754           break;
4755         }
4756       }
4757     }
4758   }
4759
4760   for (; anArgIter < theArgNb; ++anArgIter)
4761   {
4762     // perform operation
4763     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4764     anArg.LowerCase();
4765     if (anUpdateTool.parseRedrawMode (anArg))
4766     {
4767       //
4768     }
4769     else if (anArg == "-add"
4770           || anArg == "add")
4771     {
4772       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4773       if (!aViewer->AddZLayer (aLayerId))
4774       {
4775         std::cout << "Error: can not add a new z layer!\n";
4776         return 0;
4777       }
4778
4779       theDI << aLayerId;
4780     }
4781     else if (anArg == "-del"
4782           || anArg == "-delete"
4783           || anArg == "del")
4784     {
4785       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4786       {
4787         if (++anArgIter >= theArgNb)
4788         {
4789           std::cout << "Syntax error: id of z layer to remove is missing\n";
4790           return 1;
4791         }
4792
4793         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4794       }
4795
4796       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4797        || aLayerId == Graphic3d_ZLayerId_Default
4798        || aLayerId == Graphic3d_ZLayerId_Top
4799        || aLayerId == Graphic3d_ZLayerId_Topmost
4800        || aLayerId == Graphic3d_ZLayerId_TopOSD
4801        || aLayerId == Graphic3d_ZLayerId_BotOSD)
4802       {
4803         std::cout << "Syntax error: standard Z layer can not be removed\n";
4804         return 1;
4805       }
4806
4807       // move all object displayed in removing layer to default layer
4808       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4809            anObjIter.More(); anObjIter.Next())
4810       {
4811         Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anObjIter.Key1());
4812         if (aPrs.IsNull()
4813          || aPrs->ZLayer() != aLayerId)
4814         {
4815           continue;
4816         }
4817         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4818       }
4819
4820       if (!aViewer->RemoveZLayer (aLayerId))
4821       {
4822         std::cout << "Z layer can not be removed!\n";
4823       }
4824       else
4825       {
4826         theDI << aLayerId << " ";
4827       }
4828     }
4829     else if (anArg == "-get"
4830           || anArg == "get")
4831     {
4832       TColStd_SequenceOfInteger aLayers;
4833       aViewer->GetAllZLayers (aLayers);
4834       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4835       {
4836         theDI << aLayeriter.Value() << " ";
4837       }
4838
4839       theDI << "\n";
4840     }
4841     else if (anArg == "-name")
4842     {
4843       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4844       {
4845         std::cout << "Syntax error: id of Z layer is missing\n";
4846         return 1;
4847       }
4848
4849       if (++anArgIter >= theArgNb)
4850       {
4851         std::cout << "Syntax error: name is missing\n";
4852         return 1;
4853       }
4854
4855       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4856       aSettings.SetName (theArgVec[anArgIter]);
4857       aViewer->SetZLayerSettings (aLayerId, aSettings);
4858     }
4859     else if (anArg == "-origin")
4860     {
4861       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4862       {
4863         std::cout << "Syntax error: id of Z layer is missing\n";
4864         return 1;
4865       }
4866
4867       if (anArgIter + 2 >= theArgNb)
4868       {
4869         std::cout << "Syntax error: origin coordinates are missing\n";
4870         return 1;
4871       }
4872
4873       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4874       gp_XYZ anOrigin;
4875       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4876       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4877       anOrigin.SetZ (0.0);
4878       if (anArgIter + 3 < theArgNb)
4879       {
4880         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4881         anArgIter += 3;
4882       }
4883       else
4884       {
4885         anArgIter += 2;
4886       }
4887       aSettings.SetOrigin (anOrigin);
4888       aViewer->SetZLayerSettings (aLayerId, aSettings);
4889     }
4890     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4891           && anArgIter + 1 < theArgNb
4892           && (anArg == "-cullingdistance"
4893            || anArg == "-cullingdist"
4894            || anArg == "-culldistance"
4895            || anArg == "-culldist"
4896            || anArg == "-distcull"
4897            || anArg == "-distculling"
4898            || anArg == "-distanceculling"))
4899     {
4900       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4901       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
4902       aSettings.SetCullingDistance (aDist);
4903       aViewer->SetZLayerSettings (aLayerId, aSettings);
4904     }
4905     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4906           && anArgIter + 1 < theArgNb
4907           && (anArg == "-cullingsize"
4908            || anArg == "-cullsize"
4909            || anArg == "-sizecull"
4910            || anArg == "-sizeculling"))
4911     {
4912       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4913       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
4914       aSettings.SetCullingSize (aSize);
4915       aViewer->SetZLayerSettings (aLayerId, aSettings);
4916     }
4917     else if (anArg == "-settings"
4918           || anArg == "settings")
4919     {
4920       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4921       {
4922         if (++anArgIter >= theArgNb)
4923         {
4924           std::cout << "Syntax error: id of Z layer is missing\n";
4925           return 1;
4926         }
4927
4928         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4929       }
4930
4931       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4932       printZLayerInfo (theDI, aSettings);
4933     }
4934     else if (anArg == "-enable"
4935           || anArg == "enable"
4936           || anArg == "-disable"
4937           || anArg == "disable")
4938     {
4939       const Standard_Boolean toEnable = anArg == "-enable"
4940                                      || anArg == "enable";
4941       if (++anArgIter >= theArgNb)
4942       {
4943         std::cout << "Syntax error: option name is missing\n";
4944         return 1;
4945       }
4946
4947       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4948       aSubOp.LowerCase();
4949       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4950       {
4951         if (++anArgIter >= theArgNb)
4952         {
4953           std::cout << "Syntax error: id of Z layer is missing\n";
4954           return 1;
4955         }
4956
4957         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4958       }
4959
4960       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4961       if (aSubOp == "depthtest"
4962        || aSubOp == "test")
4963       {
4964         aSettings.SetEnableDepthTest (toEnable);
4965       }
4966       else if (aSubOp == "depthwrite"
4967             || aSubOp == "write")
4968       {
4969         aSettings.SetEnableDepthWrite (toEnable);
4970       }
4971       else if (aSubOp == "depthclear"
4972             || aSubOp == "clear")
4973       {
4974         aSettings.SetClearDepth (toEnable);
4975       }
4976       else if (aSubOp == "depthoffset"
4977             || aSubOp == "offset")
4978       {
4979         Graphic3d_PolygonOffset aParams;
4980         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4981         if (toEnable)
4982         {
4983           if (anArgIter + 2 >= theArgNb)
4984           {
4985             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
4986             return 1;
4987           }
4988
4989           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4990           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4991         }
4992         aSettings.SetPolygonOffset (aParams);
4993       }
4994       else if (aSubOp == "positiveoffset"
4995             || aSubOp == "poffset")
4996       {
4997         if (toEnable)
4998         {
4999           aSettings.SetDepthOffsetPositive();
5000         }
5001         else
5002         {
5003           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5004         }
5005       }
5006       else if (aSubOp == "negativeoffset"
5007             || aSubOp == "noffset")
5008       {
5009         if (toEnable)
5010         {
5011           aSettings.SetDepthOffsetNegative();
5012         }
5013         else
5014         {
5015           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5016         }
5017       }
5018       else if (aSubOp == "textureenv")
5019       {
5020         aSettings.SetEnvironmentTexture (toEnable);
5021       }
5022
5023       aViewer->SetZLayerSettings (aLayerId, aSettings);
5024     }
5025     else
5026     {
5027       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5028       return 1;
5029     }
5030   }
5031
5032   return 0;
5033 }
5034
5035 // The interactive presentation of 2d layer item
5036 // for "vlayerline" command it provides a presentation of
5037 // line with user-defined linewidth, linetype and transparency.
5038 class V3d_LineItem : public AIS_InteractiveObject
5039 {
5040 public:
5041   // CASCADE RTTI
5042   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5043
5044   // constructor
5045   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5046                                Standard_Real X2, Standard_Real Y2,
5047                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5048                                Standard_Real theWidth    = 0.5,
5049                                Standard_Real theTransp   = 1.0);
5050
5051   private:
5052
5053   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5054                 const Handle(Prs3d_Presentation)& thePresentation,
5055                 const Standard_Integer theMode) Standard_OVERRIDE;
5056
5057   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5058                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5059   {}
5060
5061 private:
5062
5063   Standard_Real       myX1, myY1, myX2, myY2;
5064   Aspect_TypeOfLine   myType;
5065   Standard_Real       myWidth;
5066 };
5067
5068 // default constructor for line item
5069 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5070                            Standard_Real X2, Standard_Real Y2,
5071                            Aspect_TypeOfLine theType,
5072                            Standard_Real theWidth,
5073                            Standard_Real theTransp) :
5074   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5075   myType(theType), myWidth(theWidth)
5076 {
5077   SetTransparency (1-theTransp);
5078 }
5079
5080 // render line
5081 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5082                             const Handle(Prs3d_Presentation)& thePresentation,
5083                             const Standard_Integer /*theMode*/)
5084 {
5085   thePresentation->Clear();
5086   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5087   Standard_Integer aWidth, aHeight;
5088   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5089   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5090   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5091   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5092   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5093   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5094   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5095   aGroup->AddPrimitiveArray (aPrim);
5096 }
5097
5098 //=============================================================================
5099 //function : VLayerLine
5100 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5101 //         : linewidth, transparency coefficient
5102 //============================================================================
5103 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5104 {
5105   // get the active view
5106   Handle(V3d_View) aView = ViewerTest::CurrentView();
5107   if (aView.IsNull())
5108   {
5109     di << "Call vinit before!\n";
5110     return 1;
5111   }
5112   else if (argc < 5)
5113   {
5114     di << "Use: " << argv[0];
5115     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5116     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5117     di << "              0 - solid  \n";
5118     di << "              1 - dashed \n";
5119     di << "              2 - dot    \n";
5120     di << "              3 - dashdot\n";
5121     di << " transparency : { 0.0 - 1.0 } \n";
5122     di << "                  0.0 - transparent\n";
5123     di << "                  1.0 - visible    \n";
5124     return 1;
5125   }
5126
5127   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5128   // get the input params
5129   Standard_Real X1 = Draw::Atof(argv[1]);
5130   Standard_Real Y1 = Draw::Atof(argv[2]);
5131   Standard_Real X2 = Draw::Atof(argv[3]);
5132   Standard_Real Y2 = Draw::Atof(argv[4]);
5133
5134   Standard_Real aWidth = 0.5;
5135   Standard_Real aTransparency = 1.0;
5136
5137   // has width
5138   if (argc > 5)
5139     aWidth = Draw::Atof(argv[5]);
5140
5141   // select appropriate line type
5142   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5143   if (argc > 6
5144   && !ViewerTest::ParseLineType (argv[6], aLineType))
5145   {
5146     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5147     return 1;
5148   }
5149
5150   // has transparency
5151   if (argc > 7)
5152   {
5153     aTransparency = Draw::Atof(argv[7]);
5154     if (aTransparency < 0 || aTransparency > 1.0)
5155       aTransparency = 1.0;
5156   }
5157
5158   static Handle (V3d_LineItem) aLine;
5159   if (!aLine.IsNull())
5160   {
5161     aContext->Erase (aLine, Standard_False);
5162   }
5163   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5164                             aLineType, aWidth,
5165                             aTransparency);
5166
5167   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5168   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5169   aLine->SetToUpdate();
5170   aContext->Display (aLine, Standard_True);
5171
5172   return 0;
5173 }
5174
5175
5176 //==============================================================================
5177 //function : VGrid
5178 //purpose  :
5179 //==============================================================================
5180
5181 static int VGrid (Draw_Interpretor& /*theDI*/,
5182                   Standard_Integer  theArgNb,
5183                   const char**      theArgVec)
5184 {
5185   // get the active view
5186   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5187   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5188   if (aView.IsNull() || aViewer.IsNull())
5189   {
5190     std::cerr << "No active view. Please call vinit.\n";
5191     return 1;
5192   }
5193
5194   Aspect_GridType     aType = aViewer->GridType();
5195   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5196   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5197   Standard_Integer anIter = 1;
5198   for (; anIter < theArgNb; ++anIter)
5199   {
5200     const char* aValue = theArgVec[anIter];
5201     if (anUpdateTool.parseRedrawMode (aValue))
5202     {
5203       continue;
5204     }
5205     else if (*aValue == 'r')
5206     {
5207       aType = Aspect_GT_Rectangular;
5208     }
5209     else if (*aValue == 'c')
5210     {
5211       aType = Aspect_GT_Circular;
5212     }
5213     else if (*aValue == 'l')
5214     {
5215       aMode = Aspect_GDM_Lines;
5216     }
5217     else if (*aValue == 'p')
5218     {
5219       aMode = Aspect_GDM_Points;
5220     }
5221     else if (strcmp (aValue, "off" ) == 0)
5222     {
5223       aViewer->DeactivateGrid();
5224       return 0;
5225     }
5226     else
5227     {
5228       break;
5229     }
5230   }
5231
5232   Standard_Integer aTail = (theArgNb - anIter);
5233   if (aTail == 0)
5234   {
5235     aViewer->ActivateGrid (aType, aMode);
5236     return 0;
5237   }
5238   else if (aTail != 2 && aTail != 5)
5239   {
5240     std::cerr << "Incorrect arguments number! Usage:\n"
5241               << "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]\n";
5242     return 1;
5243   }
5244
5245   Standard_Real anOriginX, anOriginY, aRotAngle;
5246   if (aType == Aspect_GT_Rectangular)
5247   {
5248     Standard_Real aRStepX, aRStepY;
5249     aViewer->RectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5250
5251     anOriginX = Draw::Atof (theArgVec[anIter++]);
5252     anOriginY = Draw::Atof (theArgVec[anIter++]);
5253     if (aTail == 5)
5254     {
5255       aRStepX   = Draw::Atof (theArgVec[anIter++]);
5256       aRStepY   = Draw::Atof (theArgVec[anIter++]);
5257       aRotAngle = Draw::Atof (theArgVec[anIter++]);
5258     }
5259     aViewer->SetRectangularGridValues (anOriginX, anOriginY, aRStepX, aRStepY, aRotAngle);
5260     aViewer->ActivateGrid (aType, aMode);
5261   }
5262   else if (aType == Aspect_GT_Circular)
5263   {
5264     Standard_Real aRadiusStep;
5265     Standard_Integer aDivisionNumber;
5266     aViewer->CircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5267
5268     anOriginX = Draw::Atof (theArgVec[anIter++]);
5269     anOriginY = Draw::Atof (theArgVec[anIter++]);
5270     if (aTail == 5)
5271     {
5272       aRadiusStep     = Draw::Atof (theArgVec[anIter++]);
5273       aDivisionNumber = Draw::Atoi (theArgVec[anIter++]);
5274       aRotAngle       = Draw::Atof (theArgVec[anIter++]);
5275     }
5276
5277     aViewer->SetCircularGridValues (anOriginX, anOriginY, aRadiusStep, aDivisionNumber, aRotAngle);
5278     aViewer->ActivateGrid (aType, aMode);
5279   }
5280
5281   return 0;
5282 }
5283
5284 //==============================================================================
5285 //function : VPriviledgedPlane
5286 //purpose  :
5287 //==============================================================================
5288
5289 static int VPriviledgedPlane (Draw_Interpretor& theDI,
5290                               Standard_Integer  theArgNb,
5291                               const char**      theArgVec)
5292 {
5293   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5294   {
5295     std::cerr << "Error: wrong number of arguments! See usage:\n";
5296     theDI.PrintHelp (theArgVec[0]);
5297     return 1;
5298   }
5299
5300   // get the active viewer
5301   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5302   if (aViewer.IsNull())
5303   {
5304     std::cerr << "Error: no active viewer. Please call vinit.\n";
5305     return 1;
5306   }
5307
5308   if (theArgNb == 1)
5309   {
5310     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5311     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5312     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5313     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5314     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5315           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5316           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5317     return 0;
5318   }
5319
5320   Standard_Integer anArgIdx = 1;
5321   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5322   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5323   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5324   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
5325   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
5326   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
5327
5328   gp_Ax3 aPriviledgedPlane;
5329   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5330   gp_Dir aNorm (aNormX, aNormY, aNormZ);
5331   if (theArgNb > 7)
5332   {
5333     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5334     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5335     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5336     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5337     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5338   }
5339   else
5340   {
5341     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5342   }
5343
5344   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5345
5346   return 0;
5347 }
5348
5349 //==============================================================================
5350 //function : VConvert
5351 //purpose  :
5352 //==============================================================================
5353
5354 static int VConvert (Draw_Interpretor& theDI,
5355                      Standard_Integer  theArgNb,
5356                      const char**      theArgVec)
5357 {
5358   // get the active view
5359   Handle(V3d_View) aView = ViewerTest::CurrentView();
5360   if (aView.IsNull())
5361   {
5362     std::cerr << "Error: no active view. Please call vinit.\n";
5363     return 1;
5364   }
5365
5366   enum { Model, Ray, View, Window, Grid } aMode = Model;
5367
5368   // access coordinate arguments
5369   TColStd_SequenceOfReal aCoord;
5370   Standard_Integer anArgIdx = 1;
5371   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5372   {
5373     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5374     if (!anArg.IsRealValue())
5375     {
5376       break;
5377     }
5378     aCoord.Append (anArg.RealValue());
5379   }
5380
5381   // non-numeric argument too early
5382   if (aCoord.IsEmpty())
5383   {
5384     std::cerr << "Error: wrong number of arguments! See usage:\n";
5385     theDI.PrintHelp (theArgVec[0]);
5386     return 1;
5387   }
5388
5389   // collect all other arguments and options
5390   for (; anArgIdx < theArgNb; ++anArgIdx)
5391   {
5392     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5393     anArg.LowerCase();
5394     if      (anArg == "window") aMode = Window;
5395     else if (anArg == "view")   aMode = View;
5396     else if (anArg == "grid")   aMode = Grid;
5397     else if (anArg == "ray")    aMode = Ray;
5398     else
5399     {
5400       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
5401       theDI.PrintHelp (theArgVec[0]);
5402       return 1;
5403     }
5404   }
5405
5406   // complete input checks
5407   if ((aCoord.Length() == 1 && theArgNb > 3) ||
5408       (aCoord.Length() == 2 && theArgNb > 4) ||
5409       (aCoord.Length() == 3 && theArgNb > 5))
5410   {
5411     std::cerr << "Error: wrong number of arguments! See usage:\n";
5412     theDI.PrintHelp (theArgVec[0]);
5413     return 1;
5414   }
5415
5416   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5417   Standard_Integer aXYp[2] = {0, 0};
5418
5419   // convert one-dimensional coordinate
5420   if (aCoord.Length() == 1)
5421   {
5422     switch (aMode)
5423     {
5424       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5425       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
5426       default:
5427         std::cerr << "Error: wrong arguments! See usage:\n";
5428         theDI.PrintHelp (theArgVec[0]);
5429         return 1;
5430     }
5431   }
5432
5433   // convert 2D coordinates from projection or view reference space
5434   if (aCoord.Length() == 2)
5435   {
5436     switch (aMode)
5437     {
5438       case Model :
5439         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5440         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5441         return 0;
5442
5443       case View :
5444         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5445         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5446         return 0;
5447
5448       case Window :
5449         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
5450         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5451         return 0;
5452
5453       case Grid :
5454         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5455         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5456         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5457         return 0;
5458
5459       case Ray :
5460         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5461                                 (Standard_Integer) aCoord (2),
5462                                 aXYZ[0], aXYZ[1], aXYZ[2],
5463                                 aXYZ[3], aXYZ[4], aXYZ[5]);
5464         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5465         return 0;
5466
5467       default:
5468         std::cerr << "Error: wrong arguments! See usage:\n";
5469         theDI.PrintHelp (theArgVec[0]);
5470         return 1;
5471     }
5472   }
5473
5474   // convert 3D coordinates from view reference space
5475   else if (aCoord.Length() == 3)
5476   {
5477     switch (aMode)
5478     {
5479       case Window :
5480         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5481         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5482         return 0;
5483
5484       case Grid :
5485         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5486         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5487         return 0;
5488
5489       default:
5490         std::cerr << "Error: wrong arguments! See usage:\n";
5491         theDI.PrintHelp (theArgVec[0]);
5492         return 1;
5493     }
5494   }
5495
5496   return 0;
5497 }
5498
5499 //==============================================================================
5500 //function : VFps
5501 //purpose  :
5502 //==============================================================================
5503
5504 static int VFps (Draw_Interpretor& theDI,
5505                  Standard_Integer  theArgNb,
5506                  const char**      theArgVec)
5507 {
5508   // get the active view
5509   Handle(V3d_View) aView = ViewerTest::CurrentView();
5510   if (aView.IsNull())
5511   {
5512     std::cerr << "No active view. Please call vinit.\n";
5513     return 1;
5514   }
5515
5516   Standard_Integer aFramesNb = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 100;
5517   if (aFramesNb <= 0)
5518   {
5519     std::cerr << "Incorrect arguments!\n";
5520     return 1;
5521   }
5522
5523   // the time is meaningless for first call
5524   // due to async OpenGl rendering
5525   aView->Redraw();
5526
5527   // redraw view in loop to estimate average values
5528   OSD_Timer aTimer;
5529   aTimer.Start();
5530   for (Standard_Integer anInter = 0; anInter < aFramesNb; ++anInter)
5531   {
5532     aView->Redraw();
5533   }
5534   aTimer.Stop();
5535   Standard_Real aCpu;
5536   const Standard_Real aTime = aTimer.ElapsedTime();
5537   aTimer.OSD_Chronometer::Show (aCpu);
5538
5539   const Standard_Real aFpsAver = Standard_Real(aFramesNb) / aTime;
5540   const Standard_Real aCpuAver = aCpu / Standard_Real(aFramesNb);
5541
5542   // return statistics
5543   theDI << "FPS: " << aFpsAver << "\n"
5544         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5545
5546   // compute additional statistics in ray-tracing mode
5547   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
5548
5549   if (aParams.Method == Graphic3d_RM_RAYTRACING)
5550   {
5551     Standard_Integer aSizeX;
5552     Standard_Integer aSizeY;
5553
5554     aView->Window()->Size (aSizeX, aSizeY);
5555
5556     // 1 shadow ray and 1 secondary ray pew each bounce
5557     const Standard_Real aMRays = aSizeX * aSizeY * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
5558
5559     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5560   }
5561
5562   return 0;
5563 }
5564
5565 //==============================================================================
5566 //function : VGlDebug
5567 //purpose  :
5568 //==============================================================================
5569
5570 static int VGlDebug (Draw_Interpretor& theDI,
5571                      Standard_Integer  theArgNb,
5572                      const char**      theArgVec)
5573 {
5574   Handle(OpenGl_GraphicDriver) aDriver;
5575   Handle(V3d_View) aView = ViewerTest::CurrentView();
5576   if (!aView.IsNull())
5577   {
5578     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
5579   }
5580   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
5581   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
5582
5583   if (theArgNb < 2)
5584   {
5585     TCollection_AsciiString aDebActive, aSyncActive;
5586     if (aCaps == NULL)
5587     {
5588       aCaps = aDefCaps;
5589     }
5590     else
5591     {
5592       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
5593                                                                   "GL_ARB_debug_output");
5594       aDebActive = isActive ? " (active)" : " (inactive)";
5595       if (isActive)
5596       {
5597         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
5598         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
5599       }
5600     }
5601
5602     theDI << "debug:   " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
5603           << "sync:    " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
5604           << "glslWarn:" << (aCaps->glslWarnings      ? "1" : "0") << "\n"
5605           << "extraMsg:" << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
5606     return 0;
5607   }
5608
5609   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5610   {
5611     Standard_CString        anArg     = theArgVec[anArgIter];
5612     TCollection_AsciiString anArgCase (anArg);
5613     anArgCase.LowerCase();
5614     Standard_Boolean toEnableDebug = Standard_True;
5615     if (anArgCase == "-glsl"
5616      || anArgCase == "-glslwarn"
5617      || anArgCase == "-glslwarns"
5618      || anArgCase == "-glslwarnings")
5619     {
5620       Standard_Boolean toShowWarns = Standard_True;
5621       if (++anArgIter < theArgNb
5622       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
5623       {
5624         --anArgIter;
5625       }
5626       aDefCaps->glslWarnings = toShowWarns;
5627       if (aCaps != NULL)
5628       {
5629         aCaps->glslWarnings = toShowWarns;
5630       }
5631     }
5632     else if (anArgCase == "-extra"
5633           || anArgCase == "-extramsg"
5634           || anArgCase == "-extramessages")
5635     {
5636       Standard_Boolean toShow = Standard_True;
5637       if (++anArgIter < theArgNb
5638       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
5639       {
5640         --anArgIter;
5641       }
5642       aDefCaps->suppressExtraMsg = !toShow;
5643       if (aCaps != NULL)
5644       {
5645         aCaps->suppressExtraMsg = !toShow;
5646       }
5647     }
5648     else if (anArgCase == "-noextra"
5649           || anArgCase == "-noextramsg"
5650           || anArgCase == "-noextramessages")
5651     {
5652       Standard_Boolean toSuppress = Standard_True;
5653       if (++anArgIter < theArgNb
5654       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
5655       {
5656         --anArgIter;
5657       }
5658       aDefCaps->suppressExtraMsg = toSuppress;
5659       if (aCaps != NULL)
5660       {
5661         aCaps->suppressExtraMsg = toSuppress;
5662       }
5663     }
5664     else if (anArgCase == "-sync")
5665     {
5666       Standard_Boolean toSync = Standard_True;
5667       if (++anArgIter < theArgNb
5668       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
5669       {
5670         --anArgIter;
5671       }
5672       aDefCaps->contextSyncDebug = toSync;
5673       if (toSync)
5674       {
5675         aDefCaps->contextDebug = Standard_True;
5676       }
5677     }
5678     else if (anArgCase == "-debug")
5679     {
5680       if (++anArgIter < theArgNb
5681       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
5682       {
5683         --anArgIter;
5684       }
5685       aDefCaps->contextDebug = toEnableDebug;
5686     }
5687     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
5688           && (anArgIter + 1 == theArgNb))
5689     {
5690       // simple alias to turn on almost everything
5691       aDefCaps->contextDebug     = toEnableDebug;
5692       aDefCaps->contextSyncDebug = toEnableDebug;
5693       aDefCaps->glslWarnings     = toEnableDebug;
5694     }
5695     else
5696     {
5697       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
5698       return 1;
5699     }
5700   }
5701
5702   return 0;
5703 }
5704
5705 //==============================================================================
5706 //function : VVbo
5707 //purpose  :
5708 //==============================================================================
5709
5710 static int VVbo (Draw_Interpretor& theDI,
5711                  Standard_Integer  theArgNb,
5712                  const char**      theArgVec)
5713 {
5714   const Standard_Boolean toSet    = (theArgNb > 1);
5715   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
5716   if (toSet)
5717   {
5718     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
5719   }
5720
5721   // get the context
5722   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5723   if (aContextAIS.IsNull())
5724   {
5725     if (!toSet)
5726     {
5727       std::cerr << "No active view!\n";
5728     }
5729     return 1;
5730   }
5731   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
5732   if (!aDriver.IsNull())
5733   {
5734     if (!toSet)
5735     {
5736       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
5737     }
5738     else
5739     {
5740       aDriver->ChangeOptions().vboDisable = toUseVbo;
5741     }
5742   }
5743
5744   return 0;
5745 }
5746
5747 //==============================================================================
5748 //function : VCaps
5749 //purpose  :
5750 //==============================================================================
5751
5752 static int VCaps (Draw_Interpretor& theDI,
5753                   Standard_Integer  theArgNb,
5754                   const char**      theArgVec)
5755 {
5756   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
5757   Handle(OpenGl_GraphicDriver)   aDriver;
5758   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5759   if (!aContext.IsNull())
5760   {
5761     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
5762     aCaps   = &aDriver->ChangeOptions();
5763   }
5764
5765   if (theArgNb < 2)
5766   {
5767     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
5768     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
5769     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
5770     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
5771     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
5772     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
5773     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
5774     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
5775     return 0;
5776   }
5777
5778   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
5779   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5780   {
5781     Standard_CString        anArg     = theArgVec[anArgIter];
5782     TCollection_AsciiString anArgCase (anArg);
5783     anArgCase.LowerCase();
5784     if (anUpdateTool.parseRedrawMode (anArg))
5785     {
5786       continue;
5787     }
5788     else if (anArgCase == "-vsync"
5789           || anArgCase == "-swapinterval")
5790     {
5791       Standard_Boolean toEnable = Standard_True;
5792       if (++anArgIter < theArgNb
5793       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5794       {
5795         --anArgIter;
5796       }
5797       aCaps->swapInterval = toEnable;
5798     }
5799     else if (anArgCase == "-ffp")
5800     {
5801       Standard_Boolean toEnable = Standard_True;
5802       if (++anArgIter < theArgNb
5803       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5804       {
5805         --anArgIter;
5806       }
5807       aCaps->ffpEnable = toEnable;
5808     }
5809     else if (anArgCase == "-vbo")
5810     {
5811       Standard_Boolean toEnable = Standard_True;
5812       if (++anArgIter < theArgNb
5813       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5814       {
5815         --anArgIter;
5816       }
5817       aCaps->vboDisable = !toEnable;
5818     }
5819     else if (anArgCase == "-sprite"
5820           || anArgCase == "-sprites")
5821     {
5822       Standard_Boolean toEnable = Standard_True;
5823       if (++anArgIter < theArgNb
5824       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5825       {
5826         --anArgIter;
5827       }
5828       aCaps->pntSpritesDisable = !toEnable;
5829     }
5830     else if (anArgCase == "-softmode")
5831     {
5832       Standard_Boolean toEnable = Standard_True;
5833       if (++anArgIter < theArgNb
5834       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5835       {
5836         --anArgIter;
5837       }
5838       aCaps->contextNoAccel = toEnable;
5839     }
5840     else if (anArgCase == "-winbuffer"
5841           || anArgCase == "-windowbuffer"
5842           || anArgCase == "-usewinbuffer"
5843           || anArgCase == "-usewindowbuffer"
5844           || anArgCase == "-usesystembuffer")
5845     {
5846       Standard_Boolean toEnable = Standard_True;
5847       if (++anArgIter < theArgNb
5848       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5849       {
5850         --anArgIter;
5851       }
5852       aCaps->useSystemBuffer = toEnable;
5853     }
5854     else if (anArgCase == "-accel"
5855           || anArgCase == "-acceleration")
5856     {
5857       Standard_Boolean toEnable = Standard_True;
5858       if (++anArgIter < theArgNb
5859       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5860       {
5861         --anArgIter;
5862       }
5863       aCaps->contextNoAccel = !toEnable;
5864     }
5865     else if (anArgCase == "-compat"
5866           || anArgCase == "-compatprofile"
5867           || anArgCase == "-compatible"
5868           || anArgCase == "-compatibleprofile")
5869     {
5870       Standard_Boolean toEnable = Standard_True;
5871       if (++anArgIter < theArgNb
5872       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5873       {
5874         --anArgIter;
5875       }
5876       aCaps->contextCompatible = toEnable;
5877       if (!aCaps->contextCompatible)
5878       {
5879         aCaps->ffpEnable = Standard_False;
5880       }
5881     }
5882     else if (anArgCase == "-core"
5883           || anArgCase == "-coreprofile")
5884     {
5885       Standard_Boolean toEnable = Standard_True;
5886       if (++anArgIter < theArgNb
5887       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5888       {
5889         --anArgIter;
5890       }
5891       aCaps->contextCompatible = !toEnable;
5892       if (!aCaps->contextCompatible)
5893       {
5894         aCaps->ffpEnable = Standard_False;
5895       }
5896     }
5897     else if (anArgCase == "-stereo"
5898           || anArgCase == "-quadbuffer")
5899     {
5900       Standard_Boolean toEnable = Standard_True;
5901       if (++anArgIter < theArgNb
5902       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
5903       {
5904         --anArgIter;
5905       }
5906       aCaps->contextStereo = toEnable;
5907     }
5908     else
5909     {
5910       std::cout << "Error: unknown argument '" << anArg << "'\n";
5911       return 1;
5912     }
5913   }
5914   if (aCaps != &ViewerTest_myDefaultCaps)
5915   {
5916     ViewerTest_myDefaultCaps = *aCaps;
5917   }
5918   return 0;
5919 }
5920
5921 //==============================================================================
5922 //function : VMemGpu
5923 //purpose  :
5924 //==============================================================================
5925
5926 static int VMemGpu (Draw_Interpretor& theDI,
5927                     Standard_Integer  theArgNb,
5928                     const char**      theArgVec)
5929 {
5930   // get the context
5931   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5932   if (aContextAIS.IsNull())
5933   {
5934     std::cerr << "No active view. Please call vinit.\n";
5935     return 1;
5936   }
5937
5938   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
5939   if (aDriver.IsNull())
5940   {
5941     std::cerr << "Graphic driver not available.\n";
5942     return 1;
5943   }
5944
5945   Standard_Size aFreeBytes = 0;
5946   TCollection_AsciiString anInfo;
5947   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5948   {
5949     std::cerr << "Information not available.\n";
5950     return 1;
5951   }
5952
5953   if (theArgNb > 1 && *theArgVec[1] == 'f')
5954   {
5955     theDI << Standard_Real (aFreeBytes);
5956   }
5957   else
5958   {
5959     theDI << anInfo;
5960   }
5961
5962   return 0;
5963 }
5964
5965 // ==============================================================================
5966 // function : VReadPixel
5967 // purpose  :
5968 // ==============================================================================
5969 static int VReadPixel (Draw_Interpretor& theDI,
5970                        Standard_Integer  theArgNb,
5971                        const char**      theArgVec)
5972 {
5973   // get the active view
5974   Handle(V3d_View) aView = ViewerTest::CurrentView();
5975   if (aView.IsNull())
5976   {
5977     std::cerr << "No active view. Please call vinit.\n";
5978     return 1;
5979   }
5980   else if (theArgNb < 3)
5981   {
5982     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
5983     return 1;
5984   }
5985
5986   Image_Format         aFormat     = Image_Format_RGBA;
5987   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
5988
5989   Standard_Integer aWidth, aHeight;
5990   aView->Window()->Size (aWidth, aHeight);
5991   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5992   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
5993   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5994   {
5995     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
5996     return 1;
5997   }
5998
5999   Standard_Boolean toShowName = Standard_False;
6000   Standard_Boolean toShowHls  = Standard_False;
6001   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6002   {
6003     TCollection_AsciiString aParam (theArgVec[anIter]);
6004     aParam.LowerCase();
6005     if (aParam == "rgb")
6006     {
6007       aFormat     = Image_Format_RGB;
6008       aBufferType = Graphic3d_BT_RGB;
6009     }
6010     else if (aParam == "hls")
6011     {
6012       aFormat     = Image_Format_RGB;
6013       aBufferType = Graphic3d_BT_RGB;
6014       toShowHls   = Standard_True;
6015     }
6016     else if (aParam == "rgbf")
6017     {
6018       aFormat     = Image_Format_RGBF;
6019       aBufferType = Graphic3d_BT_RGB;
6020     }
6021     else if (aParam == "rgba")
6022     {
6023       aFormat     = Image_Format_RGBA;
6024       aBufferType = Graphic3d_BT_RGBA;
6025     }
6026     else if (aParam == "rgbaf")
6027     {
6028       aFormat     = Image_Format_RGBAF;
6029       aBufferType = Graphic3d_BT_RGBA;
6030     }
6031     else if (aParam == "depth")
6032     {
6033       aFormat     = Image_Format_GrayF;
6034       aBufferType = Graphic3d_BT_Depth;
6035     }
6036     else if (aParam == "name")
6037     {
6038       toShowName = Standard_True;
6039     }
6040   }
6041
6042   Image_PixMap anImage;
6043   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6044   {
6045     std::cerr << "Image allocation failed\n";
6046     return 1;
6047   }
6048   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6049   {
6050     std::cerr << "Image dump failed\n";
6051     return 1;
6052   }
6053
6054   // redirect possible warning messages that could have been added by ToPixMap
6055   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6056   // contaminate result of the command
6057   Standard_CString aWarnLog = theDI.Result();
6058   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6059   {
6060     std::cout << aWarnLog << std::endl;
6061   }
6062   theDI.Reset();
6063
6064   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6065   if (toShowName)
6066   {
6067     if (aBufferType == Graphic3d_BT_RGBA)
6068     {
6069       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6070     }
6071     else
6072     {
6073       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6074     }
6075   }
6076   else
6077   {
6078     switch (aBufferType)
6079     {
6080       default:
6081       case Graphic3d_BT_RGB:
6082       {
6083         if (toShowHls)
6084         {
6085           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6086         }
6087         else
6088         {
6089           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6090         }
6091         break;
6092       }
6093       case Graphic3d_BT_RGBA:
6094       {
6095         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6096         break;
6097       }
6098       case Graphic3d_BT_Depth:
6099       {
6100         theDI << aColor.GetRGB().Red();
6101         break;
6102       }
6103     }
6104   }
6105
6106   return 0;
6107 }
6108
6109 //! Auxiliary presentation for an image plane.
6110 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6111 {
6112 public:
6113   //! Main constructor.
6114   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6115                        const Standard_Real theWidth,
6116                        const Standard_Real theHeight,
6117                        const TCollection_AsciiString& theLabel)
6118   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6119   {
6120     SetDisplayMode (0);
6121     SetHilightMode (1);
6122     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6123     {
6124       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6125       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6126       Graphic3d_MaterialAspect aMat;
6127       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6128       aMat.SetAmbient  (1.0);
6129       aMat.SetDiffuse  (1.0);
6130       aMat.SetSpecular (1.0);
6131       aMat.SetEmissive (1.0);
6132       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6133       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6134       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6135       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6136       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6137       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6138       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6139       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6140       aFillAspect->SetFrontMaterial (aMat);
6141       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6142       aFillAspect->SetTextureMapOn();
6143     }
6144     {
6145       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6146       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6147       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6148       myDrawer->SetTextAspect (aTextAspect);
6149     }
6150     {
6151       const gp_Dir aNorm (0.0, 0.0, 1.0);
6152       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6153       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6154       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6155       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6156       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6157       myTris->AddEdge (1);
6158       myTris->AddEdge (2);
6159       myTris->AddEdge (3);
6160       myTris->AddEdge (3);
6161       myTris->AddEdge (2);
6162       myTris->AddEdge (4);
6163
6164       myRect = new Graphic3d_ArrayOfPolylines (4);
6165       myRect->AddVertex (myTris->Vertice (1));
6166       myRect->AddVertex (myTris->Vertice (3));
6167       myRect->AddVertex (myTris->Vertice (4));
6168       myRect->AddVertex (myTris->Vertice (2));
6169     }
6170   }
6171
6172   //! Returns TRUE for accepted display modes.
6173   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
6174
6175   //! Compute presentation.
6176   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
6177   {
6178     switch (theMode)
6179     {
6180       case 0:
6181       {
6182         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6183         aGroup->AddPrimitiveArray (myTris);
6184         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6185         aGroup->AddPrimitiveArray (myRect);
6186         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6187         return;
6188       }
6189       case 1:
6190       {
6191         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6192         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6193         aGroup->AddPrimitiveArray (myRect);
6194         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6195         return;
6196       }
6197     }
6198   }
6199
6200   //! Compute selection.
6201   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6202   {
6203     if (theMode == 0)
6204     {
6205       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6206       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6207       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6208       theSel->Add (aSensitive);
6209     }
6210   }
6211
6212 private:
6213   Handle(Graphic3d_ArrayOfTriangles) myTris;
6214   Handle(Graphic3d_ArrayOfPolylines) myRect;
6215   TCollection_AsciiString myLabel;
6216   Standard_Real myWidth;
6217   Standard_Real myHeight;
6218 };
6219
6220 //==============================================================================
6221 //function : VDiffImage
6222 //purpose  : The draw-command compares two images.
6223 //==============================================================================
6224
6225 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6226 {
6227   if (theArgNb < 3)
6228   {
6229     std::cout << "Syntax error: not enough arguments.\n";
6230     return 1;
6231   }
6232
6233   Standard_Integer anArgIter = 1;
6234   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6235   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6236   TCollection_AsciiString aDiffImagePath;
6237   Standard_Real    aTolColor        = -1.0;
6238   Standard_Integer toBlackWhite     = -1;
6239   Standard_Integer isBorderFilterOn = -1;
6240   Standard_Boolean isOldSyntax = Standard_False;
6241   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6242   for (; anArgIter < theArgNb; ++anArgIter)
6243   {
6244     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6245     anArg.LowerCase();
6246     if (anArgIter + 1 < theArgNb
6247      && (anArg == "-toleranceofcolor"
6248       || anArg == "-tolerancecolor"
6249       || anArg == "-tolerance"
6250       || anArg == "-toler"))
6251     {
6252       aTolColor = Atof (theArgVec[++anArgIter]);
6253       if (aTolColor < 0.0 || aTolColor > 1.0)
6254       {
6255         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6256         return 1;
6257       }
6258     }
6259     else if (anArg == "-blackwhite")
6260     {
6261       Standard_Boolean toEnable = Standard_True;
6262       if (anArgIter + 1 < theArgNb
6263        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6264       {
6265         ++anArgIter;
6266       }
6267       toBlackWhite = toEnable ? 1 : 0;
6268     }
6269     else if (anArg == "-borderfilter")
6270     {
6271       Standard_Boolean toEnable = Standard_True;
6272       if (anArgIter + 1 < theArgNb
6273        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
6274       {
6275         ++anArgIter;
6276       }
6277       isBorderFilterOn = toEnable ? 1 : 0;
6278     }
6279     else if (anArg == "-exitonclose")
6280     {
6281       Draw_ToExitOnCloseView = true;
6282       if (anArgIter + 1 < theArgNb
6283        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToExitOnCloseView))
6284       {
6285         ++anArgIter;
6286       }
6287     }
6288     else if (anArg == "-closeonescape"
6289           || anArg == "-closeonesc")
6290     {
6291       Draw_ToCloseViewOnEsc = true;
6292       if (anArgIter + 1 < theArgNb
6293        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], Draw_ToCloseViewOnEsc))
6294       {
6295         ++anArgIter;
6296       }
6297     }
6298     else if (anArgIter + 3 < theArgNb
6299           && anArg == "-display")
6300     {
6301       aViewName   = theArgVec[++anArgIter];
6302       aPrsNameRef = theArgVec[++anArgIter];
6303       aPrsNameNew = theArgVec[++anArgIter];
6304       if (anArgIter + 1 < theArgNb
6305       && *theArgVec[anArgIter + 1] != '-')
6306       {
6307         aPrsNameDiff = theArgVec[++anArgIter];
6308       }
6309     }
6310     else if (aTolColor < 0.0
6311           && anArg.IsRealValue())
6312     {
6313       isOldSyntax = Standard_True;
6314       aTolColor = anArg.RealValue();
6315       if (aTolColor < 0.0 || aTolColor > 1.0)
6316       {
6317         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
6318         return 1;
6319       }
6320     }
6321     else if (isOldSyntax
6322           && toBlackWhite == -1
6323           && (anArg == "0" || anArg == "1"))
6324     {
6325       toBlackWhite = anArg == "1" ? 1 : 0;
6326     }
6327     else if (isOldSyntax
6328           && isBorderFilterOn == -1
6329           && (anArg == "0" || anArg == "1"))
6330     {
6331       isBorderFilterOn = anArg == "1" ? 1 : 0;
6332     }
6333     else if (aDiffImagePath.IsEmpty())
6334     {
6335       aDiffImagePath = theArgVec[anArgIter];
6336     }
6337     else
6338     {
6339       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
6340       return 1;
6341     }
6342   }
6343
6344   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6345   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6346   if (!anImgRef->Load (anImgPathRef))
6347   {
6348     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
6349     return 1;
6350   }
6351   if (!anImgNew->Load (anImgPathNew))
6352   {
6353     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
6354     return 1;
6355   }
6356
6357   // compare the images
6358   Image_Diff aComparer;
6359   Standard_Integer aDiffColorsNb = -1;
6360   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
6361   {
6362     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6363     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6364     aDiffColorsNb = aComparer.Compare();
6365     theDI << aDiffColorsNb << "\n";
6366   }
6367
6368   // save image of difference
6369   Handle(Image_AlienPixMap) aDiff;
6370   if (aDiffColorsNb > 0
6371   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6372   {
6373     aDiff = new Image_AlienPixMap();
6374     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6375     {
6376       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
6377       return 1;
6378     }
6379     aComparer.SaveDiffImage (*aDiff);
6380     if (!aDiffImagePath.IsEmpty()
6381      && !aDiff->Save (aDiffImagePath))
6382     {
6383       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
6384       return 1;
6385     }
6386   }
6387
6388   if (aViewName.IsEmpty())
6389   {
6390     return 0;
6391   }
6392
6393   ViewerTest_Names aViewNames (aViewName);
6394   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6395   {
6396     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6397     theDI.Eval (aCommand.ToCString());
6398   }
6399
6400   Standard_Integer aPxLeft = 0;
6401   Standard_Integer aPxTop  = 0;
6402   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
6403   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6404                               ? int(anImgRef->SizeY() * 2)
6405                               : int(anImgRef->SizeY());
6406   TCollection_AsciiString aDisplayName;
6407   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop,
6408                                                             aWinSizeX, aWinSizeY,
6409                                                             aViewName.ToCString(),
6410                                                             aDisplayName.ToCString());
6411
6412   Standard_Real aRatio = anImgRef->Ratio();
6413   Standard_Real aSizeX = 1.0;
6414   Standard_Real aSizeY = aSizeX / aRatio;
6415   {
6416     OSD_Path aPath (anImgPathRef);
6417     TCollection_AsciiString aLabelRef;
6418     if (!aPath.Name().IsEmpty())
6419     {
6420       aLabelRef = aPath.Name() + aPath.Extension();
6421     }
6422     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6423
6424     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6425     gp_Trsf aTrsfRef;
6426     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6427     anImgRefPrs->SetLocalTransformation (aTrsfRef);
6428     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
6429   }
6430   {
6431     OSD_Path aPath (anImgPathNew);
6432     TCollection_AsciiString aLabelNew;
6433     if (!aPath.Name().IsEmpty())
6434     {
6435       aLabelNew = aPath.Name() + aPath.Extension();
6436     }
6437     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
6438
6439     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6440     gp_Trsf aTrsfRef;
6441     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6442     anImgNewPrs->SetLocalTransformation (aTrsfRef);
6443     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6444   }
6445   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6446   if (!aDiff.IsNull())
6447   {
6448     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6449     gp_Trsf aTrsfDiff;
6450     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6451     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6452   }
6453   if (!aPrsNameDiff.IsEmpty())
6454   {
6455     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6456   }
6457   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6458   ViewerTest::CurrentView()->FitAll();
6459   return 0;
6460 }
6461
6462 //=======================================================================
6463 //function : VSelect
6464 //purpose  : Emulates different types of selection by mouse:
6465 //           1) single click selection
6466 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6467 //           3) selection with polygon having corners at
6468 //           pixel positions (x1,y1),...,(xn,yn)
6469 //           4) any of these selections with shift button pressed
6470 //=======================================================================
6471 static Standard_Integer VSelect (Draw_Interpretor& di,
6472                                  Standard_Integer argc,
6473                                  const char ** argv)
6474 {
6475   if(argc < 3)
6476   {
6477     di << "Usage : " << argv[0] << " x1 y1 [x2 y2 [... xn yn]] [shift_selection = 1|0]\n";
6478     return 1;
6479   }
6480
6481   Handle(AIS_InteractiveContext) myAIScontext = ViewerTest::GetAISContext();
6482   if(myAIScontext.IsNull())
6483   {
6484     di << "use 'vinit' command before " << argv[0] << "\n";
6485     return 1;
6486   }
6487
6488   const Standard_Boolean isShiftSelection = (argc > 3 && !(argc % 2) && (atoi (argv[argc - 1]) == 1));
6489   Standard_Integer aCoordsNb = isShiftSelection ? argc - 2 : argc - 1;
6490   TCollection_AsciiString anArg;
6491   anArg = isShiftSelection ? argv[argc - 3] : argv[argc - 2];
6492   anArg.LowerCase();
6493   if (anArg == "-allowoverlap")
6494   {
6495     Standard_Boolean isValidated = isShiftSelection ? argc == 8
6496       : argc == 7;
6497     if (!isValidated)
6498     {
6499       di << "Wrong number of arguments! -allowoverlap key is applied only for rectangle selection";
6500       return 1;
6501     }
6502
6503     Standard_Integer isToAllow = isShiftSelection ? Draw::Atoi(argv[argc - 2]) : Draw::Atoi(argv[argc - 1]);
6504     myAIScontext->MainSelector()->AllowOverlapDetection (isToAllow != 0);
6505     aCoordsNb -= 2;
6506   }
6507
6508   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
6509   aCurrentEventManager->MoveTo(atoi(argv[1]),atoi(argv[2]));
6510   if(aCoordsNb == 2)
6511   {
6512     if(isShiftSelection)
6513       aCurrentEventManager->ShiftSelect();
6514     else
6515       aCurrentEventManager->Select();
6516   }
6517   else if(aCoordsNb == 4)
6518   {
6519     if(isShiftSelection)
6520       aCurrentEventManager->ShiftSelect (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6521     else
6522       aCurrentEventManager->Select (atoi (argv[1]), atoi (argv[2]), atoi (argv[3]), atoi (argv[4]), Standard_False);
6523   }
6524   else
6525   {
6526     TColgp_Array1OfPnt2d aPolyline (1,aCoordsNb / 2);
6527
6528     for(Standard_Integer i=1;i<=aCoordsNb / 2;++i)
6529       aPolyline.SetValue(i,gp_Pnt2d(atoi(argv[2*i-1]),atoi(argv[2*i])));
6530
6531     if(isShiftSelection)
6532       aCurrentEventManager->ShiftSelect(aPolyline);
6533     else
6534       aCurrentEventManager->Select(aPolyline);
6535   }
6536   return 0;
6537 }
6538
6539 //=======================================================================
6540 //function : VMoveTo
6541 //purpose  : Emulates cursor movement to defined pixel position
6542 //=======================================================================
6543 static Standard_Integer VMoveTo (Draw_Interpretor& di,
6544                                 Standard_Integer argc,
6545                                 const char ** argv)
6546 {
6547   if(argc != 3)
6548   {
6549     di << "Usage : " << argv[0] << " x y\n";
6550     return 1;
6551   }
6552
6553   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6554   if(aContext.IsNull())
6555   {
6556     di << "use 'vinit' command before " << argv[0] << "\n";
6557     return 1;
6558   }
6559   ViewerTest::CurrentEventManager()->MoveTo(atoi(argv[1]),atoi(argv[2]));
6560   return 0;
6561 }
6562
6563 namespace
6564 {
6565   //! Global map storing all animations registered in ViewerTest.
6566   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6567
6568   //! The animation calling the Draw Harness command.
6569   class ViewerTest_AnimationProc : public AIS_Animation
6570   {
6571   public:
6572
6573     //! Main constructor.
6574     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6575                               Draw_Interpretor* theDI,
6576                               const TCollection_AsciiString& theCommand)
6577     : AIS_Animation (theAnimationName),
6578       myDrawInter(theDI),
6579       myCommand  (theCommand)
6580     {
6581       //
6582     }
6583
6584   protected:
6585
6586     //! Evaluate the command.
6587     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6588     {
6589       TCollection_AsciiString aCmd = myCommand;
6590       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
6591       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
6592       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
6593       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
6594       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6595       myDrawInter->Eval (aCmd.ToCString());
6596     }
6597
6598     //! Find the keyword in the command and replace it with value.
6599     //! @return the position of the keyword to pass value
6600     void replace (TCollection_AsciiString&       theCmd,
6601                   const TCollection_AsciiString& theKey,
6602                   const TCollection_AsciiString& theVal)
6603     {
6604       TCollection_AsciiString aCmd (theCmd);
6605       aCmd.LowerCase();
6606       const Standard_Integer aPos = aCmd.Search (theKey);
6607       if (aPos == -1)
6608       {
6609         return;
6610       }
6611
6612       TCollection_AsciiString aPart1, aPart2;
6613       Standard_Integer aPart1To = aPos - 1;
6614       if (aPart1To >= 1
6615        && aPart1To <= theCmd.Length())
6616       {
6617         aPart1 = theCmd.SubString (1, aPart1To);
6618       }
6619
6620       Standard_Integer aPart2From = aPos + theKey.Length();
6621       if (aPart2From >= 1
6622        && aPart2From <= theCmd.Length())
6623       {
6624         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6625       }
6626
6627       theCmd = aPart1 + theVal + aPart2;
6628     }
6629
6630   protected:
6631
6632     Draw_Interpretor*       myDrawInter;
6633     TCollection_AsciiString myCommand;
6634
6635   };
6636
6637   //! Replace the animation with the new one.
6638   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6639                                 Handle(AIS_Animation)&       theAnimation,
6640                                 const Handle(AIS_Animation)& theAnimationNew)
6641   {
6642     theAnimationNew->CopyFrom (theAnimation);
6643     if (!theParentAnimation.IsNull())
6644     {
6645       theParentAnimation->Replace (theAnimation, theAnimationNew);
6646     }
6647     else
6648     {
6649       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6650       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
6651     }
6652     theAnimation = theAnimationNew;
6653   }
6654
6655   //! Parse the point.
6656   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6657   {
6658     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
6659     if (!anXYZ[0].IsRealValue()
6660      || !anXYZ[1].IsRealValue()
6661      || !anXYZ[2].IsRealValue())
6662     {
6663       return Standard_False;
6664     }
6665
6666     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6667     return Standard_True;
6668   }
6669
6670   //! Parse the quaternion.
6671   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6672   {
6673     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
6674     if (!anXYZW[0].IsRealValue()
6675      || !anXYZW[1].IsRealValue()
6676      || !anXYZW[2].IsRealValue()
6677      || !anXYZW[3].IsRealValue())
6678     {
6679       return Standard_False;
6680     }
6681
6682     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6683     return Standard_True;
6684   }
6685
6686   //! Auxiliary class for flipping image upside-down.
6687   class ImageFlipper
6688   {
6689   public:
6690
6691     //! Empty constructor.
6692     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6693
6694     //! Perform flipping.
6695     Standard_Boolean FlipY (Image_PixMap& theImage)
6696     {
6697       if (theImage.IsEmpty()
6698        || theImage.SizeX() == 0
6699        || theImage.SizeY() == 0)
6700       {
6701         return Standard_False;
6702       }
6703
6704       const Standard_Size aRowSize = theImage.SizeRowBytes();
6705       if (myTmp.Size() < aRowSize
6706       && !myTmp.Allocate (aRowSize))
6707       {
6708         return Standard_False;
6709       }
6710
6711       // for odd height middle row should be left as is
6712       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6713       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6714       {
6715         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6716         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6717         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
6718         memcpy (aTop,               aBot,         aRowSize);
6719         memcpy (aBot,               myTmp.Data(), aRowSize);
6720       }
6721       return Standard_True;
6722     }
6723
6724   private:
6725     NCollection_Buffer myTmp;
6726   };
6727
6728 }
6729
6730 //=================================================================================================
6731 //function : VViewParams
6732 //purpose  : Gets or sets AIS View characteristics
6733 //=================================================================================================
6734 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
6735 {
6736   Handle(V3d_View) aView = ViewerTest::CurrentView();
6737   if (aView.IsNull())
6738   {
6739     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
6740     return 1;
6741   }
6742
6743   Standard_Boolean toSetProj     = Standard_False;
6744   Standard_Boolean toSetUp       = Standard_False;
6745   Standard_Boolean toSetAt       = Standard_False;
6746   Standard_Boolean toSetEye      = Standard_False;
6747   Standard_Boolean toSetScale    = Standard_False;
6748   Standard_Boolean toSetSize     = Standard_False;
6749   Standard_Boolean toSetCenter2d = Standard_False;
6750   Standard_Real    aViewScale = aView->Scale();
6751   Standard_Real    aViewSize  = 1.0;
6752   Graphic3d_Vec2i  aCenter2d;
6753   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6754   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6755   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
6756   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
6757   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
6758   if (theArgsNb == 1)
6759   {
6760     // print all of the available view parameters
6761     char aText[4096];
6762     Sprintf (aText,
6763              "Scale: %g\n"
6764              "Proj:  %12g %12g %12g\n"
6765              "Up:    %12g %12g %12g\n"
6766              "At:    %12g %12g %12g\n"
6767              "Eye:   %12g %12g %12g\n",
6768               aViewScale,
6769               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6770               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6771               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
6772               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
6773     theDi << aText;
6774     return 0;
6775   }
6776
6777   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6778   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6779   {
6780     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6781     anArg.LowerCase();
6782     if (anUpdateTool.parseRedrawMode (anArg))
6783     {
6784       continue;
6785     }
6786     else if (anArg == "-cmd"
6787           || anArg == "-command"
6788           || anArg == "-args")
6789     {
6790       char aText[4096];
6791       Sprintf (aText,
6792                "-scale %g "
6793                "-proj %g %g %g "
6794                "-up %g %g %g "
6795                "-at %g %g %g\n",
6796                 aViewScale,
6797                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6798                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
6799                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
6800       theDi << aText;
6801     }
6802     else if (anArg == "-scale"
6803           || anArg == "-size")
6804     {
6805       if (anArgIter + 1 < theArgsNb
6806        && *theArgVec[anArgIter + 1] != '-')
6807       {
6808         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
6809         if (aValueArg.IsRealValue())
6810         {
6811           ++anArgIter;
6812           if (anArg == "-scale")
6813           {
6814             toSetScale = Standard_True;
6815             aViewScale = aValueArg.RealValue();
6816           }
6817           else if (anArg == "-size")
6818           {
6819             toSetSize = Standard_True;
6820             aViewSize = aValueArg.RealValue();
6821           }
6822           continue;
6823         }
6824       }
6825       if (anArg == "-scale")
6826       {
6827         theDi << "Scale: " << aView->Scale() << "\n";
6828       }
6829       else if (anArg == "-size")
6830       {
6831         Graphic3d_Vec2d aSizeXY;
6832         aView->Size (aSizeXY.x(), aSizeXY.y());
6833         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
6834       }
6835     }
6836     else if (anArg == "-eye"
6837           || anArg == "-at"
6838           || anArg == "-up"
6839           || anArg == "-proj")
6840     {
6841       if (anArgIter + 3 < theArgsNb)
6842       {
6843         gp_XYZ anXYZ;
6844         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
6845         {
6846           anArgIter += 3;
6847           if (anArg == "-eye")
6848           {
6849             toSetEye = Standard_True;
6850             aViewEye = anXYZ;
6851           }
6852           else if (anArg == "-at")
6853           {
6854             toSetAt = Standard_True;
6855             aViewAt = anXYZ;
6856           }
6857           else if (anArg == "-up")
6858           {
6859             toSetUp = Standard_True;
6860             aViewUp = anXYZ;
6861           }
6862           else if (anArg == "-proj")
6863           {
6864             toSetProj = Standard_True;
6865             aViewProj = anXYZ;
6866           }
6867           continue;
6868         }
6869       }
6870
6871       if (anArg == "-eye")
6872       {
6873         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
6874       }
6875       else if (anArg == "-at")
6876       {
6877         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
6878       }
6879       else if (anArg == "-up")
6880       {
6881         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
6882       }
6883       else if (anArg == "-proj")
6884       {
6885         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
6886       }
6887     }
6888     else if (anArg == "-center")
6889     {
6890       if (anArgIter + 2 < theArgsNb)
6891       {
6892         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
6893         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
6894         if (anX.IsIntegerValue()
6895          && anY.IsIntegerValue())
6896         {
6897           toSetCenter2d = Standard_True;
6898           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
6899         }
6900       }
6901     }
6902     else
6903     {
6904       std::cout << "Syntax error at '" << anArg << "'\n";
6905       return 1;
6906     }
6907   }
6908
6909   // change view parameters in proper order
6910   if (toSetScale)
6911   {
6912     aView->SetScale (aViewScale);
6913   }
6914   if (toSetSize)
6915   {
6916     aView->SetSize (aViewSize);
6917   }
6918   if (toSetEye)
6919   {
6920     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
6921   }
6922   if (toSetAt)
6923   {
6924     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6925   }
6926   if (toSetProj)
6927   {
6928     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
6929   }
6930   if (toSetUp)
6931   {
6932     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
6933   }
6934   if (toSetCenter2d)
6935   {
6936     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
6937   }
6938
6939   return 0;
6940 }
6941
6942 //==============================================================================
6943 //function : VAnimation
6944 //purpose  :
6945 //==============================================================================
6946 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
6947                                     Standard_Integer  theArgNb,
6948                                     const char**      theArgVec)
6949 {
6950   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6951   if (theArgNb < 2)
6952   {
6953     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
6954          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
6955     {
6956       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
6957     }
6958     return 0;
6959   }
6960   if (aCtx.IsNull())
6961   {
6962     std::cout << "Error: no active view\n";
6963     return 1;
6964   }
6965
6966   Standard_Integer anArgIter = 1;
6967   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
6968   if (aNameArg.IsEmpty())
6969   {
6970     std::cout << "Syntax error: animation name is not defined.\n";
6971     return 1;
6972   }
6973
6974   TCollection_AsciiString aNameArgLower = aNameArg;
6975   aNameArgLower.LowerCase();
6976   if (aNameArgLower == "-reset"
6977    || aNameArgLower == "-clear")
6978   {
6979     ViewerTest_AnimationTimelineMap.Clear();
6980     return 0;
6981   }
6982   else if (aNameArg.Value (1) == '-')
6983   {
6984     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
6985     return 1;
6986   }
6987
6988   const char* aNameSplitter = "/";
6989   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
6990   if (aSplitPos == -1)
6991   {
6992     aNameSplitter = ".";
6993     aSplitPos = aNameArg.Search (aNameSplitter);
6994   }
6995
6996   // find existing or create a new animation by specified name within syntax "parent.child".
6997   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
6998   for (; !aNameArg.IsEmpty();)
6999   {
7000     TCollection_AsciiString aNameParent;
7001     if (aSplitPos != -1)
7002     {
7003       if (aSplitPos == aNameArg.Length())
7004       {
7005         std::cout << "Syntax error: animation name is not defined.\n";
7006         return 1;
7007       }
7008
7009       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7010       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7011
7012       aSplitPos = aNameArg.Search (aNameSplitter);
7013     }
7014     else
7015     {
7016       aNameParent = aNameArg;
7017       aNameArg.Clear();
7018     }
7019
7020     if (anAnimation.IsNull())
7021     {
7022       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7023       {
7024         anAnimation = new AIS_Animation (aNameParent);
7025         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7026       }
7027       aRootAnimation = anAnimation;
7028     }
7029     else
7030     {
7031       aParentAnimation = anAnimation;
7032       anAnimation = aParentAnimation->Find (aNameParent);
7033       if (anAnimation.IsNull())
7034       {
7035         anAnimation = new AIS_Animation (aNameParent);
7036         aParentAnimation->Add (anAnimation);
7037       }
7038     }
7039   }
7040
7041   if (anArgIter >= theArgNb)
7042   {
7043     // just print the list of children
7044     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
7045     {
7046       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
7047     }
7048     return 0;
7049   }
7050
7051   // animation parameters
7052   Standard_Boolean toPlay = Standard_False;
7053   Standard_Real aPlaySpeed     = 1.0;
7054   Standard_Real aPlayStartTime = anAnimation->StartPts();
7055   Standard_Real aPlayDuration  = anAnimation->Duration();
7056   Standard_Boolean isFreeCamera = Standard_False;
7057   Standard_Boolean isLockLoop   = Standard_False;
7058
7059   // video recording parameters
7060   TCollection_AsciiString aRecFile;
7061   Image_VideoParams aRecParams;
7062
7063   Handle(V3d_View) aView = ViewerTest::CurrentView();
7064   for (; anArgIter < theArgNb; ++anArgIter)
7065   {
7066     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7067     anArg.LowerCase();
7068     // general options
7069     if (anArg == "-reset"
7070      || anArg == "-clear")
7071     {
7072       anAnimation->Clear();
7073     }
7074     else if (anArg == "-remove"
7075           || anArg == "-del"
7076           || anArg == "-delete")
7077     {
7078       if (!aParentAnimation.IsNull())
7079       {
7080         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7081       }
7082       else
7083       {
7084         aParentAnimation->Remove (anAnimation);
7085       }
7086     }
7087     // playback options
7088     else if (anArg == "-play")
7089     {
7090       toPlay = Standard_True;
7091       if (++anArgIter < theArgNb)
7092       {
7093         if (*theArgVec[anArgIter] == '-')
7094         {
7095           --anArgIter;
7096           continue;
7097         }
7098         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7099
7100         if (++anArgIter < theArgNb)
7101         {
7102           if (*theArgVec[anArgIter] == '-')
7103           {
7104             --anArgIter;
7105             continue;
7106           }
7107           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7108         }
7109       }
7110     }
7111     else if (anArg == "-resume")
7112     {
7113       toPlay = Standard_True;
7114       aPlayStartTime = anAnimation->ElapsedTime();
7115       if (++anArgIter < theArgNb)
7116       {
7117         if (*theArgVec[anArgIter] == '-')
7118         {
7119           --anArgIter;
7120           continue;
7121         }
7122
7123         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7124       }
7125     }
7126     else if (anArg == "-playspeed"
7127           || anArg == "-speed")
7128     {
7129       if (++anArgIter >= theArgNb)
7130       {
7131         std::cout << "Syntax error at " << anArg << ".\n";
7132         return 1;
7133       }
7134       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7135     }
7136     else if (anArg == "-lock"
7137           || anArg == "-lockloop"
7138           || anArg == "-playlockloop")
7139     {
7140       isLockLoop = Standard_True;
7141     }
7142     else if (anArg == "-freecamera"
7143           || anArg == "-playfreecamera"
7144           || anArg == "-freelook")
7145     {
7146       isFreeCamera = Standard_True;
7147     }
7148     // video recodring options
7149     else if (anArg == "-rec"
7150           || anArg == "-record")
7151     {
7152       if (++anArgIter >= theArgNb)
7153       {
7154         std::cout << "Syntax error at " << anArg << ".\n";
7155         return 1;
7156       }
7157
7158       aRecFile = theArgVec[anArgIter];
7159       if (aRecParams.FpsNum <= 0)
7160       {
7161         aRecParams.FpsNum = 24;
7162       }
7163
7164       if (anArgIter + 2 < theArgNb
7165       && *theArgVec[anArgIter + 1] != '-'
7166       && *theArgVec[anArgIter + 2] != '-')
7167       {
7168         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
7169         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7170         if (aWidthArg .IsIntegerValue()
7171          && aHeightArg.IsIntegerValue())
7172         {
7173           aRecParams.Width  = aWidthArg .IntegerValue();
7174           aRecParams.Height = aHeightArg.IntegerValue();
7175           anArgIter += 2;
7176         }
7177       }
7178     }
7179     else if (anArg == "-fps")
7180     {
7181       if (++anArgIter >= theArgNb)
7182       {
7183         std::cout << "Syntax error at " << anArg << ".\n";
7184         return 1;
7185       }
7186
7187       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7188       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7189       if (aSplitIndex == 0)
7190       {
7191         aRecParams.FpsNum = aFpsArg.IntegerValue();
7192       }
7193       else
7194       {
7195         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7196         aFpsArg.Split (aFpsArg.Length() - 1);
7197         const TCollection_AsciiString aNumStr = aFpsArg;
7198         aRecParams.FpsNum = aNumStr.IntegerValue();
7199         aRecParams.FpsDen = aDenStr.IntegerValue();
7200         if (aRecParams.FpsDen < 1)
7201         {
7202           std::cout << "Syntax error at " << anArg << ".\n";
7203           return 1;
7204         }
7205       }
7206     }
7207     else if (anArg == "-format")
7208     {
7209       if (++anArgIter >= theArgNb)
7210       {
7211         std::cout << "Syntax error at " << anArg << ".\n";
7212         return 1;
7213       }
7214       aRecParams.Format = theArgVec[anArgIter];
7215     }
7216     else if (anArg == "-pix_fmt"
7217           || anArg == "-pixfmt"
7218           || anArg == "-pixelformat")
7219     {
7220       if (++anArgIter >= theArgNb)
7221       {
7222         std::cout << "Syntax error at " << anArg << ".\n";
7223         return 1;
7224       }
7225       aRecParams.PixelFormat = theArgVec[anArgIter];
7226     }
7227     else if (anArg == "-codec"
7228           || anArg == "-vcodec"
7229           || anArg == "-videocodec")
7230     {
7231       if (++anArgIter >= theArgNb)
7232       {
7233         std::cout << "Syntax error at " << anArg << ".\n";
7234         return 1;
7235       }
7236       aRecParams.VideoCodec = theArgVec[anArgIter];
7237     }
7238     else if (anArg == "-crf"
7239           || anArg == "-preset"
7240           || anArg == "-qp")
7241     {
7242       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7243       if (++anArgIter >= theArgNb)
7244       {
7245         std::cout << "Syntax error at " << anArg << ".\n";
7246         return 1;
7247       }
7248
7249       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7250     }
7251     // animation definition options
7252     else if (anArg == "-start"
7253           || anArg == "-starttime"
7254           || anArg == "-startpts")
7255     {
7256       if (++anArgIter >= theArgNb)
7257       {
7258         std::cout << "Syntax error at " << anArg << ".\n";
7259         return 1;
7260       }
7261
7262       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7263       aRootAnimation->UpdateTotalDuration();
7264     }
7265     else if (anArg == "-end"
7266           || anArg == "-endtime"
7267           || anArg == "-endpts")
7268     {
7269       if (++anArgIter >= theArgNb)
7270       {
7271         std::cout << "Syntax error at " << anArg << ".\n";
7272         return 1;
7273       }
7274
7275       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7276       aRootAnimation->UpdateTotalDuration();
7277     }
7278     else if (anArg == "-dur"
7279           || anArg == "-duration")
7280     {
7281       if (++anArgIter >= theArgNb)
7282       {
7283         std::cout << "Syntax error at " << anArg << ".\n";
7284         return 1;
7285       }
7286
7287       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7288       aRootAnimation->UpdateTotalDuration();
7289     }
7290     else if (anArg == "-command"
7291           || anArg == "-cmd"
7292           || anArg == "-invoke"
7293           || anArg == "-eval"
7294           || anArg == "-proc")
7295     {
7296       if (++anArgIter >= theArgNb)
7297       {
7298         std::cout << "Syntax error at " << anArg << ".\n";
7299         return 1;
7300       }
7301
7302       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7303       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7304     }
7305     else if (anArg == "-objecttrsf"
7306           || anArg == "-objectransformation"
7307           || anArg == "-objtransformation"
7308           || anArg == "-objtrsf"
7309           || anArg == "-object"
7310           || anArg == "-obj")
7311     {
7312       if (++anArgIter >= theArgNb)
7313       {
7314         std::cout << "Syntax error at " << anArg << ".\n";
7315         return 1;
7316       }
7317
7318       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7319       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
7320       if (!aMapOfAIS.IsBound2 (anObjName))
7321       {
7322         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
7323         return 1;
7324       }
7325
7326       Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName));
7327       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7328       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
7329       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
7330       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
7331       Standard_Boolean isTrsfSet = Standard_False;
7332       Standard_Integer aTrsfArgIter = anArgIter + 1;
7333       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7334       {
7335         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7336         aTrsfArg.LowerCase();
7337         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7338         if (aTrsfArg.StartsWith ("-rotation")
7339          || aTrsfArg.StartsWith ("-rot"))
7340         {
7341           isTrsfSet = Standard_True;
7342           if (aTrsfArgIter + 4 >= theArgNb
7343           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7344           {
7345             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7346             return 1;
7347           }
7348           aTrsfArgIter += 4;
7349         }
7350         else if (aTrsfArg.StartsWith ("-location")
7351               || aTrsfArg.StartsWith ("-loc"))
7352         {
7353           isTrsfSet = Standard_True;
7354           if (aTrsfArgIter + 3 >= theArgNb
7355           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7356           {
7357             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7358             return 1;
7359           }
7360           aTrsfArgIter += 3;
7361         }
7362         else if (aTrsfArg.StartsWith ("-scale"))
7363         {
7364           isTrsfSet = Standard_True;
7365           if (++aTrsfArgIter >= theArgNb)
7366           {
7367             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7368             return 1;
7369           }
7370
7371           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
7372           if (!aScaleStr.IsRealValue())
7373           {
7374             std::cout << "Syntax error at " << aTrsfArg << ".\n";
7375             return 1;
7376           }
7377           aScales[anIndex] = aScaleStr.RealValue();
7378         }
7379         else
7380         {
7381           anArgIter = aTrsfArgIter - 1;
7382           break;
7383         }
7384       }
7385       if (!isTrsfSet)
7386       {
7387         std::cout << "Syntax error at " << anArg << ".\n";
7388         return 1;
7389       }
7390       else if (aTrsfArgIter >= theArgNb)
7391       {
7392         anArgIter = theArgNb;
7393       }
7394
7395       aTrsfs[0].SetRotation        (aRotQuats[0]);
7396       aTrsfs[1].SetRotation        (aRotQuats[1]);
7397       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7398       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7399       aTrsfs[0].SetScaleFactor     (aScales[0]);
7400       aTrsfs[1].SetScaleFactor     (aScales[1]);
7401
7402       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7403       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7404     }
7405     else if (anArg == "-viewtrsf"
7406           || anArg == "-view")
7407     {
7408       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7409       if (aCamAnimation.IsNull())
7410       {
7411         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7412         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7413       }
7414
7415       Handle(Graphic3d_Camera) aCams[2] =
7416       {
7417         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7418         new Graphic3d_Camera (aCamAnimation->View()->Camera())
7419       };
7420
7421       Standard_Boolean isTrsfSet = Standard_False;
7422       Standard_Integer aViewArgIter = anArgIter + 1;
7423       for (; aViewArgIter < theArgNb; ++aViewArgIter)
7424       {
7425         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7426         aViewArg.LowerCase();
7427         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7428         if (aViewArg.StartsWith ("-scale"))
7429         {
7430           isTrsfSet = Standard_True;
7431           if (++aViewArgIter >= theArgNb)
7432           {
7433             std::cout << "Syntax error at " << anArg << ".\n";
7434             return 1;
7435           }
7436
7437           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
7438           if (!aScaleStr.IsRealValue())
7439           {
7440             std::cout << "Syntax error at " << aViewArg << ".\n";
7441             return 1;
7442           }
7443           Standard_Real aScale = aScaleStr.RealValue();
7444           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7445           aCams[anIndex]->SetScale (aScale);
7446         }
7447         else if (aViewArg.StartsWith ("-eye")
7448               || aViewArg.StartsWith ("-center")
7449               || aViewArg.StartsWith ("-at")
7450               || aViewArg.StartsWith ("-up"))
7451         {
7452           isTrsfSet = Standard_True;
7453           gp_XYZ anXYZ;
7454           if (aViewArgIter + 3 >= theArgNb
7455           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7456           {
7457             std::cout << "Syntax error at " << aViewArg << ".\n";
7458             return 1;
7459           }
7460           aViewArgIter += 3;
7461
7462           if (aViewArg.StartsWith ("-eye"))
7463           {
7464             aCams[anIndex]->SetEye (anXYZ);
7465           }
7466           else if (aViewArg.StartsWith ("-center")
7467                 || aViewArg.StartsWith ("-at"))
7468           {
7469             aCams[anIndex]->SetCenter (anXYZ);
7470           }
7471           else if (aViewArg.StartsWith ("-up"))
7472           {
7473             aCams[anIndex]->SetUp (anXYZ);
7474           }
7475         }
7476         else
7477         {
7478           anArgIter = aViewArgIter - 1;
7479           break;
7480         }
7481       }
7482       if (!isTrsfSet)
7483       {
7484         std::cout << "Syntax error at " << anArg << ".\n";
7485         return 1;
7486       }
7487       else if (aViewArgIter >= theArgNb)
7488       {
7489         anArgIter = theArgNb;
7490       }
7491
7492       aCamAnimation->SetCameraStart(aCams[0]);
7493       aCamAnimation->SetCameraEnd  (aCams[1]);
7494     }
7495     else
7496     {
7497       std::cout << "Syntax error at " << anArg << ".\n";
7498       return 1;
7499     }
7500   }
7501
7502   if (!toPlay && aRecFile.IsEmpty())
7503   {
7504     return 0;
7505   }
7506
7507   // Start animation timeline and process frame updating.
7508   TheIsAnimating = Standard_True;
7509   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
7510   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
7511   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7512   if (isFreeCamera)
7513   {
7514     aView->Camera()->Copy (aCameraBack);
7515   }
7516
7517   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
7518   if (aRecParams.FpsNum <= 0)
7519   {
7520     while (!anAnimation->IsStopped())
7521     {
7522       aCameraBack->Copy (aView->Camera());
7523       const Standard_Real aPts = anAnimation->UpdateTimer();
7524       if (isFreeCamera)
7525       {
7526         aView->Camera()->Copy (aCameraBack);
7527       }
7528
7529       if (aPts >= anUpperPts)
7530       {
7531         anAnimation->Pause();
7532         break;
7533       }
7534
7535       if (aView->IsInvalidated())
7536       {
7537         aView->Redraw();
7538       }
7539       else
7540       {
7541         aView->RedrawImmediate();
7542       }
7543
7544       if (!isLockLoop)
7545       {
7546         // handle user events
7547         theDI.Eval ("after 1 set waiter 1");
7548         theDI.Eval ("vwait waiter");
7549       }
7550       if (!TheIsAnimating)
7551       {
7552         anAnimation->Pause();
7553         theDI << aPts;
7554         break;
7555       }
7556     }
7557
7558     if (aView->IsInvalidated())
7559     {
7560       aView->Redraw();
7561     }
7562     else
7563     {
7564       aView->RedrawImmediate();
7565     }
7566   }
7567   else
7568   {
7569     OSD_Timer aPerfTimer;
7570     aPerfTimer.Start();
7571
7572     Handle(Image_VideoRecorder) aRecorder;
7573     ImageFlipper aFlipper;
7574     Handle(Draw_ProgressIndicator) aProgress;
7575     if (!aRecFile.IsEmpty())
7576     {
7577       if (aRecParams.Width  <= 0
7578        || aRecParams.Height <= 0)
7579       {
7580         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7581       }
7582
7583       aRecorder = new Image_VideoRecorder();
7584       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7585       {
7586         std::cout << "Error: failed to open video file for recording\n";
7587         return 0;
7588       }
7589
7590       aProgress = new Draw_ProgressIndicator (theDI, 1);
7591     }
7592
7593     // Manage frame-rated animation here
7594     Standard_Real aPts = aPlayStartTime;
7595     int64_t aNbFrames = 0;
7596     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
7597     Standard_Integer aSecondsProgress = 0;
7598     for (; aPts <= anUpperPts && aPSentry.More();)
7599     {
7600       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
7601       aPts = aPlayStartTime + aRecPts;
7602       ++aNbFrames;
7603       if (!anAnimation->Update (aPts))
7604       {
7605         break;
7606       }
7607
7608       if (!aRecorder.IsNull())
7609       {
7610         V3d_ImageDumpOptions aDumpParams;
7611         aDumpParams.Width          = aRecParams.Width;
7612         aDumpParams.Height         = aRecParams.Height;
7613         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
7614         aDumpParams.StereoOptions  = V3d_SDO_MONO;
7615         aDumpParams.ToAdjustAspect = Standard_True;
7616         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
7617         {
7618           std::cout << "Error: view dump is failed!\n";
7619           return 0;
7620         }
7621         aFlipper.FlipY (aRecorder->ChangeFrame());
7622         if (!aRecorder->PushFrame())
7623         {
7624           return 0;
7625         }
7626       }
7627       else
7628       {
7629         aView->Redraw();
7630       }
7631
7632       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7633       {
7634         aPSentry.Next();
7635         ++aSecondsProgress;
7636       }
7637     }
7638
7639     aPerfTimer.Stop();
7640     anAnimation->Stop();
7641     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7642     theDI << "Average FPS: " << aRecFps << "\n"
7643           << "Nb. Frames: "  << Standard_Real(aNbFrames);
7644
7645     aView->Redraw();
7646   }
7647
7648   aView->SetImmediateUpdate (wasImmediateUpdate);
7649   TheIsAnimating = Standard_False;
7650   return 0;
7651 }
7652
7653
7654 //=======================================================================
7655 //function : VChangeSelected
7656 //purpose  : Adds the shape to selection or remove one from it
7657 //=======================================================================
7658 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7659                                 Standard_Integer argc,
7660                                 const char ** argv)
7661 {
7662   if(argc != 2)
7663   {
7664     di<<"Usage : " << argv[0] << " shape \n";
7665     return 1;
7666   }
7667   //get AIS_Shape:
7668   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7669   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
7670   TCollection_AsciiString aName(argv[1]);
7671   Handle(AIS_InteractiveObject) anAISObject;
7672
7673   if(!aMap.IsBound2(aName))
7674   {
7675     di<<"Use 'vdisplay' before";
7676     return 1;
7677   }
7678   else
7679   {
7680     anAISObject = Handle(AIS_InteractiveObject)::DownCast(aMap.Find2(aName));
7681     if(anAISObject.IsNull()){
7682       di<<"No interactive object \n";
7683       return 1;
7684     }
7685
7686     aContext->AddOrRemoveSelected(anAISObject, Standard_True);
7687   }
7688   return 0;
7689 }
7690
7691 //=======================================================================
7692 //function : VNbSelected
7693 //purpose  : Returns number of selected objects
7694 //=======================================================================
7695 static Standard_Integer VNbSelected (Draw_Interpretor& di,
7696                                 Standard_Integer argc,
7697                                 const char ** argv)
7698 {
7699   if(argc != 1)
7700   {
7701     di << "Usage : " << argv[0] << "\n";
7702     return 1;
7703   }
7704   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7705   if(aContext.IsNull())
7706   {
7707     di << "use 'vinit' command before " << argv[0] << "\n";
7708     return 1;
7709   }
7710   di << aContext->NbSelected() << "\n";
7711   return 0;
7712 }
7713
7714 //=======================================================================
7715 //function : VPurgeDisplay
7716 //purpose  : Switches altialiasing on or off
7717 //=======================================================================
7718 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
7719                                 Standard_Integer argc,
7720                                 const char ** argv)
7721 {
7722   if (argc > 1)
7723   {
7724     di << "Usage : " << argv[0] << "\n";
7725     return 1;
7726   }
7727   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7728   if (aContext.IsNull())
7729   {
7730     di << "use 'vinit' command before " << argv[0] << "\n";
7731     return 1;
7732   }
7733
7734   di << aContext->PurgeDisplay() << "\n";
7735   return 0;
7736 }
7737
7738 //=======================================================================
7739 //function : VSetViewSize
7740 //purpose  :
7741 //=======================================================================
7742 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
7743                                 Standard_Integer argc,
7744                                 const char ** argv)
7745 {
7746   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7747   if(aContext.IsNull())
7748   {
7749     di << "use 'vinit' command before " << argv[0] << "\n";
7750     return 1;
7751   }
7752   if(argc != 2)
7753   {
7754     di<<"Usage : " << argv[0] << " Size\n";
7755     return 1;
7756   }
7757   Standard_Real aSize = Draw::Atof (argv[1]);
7758   if (aSize <= 0.)
7759   {
7760     di<<"Bad Size value  : " << aSize << "\n";
7761     return 1;
7762   }
7763
7764   Handle(V3d_View) aView = ViewerTest::CurrentView();
7765   aView->SetSize(aSize);
7766   return 0;
7767 }
7768
7769 //=======================================================================
7770 //function : VMoveView
7771 //purpose  :
7772 //=======================================================================
7773 static Standard_Integer VMoveView (Draw_Interpretor& di,
7774                                 Standard_Integer argc,
7775                                 const char ** argv)
7776 {
7777   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7778   if(aContext.IsNull())
7779   {
7780     di << "use 'vinit' command before " << argv[0] << "\n";
7781     return 1;
7782   }
7783   if(argc < 4 || argc > 5)
7784   {
7785     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7786     return 1;
7787   }
7788   Standard_Real Dx = Draw::Atof (argv[1]);
7789   Standard_Real Dy = Draw::Atof (argv[2]);
7790   Standard_Real Dz = Draw::Atof (argv[3]);
7791   Standard_Boolean aStart = Standard_True;
7792   if (argc == 5)
7793   {
7794       aStart = (Draw::Atoi (argv[4]) > 0);
7795   }
7796
7797   Handle(V3d_View) aView = ViewerTest::CurrentView();
7798   aView->Move(Dx,Dy,Dz,aStart);
7799   return 0;
7800 }
7801
7802 //=======================================================================
7803 //function : VTranslateView
7804 //purpose  :
7805 //=======================================================================
7806 static Standard_Integer VTranslateView (Draw_Interpretor& di,
7807                                 Standard_Integer argc,
7808                                 const char ** argv)
7809 {
7810   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7811   if(aContext.IsNull())
7812   {
7813     di << "use 'vinit' command before " << argv[0] << "\n";
7814     return 1;
7815   }
7816   if(argc < 4 || argc > 5)
7817   {
7818     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
7819     return 1;
7820   }
7821   Standard_Real Dx = Draw::Atof (argv[1]);
7822   Standard_Real Dy = Draw::Atof (argv[2]);
7823   Standard_Real Dz = Draw::Atof (argv[3]);
7824   Standard_Boolean aStart = Standard_True;
7825   if (argc == 5)
7826   {
7827       aStart = (Draw::Atoi (argv[4]) > 0);
7828   }
7829
7830   Handle(V3d_View) aView = ViewerTest::CurrentView();
7831   aView->Translate(Dx,Dy,Dz,aStart);
7832   return 0;
7833 }
7834
7835 //=======================================================================
7836 //function : VTurnView
7837 //purpose  :
7838 //=======================================================================
7839 static Standard_Integer VTurnView (Draw_Interpretor& di,
7840                                 Standard_Integer argc,
7841                                 const char ** argv)
7842 {
7843   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7844   if(aContext.IsNull()) {
7845     di << "use 'vinit' command before " << argv[0] << "\n";
7846     return 1;
7847   }
7848   if(argc < 4 || argc > 5){
7849     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
7850     return 1;
7851   }
7852   Standard_Real Ax = Draw::Atof (argv[1]);
7853   Standard_Real Ay = Draw::Atof (argv[2]);
7854   Standard_Real Az = Draw::Atof (argv[3]);
7855   Standard_Boolean aStart = Standard_True;
7856   if (argc == 5)
7857   {
7858       aStart = (Draw::Atoi (argv[4]) > 0);
7859   }
7860
7861   Handle(V3d_View) aView = ViewerTest::CurrentView();
7862   aView->Turn(Ax,Ay,Az,aStart);
7863   return 0;
7864 }
7865
7866 //==============================================================================
7867 //function : VTextureEnv
7868 //purpose  : ENables or disables environment mapping
7869 //==============================================================================
7870 class OCC_TextureEnv : public Graphic3d_TextureEnv
7871 {
7872 public:
7873   OCC_TextureEnv(const Standard_CString FileName);
7874   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
7875   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
7876                             const Standard_Boolean theModulateFlag,
7877                             const Graphic3d_TypeOfTextureFilter theFilter,
7878                             const Standard_ShortReal theXScale,
7879                             const Standard_ShortReal theYScale,
7880                             const Standard_ShortReal theXShift,
7881                             const Standard_ShortReal theYShift,
7882                             const Standard_ShortReal theAngle);
7883   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
7884 };
7885 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
7886
7887 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
7888   : Graphic3d_TextureEnv(theFileName)
7889 {
7890 }
7891
7892 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
7893   : Graphic3d_TextureEnv(theTexId)
7894 {
7895 }
7896
7897 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
7898                                           const Standard_Boolean theModulateFlag,
7899                                           const Graphic3d_TypeOfTextureFilter theFilter,
7900                                           const Standard_ShortReal theXScale,
7901                                           const Standard_ShortReal theYScale,
7902                                           const Standard_ShortReal theXShift,
7903                                           const Standard_ShortReal theYShift,
7904                                           const Standard_ShortReal theAngle)
7905 {
7906   myParams->SetRepeat     (theRepeatFlag);
7907   myParams->SetModulate   (theModulateFlag);
7908   myParams->SetFilter     (theFilter);
7909   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
7910   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
7911   myParams->SetRotation   (theAngle);
7912 }
7913
7914 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
7915 {
7916   // get the active view
7917   Handle(V3d_View) aView = ViewerTest::CurrentView();
7918   if (aView.IsNull())
7919   {
7920     std::cerr << "No active view. Please call vinit.\n";
7921     return 1;
7922   }
7923
7924   // Checking the input arguments
7925   Standard_Boolean anEnableFlag = Standard_False;
7926   Standard_Boolean isOk         = theArgNb >= 2;
7927   if (isOk)
7928   {
7929     TCollection_AsciiString anEnableOpt(theArgVec[1]);
7930     anEnableFlag = anEnableOpt.IsEqual("on");
7931     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
7932   }
7933   if (anEnableFlag)
7934   {
7935     isOk = (theArgNb == 3 || theArgNb == 11);
7936     if (isOk)
7937     {
7938       TCollection_AsciiString aTextureOpt(theArgVec[2]);
7939       isOk = (!aTextureOpt.IsIntegerValue() ||
7940              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
7941
7942       if (isOk && theArgNb == 11)
7943       {
7944         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
7945                                 aModulateOpt(theArgVec[4]),
7946                                 aFilterOpt  (theArgVec[5]),
7947                                 aSScaleOpt  (theArgVec[6]),
7948                                 aTScaleOpt  (theArgVec[7]),
7949                                 aSTransOpt  (theArgVec[8]),
7950                                 aTTransOpt  (theArgVec[9]),
7951                                 anAngleOpt  (theArgVec[10]);
7952         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
7953                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
7954                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
7955                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
7956                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
7957                 anAngleOpt.IsRealValue());
7958       }
7959     }
7960   }
7961
7962   if (!isOk)
7963   {
7964     std::cerr << "Usage :" << std::endl;
7965     std::cerr << theArgVec[0] << " off" << std::endl;
7966     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;
7967     return 1;
7968   }
7969
7970   if (anEnableFlag)
7971   {
7972     TCollection_AsciiString aTextureOpt(theArgVec[2]);
7973     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
7974                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
7975                                      new OCC_TextureEnv(theArgVec[2]);
7976
7977     if (theArgNb == 11)
7978     {
7979       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
7980       aTexEnv->SetTextureParameters(
7981         aRepeatOpt.  IsEqual("repeat"),
7982         aModulateOpt.IsEqual("modulate"),
7983         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
7984                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
7985                                                                            Graphic3d_TOTF_TRILINEAR,
7986         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
7987         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
7988         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
7989         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
7990         (Standard_ShortReal)Draw::Atof(theArgVec[10])
7991         );
7992     }
7993     aView->SetTextureEnv(aTexEnv);
7994   }
7995   else // Disabling environment mapping
7996   {
7997     Handle(Graphic3d_TextureEnv) aTexture;
7998     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
7999   }
8000
8001   aView->Redraw();
8002   return 0;
8003 }
8004
8005 namespace
8006 {
8007   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8008
8009   //! Remove registered clipping plane from all views and objects.
8010   static void removePlane (MapOfPlanes& theRegPlanes,
8011                            const TCollection_AsciiString& theName)
8012   {
8013     Handle(Graphic3d_ClipPlane) aClipPlane;
8014     if (!theRegPlanes.Find (theName, aClipPlane))
8015     {
8016       std::cout << "Warning: no such plane.\n";
8017       return;
8018     }
8019
8020     theRegPlanes.UnBind (theName);
8021     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8022          anIObjIt.More(); anIObjIt.Next())
8023     {
8024       Handle(PrsMgr_PresentableObject) aPrs = Handle(PrsMgr_PresentableObject)::DownCast (anIObjIt.Key1());
8025       aPrs->RemoveClipPlane (aClipPlane);
8026     }
8027
8028     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8029          aViewIt.More(); aViewIt.Next())
8030     {
8031       const Handle(V3d_View)& aView = aViewIt.Key2();
8032       aView->RemoveClipPlane(aClipPlane);
8033     }
8034
8035     ViewerTest::RedrawAllViews();
8036   }
8037 }
8038
8039 //===============================================================================================
8040 //function : VClipPlane
8041 //purpose  :
8042 //===============================================================================================
8043 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8044 {
8045   // use short-cut for created clip planes map of created (or "registered by name") clip planes
8046   static MapOfPlanes aRegPlanes;
8047
8048   if (theArgsNb < 2)
8049   {
8050     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8051     {
8052       theDi << aPlaneIter.Key() << " ";
8053     }
8054     return 0;
8055   }
8056
8057   TCollection_AsciiString aCommand (theArgVec[1]);
8058   aCommand.LowerCase();
8059   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8060   if (anActiveView.IsNull())
8061   {
8062     std::cout << "Error: no active view.\n";
8063     return 1;
8064   }
8065
8066   // print maximum number of planes for current viewer
8067   if (aCommand == "-maxplanes"
8068    || aCommand == "maxplanes")
8069   {
8070     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8071           << " plane slots provided by driver.\n";
8072     return 0;
8073   }
8074
8075   // create / delete plane instance
8076   if (aCommand == "-create"
8077    || aCommand == "create"
8078    || aCommand == "-delete"
8079    || aCommand == "delete"
8080    || aCommand == "-clone"
8081    || aCommand == "clone")
8082   {
8083     if (theArgsNb < 3)
8084     {
8085       std::cout << "Syntax error: plane name is required.\n";
8086       return 1;
8087     }
8088
8089     Standard_Boolean toCreate = aCommand == "-create"
8090                              || aCommand == "create";
8091     Standard_Boolean toClone  = aCommand == "-clone"
8092                              || aCommand == "clone";
8093     Standard_Boolean toDelete = aCommand == "-delete"
8094                              || aCommand == "delete";
8095     TCollection_AsciiString aPlane (theArgVec[2]);
8096
8097     if (toCreate)
8098     {
8099       if (aRegPlanes.IsBound (aPlane))
8100       {
8101         std::cout << "Warning: existing plane has been overridden.\n";
8102         toDelete = true;
8103       }
8104       else
8105       {
8106         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8107         return 0;
8108       }
8109     }
8110     else if (toClone) // toClone
8111     {
8112       if (!aRegPlanes.IsBound (aPlane))
8113       {
8114         std::cout << "Error: no such plane.\n";
8115         return 1;
8116       }
8117       else if (theArgsNb < 4)
8118       {
8119         std::cout << "Syntax error: enter name for new plane.\n";
8120         return 1;
8121       }
8122
8123       TCollection_AsciiString aClone (theArgVec[3]);
8124       if (aRegPlanes.IsBound (aClone))
8125       {
8126         std::cout << "Error: plane name is in use.\n";
8127         return 1;
8128       }
8129
8130       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8131
8132       aRegPlanes.Bind (aClone, aClipPlane->Clone());
8133       return 0;
8134     }
8135
8136     if (toDelete)
8137     {
8138       if (aPlane == "ALL"
8139        || aPlane == "all"
8140        || aPlane == "*")
8141       {
8142         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8143         {
8144           aPlane = aPlaneIter.Key();
8145           removePlane (aRegPlanes, aPlane);
8146           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8147         }
8148       }
8149       else
8150       {
8151         removePlane (aRegPlanes, aPlane);
8152       }
8153     }
8154
8155     if (toCreate)
8156     {
8157       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8158     }
8159     return 0;
8160   }
8161
8162   // set / unset plane command
8163   if (aCommand == "set"
8164    || aCommand == "unset")
8165   {
8166     if (theArgsNb < 5)
8167     {
8168       std::cout << "Syntax error: need more arguments.\n";
8169       return 1;
8170     }
8171
8172     // redirect to new syntax
8173     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8174     anArgVec.SetValue (1, theArgVec[0]);
8175     anArgVec.SetValue (2, theArgVec[2]);
8176     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8177     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
8178     {
8179       anArgVec.SetValue (anIt, theArgVec[anIt]);
8180     }
8181
8182     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
8183   }
8184
8185   // change plane command
8186   TCollection_AsciiString aPlaneName;
8187   Handle(Graphic3d_ClipPlane) aClipPlane;
8188   Standard_Integer anArgIter = 0;
8189   if (aCommand == "-change"
8190    || aCommand == "change")
8191   {
8192     // old syntax support
8193     if (theArgsNb < 3)
8194     {
8195       std::cout << "Syntax error: need more arguments.\n";
8196       return 1;
8197     }
8198
8199     anArgIter  = 3;
8200     aPlaneName = theArgVec[2];
8201     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
8202     {
8203       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
8204       return 1;
8205     }
8206   }
8207   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8208   {
8209     anArgIter  = 2;
8210     aPlaneName = theArgVec[1];
8211   }
8212   else
8213   {
8214     anArgIter  = 2;
8215     aPlaneName = theArgVec[1];
8216     aClipPlane = new Graphic3d_ClipPlane();
8217     aRegPlanes.Bind (aPlaneName, aClipPlane);
8218     theDi << "Created new plane " << aPlaneName << ".\n";
8219   }
8220
8221   if (theArgsNb - anArgIter < 1)
8222   {
8223     std::cout << "Syntax error: need more arguments.\n";
8224     return 1;
8225   }
8226
8227   for (; anArgIter < theArgsNb; ++anArgIter)
8228   {
8229     const char**     aChangeArgs   = theArgVec + anArgIter;
8230     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8231     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8232     aChangeArg.LowerCase();
8233
8234     Standard_Boolean toEnable = Standard_True;
8235     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
8236     {
8237       aClipPlane->SetOn (toEnable);
8238     }
8239     else if (aChangeArg == "-equation"
8240           || aChangeArg == "equation")
8241     {
8242       if (aNbChangeArgs < 5)
8243       {
8244         std::cout << "Syntax error: need more arguments.\n";
8245         return 1;
8246       }
8247
8248       Standard_Real aCoeffA = Draw::Atof (aChangeArgs [1]);
8249       Standard_Real aCoeffB = Draw::Atof (aChangeArgs [2]);
8250       Standard_Real aCoeffC = Draw::Atof (aChangeArgs [3]);
8251       Standard_Real aCoeffD = Draw::Atof (aChangeArgs [4]);
8252       aClipPlane->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
8253       anArgIter += 4;
8254     }
8255     else if (aChangeArg == "-capping"
8256           || aChangeArg == "capping")
8257     {
8258       if (aNbChangeArgs < 2)
8259       {
8260         std::cout << "Syntax error: need more arguments.\n";
8261         return 1;
8262       }
8263
8264       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8265       {
8266         aClipPlane->SetCapping (toEnable);
8267         anArgIter += 1;
8268       }
8269       else
8270       {
8271         // just skip otherwise (old syntax)
8272       }
8273     }
8274     else if (aChangeArg == "-useobjectmaterial"
8275           || aChangeArg == "-useobjectmat"
8276           || aChangeArg == "-useobjmat"
8277           || aChangeArg == "-useobjmaterial")
8278     {
8279       if (aNbChangeArgs < 2)
8280       {
8281         std::cout << "Syntax error: need more arguments.\n";
8282         return 1;
8283       }
8284
8285       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8286       {
8287         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8288         anArgIter += 1;
8289       }
8290     }
8291     else if (aChangeArg == "-useobjecttexture"
8292           || aChangeArg == "-useobjecttex"
8293           || aChangeArg == "-useobjtexture"
8294           || aChangeArg == "-useobjtex")
8295     {
8296       if (aNbChangeArgs < 2)
8297       {
8298         std::cout << "Syntax error: need more arguments.\n";
8299         return 1;
8300       }
8301
8302       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8303       {
8304         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8305         anArgIter += 1;
8306       }
8307     }
8308     else if (aChangeArg == "-useobjectshader"
8309           || aChangeArg == "-useobjshader")
8310     {
8311       if (aNbChangeArgs < 2)
8312       {
8313         std::cout << "Syntax error: need more arguments.\n";
8314         return 1;
8315       }
8316
8317       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
8318       {
8319         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8320         anArgIter += 1;
8321       }
8322     }
8323     else if (aChangeArg == "-color"
8324           || aChangeArg == "color")
8325     {
8326       Quantity_Color aColor;
8327       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
8328                                                            aChangeArgs + 1,
8329                                                            aColor);
8330       if (aNbParsed == 0)
8331       {
8332         std::cout << "Syntax error: need more arguments.\n";
8333         return 1;
8334       }
8335
8336       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8337       aMat.SetAmbientColor (aColor);
8338       aMat.SetDiffuseColor (aColor);
8339       aClipPlane->SetCappingMaterial (aMat);
8340       anArgIter += aNbParsed;
8341     }
8342     else if (aChangeArg == "-texname"
8343           || aChangeArg == "texname")
8344     {
8345       if (aNbChangeArgs < 2)
8346       {
8347         std::cout << "Syntax error: need more arguments.\n";
8348         return 1;
8349       }
8350
8351       TCollection_AsciiString aTextureName (aChangeArgs[1]);
8352       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
8353       if (!aTexture->IsDone())
8354       {
8355         aClipPlane->SetCappingTexture (NULL);
8356       }
8357       else
8358       {
8359         aTexture->EnableModulate();
8360         aTexture->EnableRepeat();
8361         aClipPlane->SetCappingTexture (aTexture);
8362       }
8363       anArgIter += 1;
8364     }
8365     else if (aChangeArg == "-texscale"
8366           || aChangeArg == "texscale")
8367     {
8368       if (aClipPlane->CappingTexture().IsNull())
8369       {
8370         std::cout << "Error: no texture is set.\n";
8371         return 1;
8372       }
8373
8374       if (aNbChangeArgs < 3)
8375       {
8376         std::cout << "Syntax error: need more arguments.\n";
8377         return 1;
8378       }
8379
8380       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8381       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8382       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8383       anArgIter += 2;
8384     }
8385     else if (aChangeArg == "-texorigin"
8386           || aChangeArg == "texorigin") // texture origin
8387     {
8388       if (aClipPlane->CappingTexture().IsNull())
8389       {
8390         std::cout << "Error: no texture is set.\n";
8391         return 1;
8392       }
8393
8394       if (aNbChangeArgs < 3)
8395       {
8396         std::cout << "Syntax error: need more arguments.\n";
8397         return 1;
8398       }
8399
8400       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8401       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8402
8403       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8404       anArgIter += 2;
8405     }
8406     else if (aChangeArg == "-texrotate"
8407           || aChangeArg == "texrotate") // texture rotation
8408     {
8409       if (aClipPlane->CappingTexture().IsNull())
8410       {
8411         std::cout << "Error: no texture is set.\n";
8412         return 1;
8413       }
8414
8415       if (aNbChangeArgs < 2)
8416       {
8417         std::cout << "Syntax error: need more arguments.\n";
8418         return 1;
8419       }
8420
8421       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8422       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8423       anArgIter += 1;
8424     }
8425     else if (aChangeArg == "-hatch"
8426           || aChangeArg == "hatch")
8427     {
8428       if (aNbChangeArgs < 2)
8429       {
8430         std::cout << "Syntax error: need more arguments.\n";
8431         return 1;
8432       }
8433
8434       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8435       aHatchStr.LowerCase();
8436       if (aHatchStr == "on")
8437       {
8438         aClipPlane->SetCappingHatchOn();
8439       }
8440       else if (aHatchStr == "off")
8441       {
8442         aClipPlane->SetCappingHatchOff();
8443       }
8444       else
8445       {
8446         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8447       }
8448       anArgIter += 1;
8449     }
8450     else if (aChangeArg == "-delete"
8451           || aChangeArg == "delete")
8452     {
8453       removePlane (aRegPlanes, aPlaneName);
8454       return 0;
8455     }
8456     else if (aChangeArg == "-set"
8457           || aChangeArg == "-unset")
8458     {
8459       // set / unset plane command
8460       Standard_Boolean toSet = aChangeArg == "-set";
8461       Standard_Integer anIt = 1;
8462       for (; anIt < aNbChangeArgs; ++anIt)
8463       {
8464         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8465         if (anEntityName.IsEmpty()
8466          || anEntityName.Value (1) == '-')
8467         {
8468           break;
8469         }
8470         else if (ViewerTest_myViews.IsBound1 (anEntityName))
8471         {
8472           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
8473           if (toSet)
8474           {
8475             aView->AddClipPlane (aClipPlane);
8476           }
8477           else
8478           {
8479             aView->RemoveClipPlane (aClipPlane);
8480           }
8481           continue;
8482         }
8483         else if (GetMapOfAIS().IsBound2 (anEntityName))
8484         {
8485           Handle(AIS_InteractiveObject) aIObj = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anEntityName));
8486           if (toSet)
8487           {
8488             aIObj->AddClipPlane (aClipPlane);
8489           }
8490           else
8491           {
8492             aIObj->RemoveClipPlane (aClipPlane);
8493           }
8494         }
8495         else
8496         {
8497           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
8498           return 1;
8499         }
8500       }
8501
8502       if (anIt == 1)
8503       {
8504         // apply to active view
8505         if (toSet)
8506         {
8507           anActiveView->AddClipPlane (aClipPlane);
8508         }
8509         else
8510         {
8511           anActiveView->RemoveClipPlane (aClipPlane);
8512         }
8513       }
8514       else
8515       {
8516         anArgIter = anArgIter + anIt - 1;
8517       }
8518     }
8519     else
8520     {
8521       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
8522       return 1;
8523     }
8524   }
8525
8526   ViewerTest::RedrawAllViews();
8527   return 0;
8528 }
8529
8530 //===============================================================================================
8531 //function : VZRange
8532 //purpose  :
8533 //===============================================================================================
8534 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8535 {
8536   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8537
8538   if (aCurrentView.IsNull())
8539   {
8540     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8541     return 1;
8542   }
8543
8544   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
8545
8546   if (theArgsNb < 2)
8547   {
8548     theDi << "ZNear: " << aCamera->ZNear() << "\n";
8549     theDi << "ZFar: " << aCamera->ZFar() << "\n";
8550     return 0;
8551   }
8552
8553   if (theArgsNb == 3)
8554   {
8555     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8556     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
8557
8558     if (aNewZNear >= aNewZFar)
8559     {
8560       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
8561       return 1;
8562     }
8563
8564     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8565     {
8566       std::cout << theArgVec[0] << ": invalid arguments: ";
8567       std::cout << "znear, zfar should be positive for perspective camera.\n";
8568       return 1;
8569     }
8570
8571     aCamera->SetZRange (aNewZNear, aNewZFar);
8572   }
8573   else
8574   {
8575     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8576     return 1;
8577   }
8578
8579   aCurrentView->Redraw();
8580
8581   return 0;
8582 }
8583
8584 //===============================================================================================
8585 //function : VAutoZFit
8586 //purpose  :
8587 //===============================================================================================
8588 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8589 {
8590   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8591
8592   if (aCurrentView.IsNull())
8593   {
8594     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
8595     return 1;
8596   }
8597
8598   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
8599
8600   if (theArgsNb > 3)
8601   {
8602     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
8603     return 1;
8604   }
8605
8606   if (theArgsNb < 2)
8607   {
8608     theDi << "Auto z-fit mode: \n"
8609           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
8610           << "Scale: " << aScale << "\n";
8611     return 0;
8612   }
8613
8614   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
8615
8616   if (theArgsNb >= 3)
8617   {
8618     aScale = Draw::Atoi (theArgVec[2]);
8619   }
8620
8621   aCurrentView->SetAutoZFitMode (isOn, aScale);
8622   aCurrentView->AutoZFit();
8623   aCurrentView->Redraw();
8624
8625   return 0;
8626 }
8627
8628 //! Auxiliary function to print projection type
8629 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
8630 {
8631   switch (theProjType)
8632   {
8633     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
8634     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
8635     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
8636     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
8637     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
8638   }
8639   return "UNKNOWN";
8640 }
8641
8642 //===============================================================================================
8643 //function : VCamera
8644 //purpose  :
8645 //===============================================================================================
8646 static int VCamera (Draw_Interpretor& theDI,
8647                     Standard_Integer  theArgsNb,
8648                     const char**      theArgVec)
8649 {
8650   Handle(V3d_View) aView = ViewerTest::CurrentView();
8651   if (aView.IsNull())
8652   {
8653     std::cout << "Error: no active view.\n";
8654     return 1;
8655   }
8656
8657   Handle(Graphic3d_Camera) aCamera = aView->Camera();
8658   if (theArgsNb < 2)
8659   {
8660     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
8661     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
8662     theDI << "Distance:   " << aCamera->Distance() << "\n";
8663     theDI << "IOD:        " << aCamera->IOD() << "\n";
8664     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
8665     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
8666     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
8667     return 0;
8668   }
8669
8670   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
8671   {
8672     Standard_CString        anArg = theArgVec[anArgIter];
8673     TCollection_AsciiString anArgCase (anArg);
8674     anArgCase.LowerCase();
8675     if (anArgCase == "-proj"
8676      || anArgCase == "-projection"
8677      || anArgCase == "-projtype"
8678      || anArgCase == "-projectiontype")
8679     {
8680       theDI << projTypeName (aCamera->ProjectionType()) << " ";
8681     }
8682     else if (anArgCase == "-ortho"
8683           || anArgCase == "-orthographic")
8684     {
8685       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
8686     }
8687     else if (anArgCase == "-persp"
8688           || anArgCase == "-perspective"
8689           || anArgCase == "-perspmono"
8690           || anArgCase == "-perspectivemono"
8691           || anArgCase == "-mono")
8692     {
8693       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
8694     }
8695     else if (anArgCase == "-stereo"
8696           || anArgCase == "-stereoscopic"
8697           || anArgCase == "-perspstereo"
8698           || anArgCase == "-perspectivestereo")
8699     {
8700       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
8701     }
8702     else if (anArgCase == "-left"
8703           || anArgCase == "-lefteye"
8704           || anArgCase == "-monoleft"
8705           || anArgCase == "-monolefteye"
8706           || anArgCase == "-perpsleft"
8707           || anArgCase == "-perpslefteye")
8708     {
8709       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
8710     }
8711     else if (anArgCase == "-right"
8712           || anArgCase == "-righteye"
8713           || anArgCase == "-monoright"
8714           || anArgCase == "-monorighteye"
8715           || anArgCase == "-perpsright")
8716     {
8717       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
8718     }
8719     else if (anArgCase == "-dist"
8720           || anArgCase == "-distance")
8721     {
8722       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8723       if (anArgValue != NULL
8724       && *anArgValue != '-')
8725       {
8726         ++anArgIter;
8727         aCamera->SetDistance (Draw::Atof (anArgValue));
8728         continue;
8729       }
8730       theDI << aCamera->Distance() << " ";
8731     }
8732     else if (anArgCase == "-iod")
8733     {
8734       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8735       if (anArgValue != NULL
8736       && *anArgValue != '-')
8737       {
8738         ++anArgIter;
8739         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
8740         continue;
8741       }
8742       theDI << aCamera->IOD() << " ";
8743     }
8744     else if (anArgCase == "-iodtype")
8745     {
8746       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8747       TCollection_AsciiString anValueCase (anArgValue);
8748       anValueCase.LowerCase();
8749       if (anValueCase == "abs"
8750        || anValueCase == "absolute")
8751       {
8752         ++anArgIter;
8753         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
8754         continue;
8755       }
8756       else if (anValueCase == "rel"
8757             || anValueCase == "relative")
8758       {
8759         ++anArgIter;
8760         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
8761         continue;
8762       }
8763       else if (*anArgValue != '-')
8764       {
8765         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
8766         return 1;
8767       }
8768       switch (aCamera->GetIODType())
8769       {
8770         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
8771         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
8772       }
8773     }
8774     else if (anArgCase == "-zfocus")
8775     {
8776       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8777       if (anArgValue != NULL
8778       && *anArgValue != '-')
8779       {
8780         ++anArgIter;
8781         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
8782         continue;
8783       }
8784       theDI << aCamera->ZFocus() << " ";
8785     }
8786     else if (anArgCase == "-zfocustype")
8787     {
8788       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
8789       TCollection_AsciiString anValueCase (anArgValue);
8790       anValueCase.LowerCase();
8791       if (anValueCase == "abs"
8792        || anValueCase == "absolute")
8793       {
8794         ++anArgIter;
8795         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
8796         continue;
8797       }
8798       else if (anValueCase == "rel"
8799             || anValueCase == "relative")
8800       {
8801         ++anArgIter;
8802         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
8803         continue;
8804       }
8805       else if (*anArgValue != '-')
8806       {
8807         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
8808         return 1;
8809       }
8810       switch (aCamera->ZFocusType())
8811       {
8812         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
8813         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
8814       }
8815     }
8816     else if (anArgCase == "-fov"
8817           || anArgCase == "-fovy")
8818     {
8819       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
8820       if (anArgValue != NULL
8821       && *anArgValue != '-')
8822       {
8823         ++anArgIter;
8824         aCamera->SetFOVy (Draw::Atof (anArgValue));
8825         continue;
8826       }
8827       theDI << aCamera->FOVy() << " ";
8828     }
8829     else
8830     {
8831       std::cout << "Error: unknown argument '" << anArg << "'\n";
8832       return 1;
8833     }
8834   }
8835
8836   aView->AutoZFit();
8837   aView->Redraw();
8838
8839   return 0;
8840 }
8841
8842 //! Parse stereo output mode
8843 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
8844                                          Graphic3d_StereoMode& theMode)
8845 {
8846   TCollection_AsciiString aFlag (theArg);
8847   aFlag.LowerCase();
8848   if (aFlag == "quadbuffer")
8849   {
8850     theMode = Graphic3d_StereoMode_QuadBuffer;
8851   }
8852   else if (aFlag == "anaglyph")
8853   {
8854     theMode = Graphic3d_StereoMode_Anaglyph;
8855   }
8856   else if (aFlag == "row"
8857         || aFlag == "rowinterlaced")
8858   {
8859     theMode = Graphic3d_StereoMode_RowInterlaced;
8860   }
8861   else if (aFlag == "col"
8862         || aFlag == "colinterlaced"
8863         || aFlag == "columninterlaced")
8864   {
8865     theMode = Graphic3d_StereoMode_ColumnInterlaced;
8866   }
8867   else if (aFlag == "chess"
8868         || aFlag == "chessboard")
8869   {
8870     theMode = Graphic3d_StereoMode_ChessBoard;
8871   }
8872   else if (aFlag == "sbs"
8873         || aFlag == "sidebyside")
8874   {
8875     theMode = Graphic3d_StereoMode_SideBySide;
8876   }
8877   else if (aFlag == "ou"
8878         || aFlag == "overunder")
8879   {
8880     theMode = Graphic3d_StereoMode_OverUnder;
8881   }
8882   else if (aFlag == "pageflip"
8883         || aFlag == "softpageflip")
8884   {
8885     theMode = Graphic3d_StereoMode_SoftPageFlip;
8886   }
8887   else
8888   {
8889     return Standard_False;
8890   }
8891   return Standard_True;
8892 }
8893
8894 //! Parse anaglyph filter
8895 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
8896                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
8897 {
8898   TCollection_AsciiString aFlag (theArg);
8899   aFlag.LowerCase();
8900   if (aFlag == "redcyansimple")
8901   {
8902     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
8903   }
8904   else if (aFlag == "redcyan"
8905         || aFlag == "redcyanoptimized")
8906   {
8907     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
8908   }
8909   else if (aFlag == "yellowbluesimple")
8910   {
8911     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
8912   }
8913   else if (aFlag == "yellowblue"
8914         || aFlag == "yellowblueoptimized")
8915   {
8916     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
8917   }
8918   else if (aFlag == "greenmagenta"
8919         || aFlag == "greenmagentasimple")
8920   {
8921     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
8922   }
8923   else
8924   {
8925     return Standard_False;
8926   }
8927   return Standard_True;
8928 }
8929
8930 //==============================================================================
8931 //function : VStereo
8932 //purpose  :
8933 //==============================================================================
8934
8935 static int VStereo (Draw_Interpretor& theDI,
8936                     Standard_Integer  theArgNb,
8937                     const char**      theArgVec)
8938 {
8939   Handle(V3d_View) aView = ViewerTest::CurrentView();
8940   if (theArgNb < 2)
8941   {
8942     if (aView.IsNull())
8943     {
8944       std::cout << "Error: no active viewer!\n";
8945       return 0;
8946     }
8947
8948     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
8949     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
8950     if (isActive)
8951     {
8952       TCollection_AsciiString aMode;
8953       switch (aView->RenderingParams().StereoMode)
8954       {
8955         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
8956         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
8957         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
8958         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
8959         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
8960         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
8961         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
8962         case Graphic3d_StereoMode_Anaglyph  :
8963           aMode = "anaglyph";
8964           switch (aView->RenderingParams().AnaglyphFilter)
8965           {
8966             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
8967             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
8968             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
8969             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
8970             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
8971             default: break;
8972           }
8973         default: break;
8974       }
8975       theDI << "Mode " << aMode << "\n";
8976     }
8977     return 0;
8978   }
8979
8980   Handle(Graphic3d_Camera) aCamera;
8981   Graphic3d_RenderingParams*   aParams   = NULL;
8982   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
8983   if (!aView.IsNull())
8984   {
8985     aParams   = &aView->ChangeRenderingParams();
8986     aMode     = aParams->StereoMode;
8987     aCamera   = aView->Camera();
8988   }
8989
8990   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
8991   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
8992   {
8993     Standard_CString        anArg = theArgVec[anArgIter];
8994     TCollection_AsciiString aFlag (anArg);
8995     aFlag.LowerCase();
8996     if (anUpdateTool.parseRedrawMode (aFlag))
8997     {
8998       continue;
8999     }
9000     else if (aFlag == "0"
9001           || aFlag == "off")
9002     {
9003       if (++anArgIter < theArgNb)
9004       {
9005         std::cout << "Error: wrong number of arguments!\n";
9006         return 1;
9007       }
9008
9009       if (!aCamera.IsNull()
9010        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
9011       {
9012         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9013       }
9014       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
9015       return 0;
9016     }
9017     else if (aFlag == "1"
9018           || aFlag == "on")
9019     {
9020       if (++anArgIter < theArgNb)
9021       {
9022         std::cout << "Error: wrong number of arguments!\n";
9023         return 1;
9024       }
9025
9026       if (!aCamera.IsNull())
9027       {
9028         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9029       }
9030       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9031       return 0;
9032     }
9033     else if (aFlag == "-reverse"
9034           || aFlag == "-reversed"
9035           || aFlag == "-swap")
9036     {
9037       Standard_Boolean toEnable = Standard_True;
9038       if (++anArgIter < theArgNb
9039       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
9040       {
9041         --anArgIter;
9042       }
9043       aParams->ToReverseStereo = toEnable;
9044     }
9045     else if (aFlag == "-noreverse"
9046           || aFlag == "-noswap")
9047     {
9048       Standard_Boolean toDisable = Standard_True;
9049       if (++anArgIter < theArgNb
9050       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
9051       {
9052         --anArgIter;
9053       }
9054       aParams->ToReverseStereo = !toDisable;
9055     }
9056     else if (aFlag == "-mode"
9057           || aFlag == "-stereomode")
9058     {
9059       if (++anArgIter >= theArgNb
9060       || !parseStereoMode (theArgVec[anArgIter], aMode))
9061       {
9062         std::cout << "Error: syntax error at '" << anArg << "'\n";
9063         return 1;
9064       }
9065
9066       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9067       {
9068         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9069       }
9070     }
9071     else if (aFlag == "-anaglyph"
9072           || aFlag == "-anaglyphfilter")
9073     {
9074       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9075       if (++anArgIter >= theArgNb
9076       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9077       {
9078         std::cout << "Error: syntax error at '" << anArg << "'\n";
9079         return 1;
9080       }
9081
9082       aMode = Graphic3d_StereoMode_Anaglyph;
9083       aParams->AnaglyphFilter = aFilter;
9084     }
9085     else if (parseStereoMode (anArg, aMode)) // short syntax
9086     {
9087       if (aMode == Graphic3d_StereoMode_QuadBuffer)
9088       {
9089         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
9090       }
9091     }
9092     else
9093     {
9094       std::cout << "Error: syntax error at '" << anArg << "'\n";
9095       return 1;
9096     }
9097   }
9098
9099   if (!aView.IsNull())
9100   {
9101     aParams->StereoMode = aMode;
9102     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9103   }
9104   return 0;
9105 }
9106
9107 //===============================================================================================
9108 //function : VDefaults
9109 //purpose  :
9110 //===============================================================================================
9111 static int VDefaults (Draw_Interpretor& theDi,
9112                       Standard_Integer  theArgsNb,
9113                       const char**      theArgVec)
9114 {
9115   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9116   if (aCtx.IsNull())
9117   {
9118     std::cerr << "No active viewer!\n";
9119     return 1;
9120   }
9121
9122   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9123   if (theArgsNb < 2)
9124   {
9125     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9126     {
9127       theDi << "DeflType:           relative\n"
9128             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
9129     }
9130     else
9131     {
9132       theDi << "DeflType:           absolute\n"
9133             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9134     }
9135     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
9136     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
9137     return 0;
9138   }
9139
9140   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9141   {
9142     TCollection_AsciiString anArg (theArgVec[anArgIter]);
9143     anArg.UpperCase();
9144     if (anArg == "-ABSDEFL"
9145      || anArg == "-ABSOLUTEDEFLECTION"
9146      || anArg == "-DEFL"
9147      || anArg == "-DEFLECTION")
9148     {
9149       if (++anArgIter >= theArgsNb)
9150       {
9151         std::cout << "Error: wrong syntax at " << anArg << "\n";
9152         return 1;
9153       }
9154       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
9155       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
9156     }
9157     else if (anArg == "-RELDEFL"
9158           || anArg == "-RELATIVEDEFLECTION"
9159           || anArg == "-DEVCOEFF"
9160           || anArg == "-DEVIATIONCOEFF"
9161           || anArg == "-DEVIATIONCOEFFICIENT")
9162     {
9163       if (++anArgIter >= theArgsNb)
9164       {
9165         std::cout << "Error: wrong syntax at " << anArg << "\n";
9166         return 1;
9167       }
9168       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
9169       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
9170     }
9171     else if (anArg == "-ANGDEFL"
9172           || anArg == "-ANGULARDEFL"
9173           || anArg == "-ANGULARDEFLECTION")
9174     {
9175       if (++anArgIter >= theArgsNb)
9176       {
9177         std::cout << "Error: wrong syntax at " << anArg << "\n";
9178         return 1;
9179       }
9180       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
9181       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
9182     }
9183     else if (anArg == "-AUTOTR"
9184           || anArg == "-AUTOTRIANG"
9185           || anArg == "-AUTOTRIANGULATION")
9186     {
9187       if (++anArgIter >= theArgsNb)
9188       {
9189         std::cout << "Error: wrong syntax at " << anArg << "\n";
9190         return 1;
9191       }
9192       TCollection_AsciiString aValue (theArgVec[anArgIter]);
9193       aValue.LowerCase();
9194       if (aValue == "on"
9195        || aValue == "1")
9196       {
9197         aDefParams->SetAutoTriangulation (Standard_True);
9198       }
9199       else if (aValue == "off"
9200             || aValue == "0")
9201       {
9202         aDefParams->SetAutoTriangulation (Standard_False);
9203       }
9204     }
9205     else
9206     {
9207       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
9208     }
9209   }
9210
9211   return 0;
9212 }
9213
9214 //! Auxiliary method
9215 inline void addLight (const Handle(V3d_Light)& theLightNew,
9216                       const Graphic3d_ZLayerId theLayer,
9217                       const Standard_Boolean   theIsGlobal)
9218 {
9219   if (theLightNew.IsNull())
9220   {
9221     return;
9222   }
9223
9224   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9225   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
9226   {
9227     aViewer->AddLight (theLightNew);
9228     if (theIsGlobal)
9229     {
9230       aViewer->SetLightOn (theLightNew);
9231     }
9232     else
9233     {
9234       ViewerTest::CurrentView()->SetLightOn (theLightNew);
9235     }
9236   }
9237   else
9238   {
9239     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
9240     if (aSettings.Lights().IsNull())
9241     {
9242       aSettings.SetLights (new Graphic3d_LightSet());
9243     }
9244     aSettings.Lights()->Add (theLightNew);
9245     aViewer->SetZLayerSettings (theLayer, aSettings);
9246   }
9247 }
9248
9249 //! Auxiliary method
9250 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
9251 {
9252   TCollection_AsciiString anArgNextCase (theArgNext);
9253   anArgNextCase.UpperCase();
9254   if (anArgNextCase.Length() > 5
9255    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
9256   {
9257     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
9258   }
9259   else
9260   {
9261     return theArgNext.IntegerValue();
9262   }
9263 }
9264
9265 //===============================================================================================
9266 //function : VLight
9267 //purpose  :
9268 //===============================================================================================
9269 static int VLight (Draw_Interpretor& theDi,
9270                    Standard_Integer  theArgsNb,
9271                    const char**      theArgVec)
9272 {
9273   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
9274   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
9275   if (aView.IsNull()
9276    || aViewer.IsNull())
9277   {
9278     std::cerr << "No active viewer!\n";
9279     return 1;
9280   }
9281
9282   Standard_Real anXYZ[3]   = {};
9283   Standard_Real anAtten[2] = {};
9284   if (theArgsNb < 2)
9285   {
9286     // print lights info
9287     Standard_Integer aLightId = 0;
9288     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
9289     {
9290       Handle(V3d_Light) aLight = aLightIter.Value();
9291       const Quantity_Color aColor = aLight->Color();
9292       theDi << "Light #" << aLightId
9293             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
9294             << " [" << aLight->GetId() << "]" << "\n";
9295       switch (aLight->Type())
9296       {
9297         case V3d_AMBIENT:
9298         {
9299           theDi << "  Type:       Ambient\n";
9300           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9301           break;
9302         }
9303         case V3d_DIRECTIONAL:
9304         {
9305           theDi << "  Type:       Directional\n";
9306           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9307           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9308           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9309           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9310           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9311           break;
9312         }
9313         case V3d_POSITIONAL:
9314         {
9315           theDi << "  Type:       Positional\n";
9316           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9317           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9318           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
9319           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9320           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9321           aLight->Attenuation (anAtten[0], anAtten[1]);
9322           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9323           break;
9324         }
9325         case V3d_SPOT:
9326         {
9327           theDi << "  Type:       Spot\n";
9328           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
9329           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
9330           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
9331           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9332           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
9333           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
9334           aLight->Attenuation (anAtten[0], anAtten[1]);
9335           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
9336           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
9337           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
9338           break;
9339         }
9340         default:
9341         {
9342           theDi << "  Type:       UNKNOWN\n";
9343           break;
9344         }
9345       }
9346       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
9347     }
9348   }
9349
9350   Handle(V3d_Light) aLightNew;
9351   Handle(V3d_Light) aLightOld;
9352   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
9353   Standard_Boolean  isGlobal = Standard_True;
9354   Standard_Boolean  toCreate = Standard_False;
9355   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9356   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9357   {
9358     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
9359
9360     TCollection_AsciiString aName, aValue;
9361     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9362     TCollection_AsciiString anArgCase (anArg);
9363     anArgCase.UpperCase();
9364     if (anUpdateTool.parseRedrawMode (anArg))
9365     {
9366       continue;
9367     }
9368
9369     if (anArgCase.IsEqual ("NEW")
9370      || anArgCase.IsEqual ("ADD")
9371      || anArgCase.IsEqual ("CREATE")
9372      || anArgCase.IsEqual ("-NEW")
9373      || anArgCase.IsEqual ("-ADD")
9374      || anArgCase.IsEqual ("-CREATE"))
9375     {
9376       toCreate = Standard_True;
9377     }
9378     else if (anArgCase.IsEqual ("-LAYER")
9379           || anArgCase.IsEqual ("-ZLAYER"))
9380     {
9381       if (++anArgIt >= theArgsNb)
9382       {
9383         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9384         return 1;
9385       }
9386
9387       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
9388       aValStr.LowerCase();
9389       if (aValStr == "default"
9390        || aValStr == "def")
9391       {
9392         aLayer = Graphic3d_ZLayerId_Default;
9393       }
9394       else if (aValStr == "top")
9395       {
9396         aLayer = Graphic3d_ZLayerId_Top;
9397       }
9398       else if (aValStr == "topmost")
9399       {
9400         aLayer = Graphic3d_ZLayerId_Topmost;
9401       }
9402       else if (aValStr == "toposd"
9403             || aValStr == "osd")
9404       {
9405         aLayer = Graphic3d_ZLayerId_TopOSD;
9406       }
9407       else if (aValStr == "botosd"
9408             || aValStr == "bottom")
9409       {
9410         aLayer = Graphic3d_ZLayerId_BotOSD;
9411       }
9412       else if (aValStr.IsIntegerValue())
9413       {
9414         aLayer = Draw::Atoi (theArgVec[anArgIt]);
9415       }
9416       else
9417       {
9418         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
9419         return 1;
9420       }
9421     }
9422     else if (anArgCase.IsEqual ("GLOB")
9423           || anArgCase.IsEqual ("GLOBAL")
9424           || anArgCase.IsEqual ("-GLOB")
9425           || anArgCase.IsEqual ("-GLOBAL"))
9426     {
9427       isGlobal = Standard_True;
9428     }
9429     else if (anArgCase.IsEqual ("LOC")
9430           || anArgCase.IsEqual ("LOCAL")
9431           || anArgCase.IsEqual ("-LOC")
9432           || anArgCase.IsEqual ("-LOCAL"))
9433     {
9434       isGlobal = Standard_False;
9435     }
9436     else if (anArgCase.IsEqual ("DEF")
9437           || anArgCase.IsEqual ("DEFAULTS")
9438           || anArgCase.IsEqual ("-DEF")
9439           || anArgCase.IsEqual ("-DEFAULTS"))
9440     {
9441       toCreate = Standard_False;
9442       aViewer->SetDefaultLights();
9443     }
9444     else if (anArgCase.IsEqual ("CLR")
9445           || anArgCase.IsEqual ("CLEAR")
9446           || anArgCase.IsEqual ("-CLR")
9447           || anArgCase.IsEqual ("-CLEAR"))
9448     {
9449       toCreate = Standard_False;
9450
9451       TColStd_SequenceOfInteger aLayers;
9452       aViewer->GetAllZLayers (aLayers);
9453       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9454       {
9455         if (aLayeriter.Value() == aLayer
9456          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9457         {
9458           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9459           aSettings.SetLights (Handle(Graphic3d_LightSet)());
9460           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9461           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9462           {
9463             break;
9464           }
9465         }
9466       }
9467
9468       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9469       {
9470         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
9471         {
9472           Handle(V3d_Light) aLight = aLightIter.Value();
9473           aViewer->DelLight (aLight);
9474           aLightIter = aView->ActiveLightIterator();
9475         }
9476       }
9477     }
9478     else if (anArgCase.IsEqual ("AMB")
9479           || anArgCase.IsEqual ("AMBIENT")
9480           || anArgCase.IsEqual ("AMBLIGHT"))
9481     {
9482       if (!toCreate)
9483       {
9484         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9485         return 1;
9486       }
9487
9488       addLight (aLightNew, aLayer, isGlobal);
9489       toCreate  = Standard_False;
9490       aLightNew = new V3d_AmbientLight();
9491     }
9492     else if (anArgCase.IsEqual ("DIRECTIONAL")
9493           || anArgCase.IsEqual ("DIRLIGHT"))
9494     {
9495       if (!toCreate)
9496       {
9497         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9498         return 1;
9499       }
9500
9501       addLight (aLightNew, aLayer, isGlobal);
9502       toCreate  = Standard_False;
9503       aLightNew = new V3d_DirectionalLight();
9504     }
9505     else if (anArgCase.IsEqual ("SPOT")
9506           || anArgCase.IsEqual ("SPOTLIGHT"))
9507     {
9508       if (!toCreate)
9509       {
9510         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9511         return 1;
9512       }
9513
9514       addLight (aLightNew, aLayer, isGlobal);
9515       toCreate  = Standard_False;
9516       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
9517     }
9518     else if (anArgCase.IsEqual ("POSLIGHT")
9519           || anArgCase.IsEqual ("POSITIONAL"))
9520     {
9521       if (!toCreate)
9522       {
9523         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9524         return 1;
9525       }
9526
9527       addLight (aLightNew, aLayer, isGlobal);
9528       toCreate  = Standard_False;
9529       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
9530     }
9531     else if (anArgCase.IsEqual ("CHANGE")
9532           || anArgCase.IsEqual ("-CHANGE"))
9533     {
9534       if (++anArgIt >= theArgsNb)
9535       {
9536         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9537         return 1;
9538       }
9539
9540       addLight (aLightNew, aLayer, isGlobal);
9541       aLightNew.Nullify();
9542       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
9543       Standard_Integer aLightIt = 0;
9544       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9545       {
9546         if (aLightIt == aLightId)
9547         {
9548           aLightOld = aLightIter.Value();
9549           break;
9550         }
9551       }
9552
9553       if (aLightOld.IsNull())
9554       {
9555         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
9556         return 1;
9557       }
9558     }
9559     else if (anArgCase.IsEqual ("DEL")
9560           || anArgCase.IsEqual ("DELETE")
9561           || anArgCase.IsEqual ("-DEL")
9562           || anArgCase.IsEqual ("-DELETE"))
9563     {
9564       Handle(V3d_Light) aLightDel;
9565       if (++anArgIt >= theArgsNb)
9566       {
9567         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9568         return 1;
9569       }
9570
9571       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9572       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
9573       Standard_Integer aLightIt = 0;
9574       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
9575       {
9576         aLightDel = aLightIter.Value();
9577         if (aLightIt == aLightDelId)
9578         {
9579           break;
9580         }
9581       }
9582       if (aLightDel.IsNull())
9583       {
9584         continue;
9585       }
9586
9587       TColStd_SequenceOfInteger aLayers;
9588       aViewer->GetAllZLayers (aLayers);
9589       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
9590       {
9591         if (aLayeriter.Value() == aLayer
9592          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
9593         {
9594           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
9595           if (!aSettings.Lights().IsNull())
9596           {
9597             aSettings.Lights()->Remove (aLightDel);
9598             if (aSettings.Lights()->IsEmpty())
9599             {
9600               aSettings.SetLights (Handle(Graphic3d_LightSet)());
9601             }
9602           }
9603           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
9604           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
9605           {
9606             break;
9607           }
9608         }
9609       }
9610
9611       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
9612       {
9613         aViewer->DelLight (aLightDel);
9614       }
9615     }
9616     else if (anArgCase.IsEqual ("COLOR")
9617           || anArgCase.IsEqual ("COLOUR")
9618           || anArgCase.IsEqual ("-COLOR")
9619           || anArgCase.IsEqual ("-COLOUR"))
9620     {
9621       if (++anArgIt >= theArgsNb
9622        || aLightCurr.IsNull())
9623       {
9624         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9625         return 1;
9626       }
9627
9628       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
9629       anArgNext.UpperCase();
9630       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
9631       aLightCurr->SetColor (aColor);
9632     }
9633     else if (anArgCase.IsEqual ("POS")
9634           || anArgCase.IsEqual ("POSITION")
9635           || anArgCase.IsEqual ("-POS")
9636           || anArgCase.IsEqual ("-POSITION"))
9637     {
9638       if ((anArgIt + 3) >= theArgsNb
9639        || aLightCurr.IsNull()
9640        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9641         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9642       {
9643         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9644         return 1;
9645       }
9646
9647       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9648       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9649       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9650       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
9651     }
9652     else if (anArgCase.IsEqual ("DIR")
9653           || anArgCase.IsEqual ("DIRECTION")
9654           || anArgCase.IsEqual ("-DIR")
9655           || anArgCase.IsEqual ("-DIRECTION"))
9656     {
9657       if ((anArgIt + 3) >= theArgsNb
9658        || aLightCurr.IsNull()
9659        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
9660         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9661       {
9662         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9663         return 1;
9664       }
9665
9666       anXYZ[0] = Atof (theArgVec[++anArgIt]);
9667       anXYZ[1] = Atof (theArgVec[++anArgIt]);
9668       anXYZ[2] = Atof (theArgVec[++anArgIt]);
9669       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
9670     }
9671     else if (anArgCase.IsEqual ("SM")
9672           || anArgCase.IsEqual ("SMOOTHNESS")
9673           || anArgCase.IsEqual ("-SM")
9674           || anArgCase.IsEqual ("-SMOOTHNESS"))
9675     {
9676       if (++anArgIt >= theArgsNb
9677        || aLightCurr.IsNull())
9678       {
9679         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9680         return 1;
9681       }
9682
9683       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9684       if (Abs (aSmoothness) <= ShortRealEpsilon())
9685       {
9686         aLightCurr->SetIntensity (1.f);
9687       }
9688       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
9689       {
9690         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
9691       }
9692       else
9693       {
9694         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
9695         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
9696       }
9697
9698       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
9699       {
9700         aLightCurr->SetSmoothRadius (aSmoothness);
9701       }
9702       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
9703       {
9704         aLightCurr->SetSmoothAngle (aSmoothness);
9705       }
9706     }
9707     else if (anArgCase.IsEqual ("INT")
9708           || anArgCase.IsEqual ("INTENSITY")
9709           || anArgCase.IsEqual ("-INT")
9710           || anArgCase.IsEqual ("-INTENSITY"))
9711     {
9712       if (++anArgIt >= theArgsNb
9713        || aLightCurr.IsNull())
9714       {
9715         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9716         return 1;
9717       }
9718
9719       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9720       aLightCurr->SetIntensity (aIntensity);
9721     }
9722     else if (anArgCase.IsEqual ("ANG")
9723           || anArgCase.IsEqual ("ANGLE")
9724           || anArgCase.IsEqual ("-ANG")
9725           || anArgCase.IsEqual ("-ANGLE"))
9726     {
9727       if (++anArgIt >= theArgsNb
9728        || aLightCurr.IsNull()
9729        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
9730       {
9731         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9732         return 1;
9733       }
9734
9735       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
9736       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
9737     }
9738     else if (anArgCase.IsEqual ("CONSTATTEN")
9739           || anArgCase.IsEqual ("CONSTATTENUATION")
9740           || anArgCase.IsEqual ("-CONSTATTEN")
9741           || anArgCase.IsEqual ("-CONSTATTENUATION"))
9742     {
9743       if (++anArgIt >= theArgsNb
9744        || aLightCurr.IsNull()
9745        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9746         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9747       {
9748         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9749         return 1;
9750       }
9751
9752       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
9753       anAtten[0] = Atof (theArgVec[anArgIt]);
9754       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
9755     }
9756     else if (anArgCase.IsEqual ("LINATTEN")
9757           || anArgCase.IsEqual ("LINEARATTEN")
9758           || anArgCase.IsEqual ("LINEARATTENUATION")
9759           || anArgCase.IsEqual ("-LINATTEN")
9760           || anArgCase.IsEqual ("-LINEARATTEN")
9761           || anArgCase.IsEqual ("-LINEARATTENUATION"))
9762     {
9763       if (++anArgIt >= theArgsNb
9764        || aLightCurr.IsNull()
9765        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
9766         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
9767       {
9768         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9769         return 1;
9770       }
9771
9772       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
9773       anAtten[1] = Atof (theArgVec[anArgIt]);
9774       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
9775     }
9776     else if (anArgCase.IsEqual ("EXP")
9777           || anArgCase.IsEqual ("EXPONENT")
9778           || anArgCase.IsEqual ("SPOTEXP")
9779           || anArgCase.IsEqual ("SPOTEXPONENT")
9780           || anArgCase.IsEqual ("-EXP")
9781           || anArgCase.IsEqual ("-EXPONENT")
9782           || anArgCase.IsEqual ("-SPOTEXP")
9783           || anArgCase.IsEqual ("-SPOTEXPONENT"))
9784     {
9785       if (++anArgIt >= theArgsNb
9786        || aLightCurr.IsNull()
9787        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
9788       {
9789         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9790         return 1;
9791       }
9792
9793       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
9794     }
9795     else if (anArgCase.IsEqual ("HEAD")
9796           || anArgCase.IsEqual ("HEADLIGHT")
9797           || anArgCase.IsEqual ("-HEAD")
9798           || anArgCase.IsEqual ("-HEADLIGHT"))
9799     {
9800       if (aLightCurr.IsNull()
9801        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
9802       {
9803         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
9804         return 1;
9805       }
9806
9807       Standard_Boolean isHeadLight = Standard_True;
9808       if (anArgIt + 1 < theArgsNb
9809        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
9810       {
9811         ++anArgIt;
9812       }
9813       aLightCurr->SetHeadlight (isHeadLight);
9814     }
9815     else
9816     {
9817       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
9818     }
9819   }
9820
9821   addLight (aLightNew, aLayer, isGlobal);
9822   return 0;
9823 }
9824
9825 //! Read Graphic3d_RenderingParams::PerfCounters flag.
9826 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
9827                                             Standard_Boolean& theToReset,
9828                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
9829                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
9830 {
9831   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
9832   TCollection_AsciiString aVal = theValue;
9833   Standard_Boolean toReverse = Standard_False;
9834   if (aVal == "none")
9835   {
9836     theToReset = Standard_True;
9837     return Standard_True;
9838   }
9839   else if (aVal.StartsWith ("-"))
9840   {
9841     toReverse = Standard_True;
9842     aVal = aVal.SubString (2, aVal.Length());
9843   }
9844   else if (aVal.StartsWith ("no"))
9845   {
9846     toReverse = Standard_True;
9847     aVal = aVal.SubString (3, aVal.Length());
9848   }
9849   else if (aVal.StartsWith ("+"))
9850   {
9851     aVal = aVal.SubString (2, aVal.Length());
9852   }
9853   else
9854   {
9855     theToReset = Standard_True;
9856   }
9857
9858   if (     aVal == "fps"
9859         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
9860   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
9861   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
9862   else if (aVal == "structs"
9863         || aVal == "structures"
9864         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
9865   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
9866   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
9867   else if (aVal == "tris"
9868         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
9869   else if (aVal == "pnts"
9870         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
9871   else if (aVal == "mem"
9872         || aVal == "gpumem"
9873         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
9874   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
9875   else if (aVal == "extended"
9876         || aVal == "verbose"
9877         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
9878   else
9879   {
9880     return Standard_False;
9881   }
9882
9883   if (toReverse)
9884   {
9885     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
9886   }
9887   else
9888   {
9889     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
9890   }
9891   return Standard_True;
9892 }
9893
9894 //! Read Graphic3d_RenderingParams::PerfCounters flags.
9895 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
9896                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
9897 {
9898   TCollection_AsciiString aValue = theValue;
9899   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
9900   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
9901   Standard_Boolean toReset = Standard_False;
9902   for (;;)
9903   {
9904     Standard_Integer aSplitPos = aValue.Search ("|");
9905     if (aSplitPos <= 0)
9906     {
9907       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
9908       {
9909         return Standard_False;
9910       }
9911       if (toReset)
9912       {
9913         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
9914       }
9915       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
9916       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
9917       return Standard_True;
9918     }
9919
9920     if (aSplitPos > 1)
9921     {
9922       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
9923       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
9924       {
9925         return Standard_False;
9926       }
9927     }
9928     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
9929   }
9930 }
9931
9932 //=======================================================================
9933 //function : VRenderParams
9934 //purpose  : Enables/disables rendering features
9935 //=======================================================================
9936
9937 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
9938                                        Standard_Integer  theArgNb,
9939                                        const char**      theArgVec)
9940 {
9941   Handle(V3d_View) aView = ViewerTest::CurrentView();
9942   if (aView.IsNull())
9943   {
9944     std::cerr << "Error: no active viewer!\n";
9945     return 1;
9946   }
9947
9948   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
9949   TCollection_AsciiString aCmdName (theArgVec[0]);
9950   aCmdName.LowerCase();
9951   if (aCmdName == "vraytrace")
9952   {
9953     if (theArgNb == 1)
9954     {
9955       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
9956       return 0;
9957     }
9958     else if (theArgNb == 2)
9959     {
9960       TCollection_AsciiString aValue (theArgVec[1]);
9961       aValue.LowerCase();
9962       if (aValue == "on"
9963        || aValue == "1")
9964       {
9965         aParams.Method = Graphic3d_RM_RAYTRACING;
9966         aView->Redraw();
9967         return 0;
9968       }
9969       else if (aValue == "off"
9970             || aValue == "0")
9971       {
9972         aParams.Method = Graphic3d_RM_RASTERIZATION;
9973         aView->Redraw();
9974         return 0;
9975       }
9976       else
9977       {
9978         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
9979         return 1;
9980       }
9981     }
9982     else
9983     {
9984       std::cout << "Error: wrong number of arguments\n";
9985       return 1;
9986     }
9987   }
9988
9989   if (theArgNb < 2)
9990   {
9991     theDI << "renderMode:  ";
9992     switch (aParams.Method)
9993     {
9994       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
9995       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
9996     }
9997     theDI << "\n";
9998     theDI << "transparency:  ";
9999     switch (aParams.TransparencyMethod)
10000     {
10001       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10002       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10003                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
10004     }
10005     theDI << "\n";
10006     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
10007     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
10008     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
10009     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
10010     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
10011     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
10012     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
10013     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10014     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
10015     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
10016     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
10017     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
10018     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
10019     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
10020     theDI << "shadingModel: ";
10021     switch (aView->ShadingModel())
10022     {
10023       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
10024       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
10025       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
10026       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
10027       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
10028     }
10029     {
10030       theDI << "perfCounters:";
10031       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10032       {
10033         theDI << " fps";
10034       }
10035       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10036       {
10037         theDI << " cpu";
10038       }
10039       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10040       {
10041         theDI << " structs";
10042       }
10043       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10044       {
10045         theDI << " groups";
10046       }
10047       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10048       {
10049         theDI << " arrays";
10050       }
10051       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10052       {
10053         theDI << " tris";
10054       }
10055       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10056       {
10057         theDI << " pnts";
10058       }
10059       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10060       {
10061         theDI << " gpumem";
10062       }
10063       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10064       {
10065         theDI << " none";
10066       }
10067       theDI << "\n";
10068     }
10069     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
10070     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
10071     theDI << "\n";
10072     return 0;
10073   }
10074
10075   Standard_Boolean toPrint = Standard_False;
10076   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10077   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10078   {
10079     Standard_CString        anArg (theArgVec[anArgIter]);
10080     TCollection_AsciiString aFlag (anArg);
10081     aFlag.LowerCase();
10082     if (anUpdateTool.parseRedrawMode (aFlag))
10083     {
10084       continue;
10085     }
10086     else if (aFlag == "-echo"
10087           || aFlag == "-print")
10088     {
10089       toPrint = Standard_True;
10090       anUpdateTool.Invalidate();
10091     }
10092     else if (aFlag == "-mode"
10093           || aFlag == "-rendermode"
10094           || aFlag == "-render_mode")
10095     {
10096       if (toPrint)
10097       {
10098         switch (aParams.Method)
10099         {
10100           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10101           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
10102         }
10103         continue;
10104       }
10105       else
10106       {
10107         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10108         return 1;
10109       }
10110     }
10111     else if (aFlag == "-ray"
10112           || aFlag == "-raytrace")
10113     {
10114       if (toPrint)
10115       {
10116         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
10117         continue;
10118       }
10119
10120       aParams.Method = Graphic3d_RM_RAYTRACING;
10121     }
10122     else if (aFlag == "-rast"
10123           || aFlag == "-raster"
10124           || aFlag == "-rasterization")
10125     {
10126       if (toPrint)
10127       {
10128         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
10129         continue;
10130       }
10131
10132       aParams.Method = Graphic3d_RM_RASTERIZATION;
10133     }
10134     else if (aFlag == "-msaa")
10135     {
10136       if (toPrint)
10137       {
10138         theDI << aParams.NbMsaaSamples << " ";
10139         continue;
10140       }
10141       else if (++anArgIter >= theArgNb)
10142       {
10143         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10144         return 1;
10145       }
10146
10147       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
10148       if (aNbSamples < 0)
10149       {
10150         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
10151         return 1;
10152       }
10153       else
10154       {
10155         aParams.NbMsaaSamples = aNbSamples;
10156       }
10157     }
10158     else if (aFlag == "-oit")
10159     {
10160       if (toPrint)
10161       {
10162         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
10163         {
10164           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
10165         }
10166         else
10167         {
10168           theDI << "off" << " ";
10169         }
10170         continue;
10171       }
10172       else if (++anArgIter >= theArgNb)
10173       {
10174         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10175         return 1;
10176       }
10177
10178       TCollection_AsciiString aParam = theArgVec[anArgIter];
10179       aParam.LowerCase();
10180       if (aParam.IsRealValue())
10181       {
10182         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
10183         if (aWeight < 0.f || aWeight > 1.f)
10184         {
10185           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
10186           return 1;
10187         }
10188
10189         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
10190         aParams.OitDepthFactor     = aWeight;
10191       }
10192       else if (aParam == "off")
10193       {
10194         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
10195       }
10196       else
10197       {
10198         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10199         return 1;
10200       }
10201     }
10202     else if (aFlag == "-depthprepass")
10203     {
10204       if (toPrint)
10205       {
10206         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
10207         continue;
10208       }
10209       aParams.ToEnableDepthPrepass = Standard_True;
10210       if (anArgIter + 1 < theArgNb
10211        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
10212       {
10213         ++anArgIter;
10214       }
10215     }
10216     else if (aFlag == "-samplealphatocoverage"
10217           || aFlag == "-alphatocoverage")
10218     {
10219       if (toPrint)
10220       {
10221         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
10222         continue;
10223       }
10224       aParams.ToEnableAlphaToCoverage = Standard_True;
10225       if (anArgIter + 1 < theArgNb
10226        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
10227       {
10228         ++anArgIter;
10229       }
10230     }
10231     else if (aFlag == "-rendscale"
10232           || aFlag == "-renderscale"
10233           || aFlag == "-renderresolutionscale")
10234     {
10235       if (toPrint)
10236       {
10237         theDI << aParams.RenderResolutionScale << " ";
10238         continue;
10239       }
10240       else if (++anArgIter >= theArgNb)
10241       {
10242         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10243         return 1;
10244       }
10245
10246       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
10247       if (aScale < 0.01)
10248       {
10249         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
10250         return 1;
10251       }
10252       else
10253       {
10254         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
10255       }
10256     }
10257     else if (aFlag == "-raydepth"
10258           || aFlag == "-ray_depth")
10259     {
10260       if (toPrint)
10261       {
10262         theDI << aParams.RaytracingDepth << " ";
10263         continue;
10264       }
10265       else if (++anArgIter >= theArgNb)
10266       {
10267         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10268         return 1;
10269       }
10270
10271       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
10272
10273       // We allow RaytracingDepth be more than 10 in case of GI enabled
10274       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
10275       {
10276         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
10277         return 1;
10278       }
10279       else
10280       {
10281         aParams.RaytracingDepth = aDepth;
10282       }
10283     }
10284     else if (aFlag == "-shad"
10285           || aFlag == "-shadows")
10286     {
10287       if (toPrint)
10288       {
10289         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
10290         continue;
10291       }
10292
10293       Standard_Boolean toEnable = Standard_True;
10294       if (++anArgIter < theArgNb
10295       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10296       {
10297         --anArgIter;
10298       }
10299       aParams.IsShadowEnabled = toEnable;
10300     }
10301     else if (aFlag == "-refl"
10302           || aFlag == "-reflections")
10303     {
10304       if (toPrint)
10305       {
10306         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
10307         continue;
10308       }
10309
10310       Standard_Boolean toEnable = Standard_True;
10311       if (++anArgIter < theArgNb
10312       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10313       {
10314         --anArgIter;
10315       }
10316       aParams.IsReflectionEnabled = toEnable;
10317     }
10318     else if (aFlag == "-fsaa")
10319     {
10320       if (toPrint)
10321       {
10322         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
10323         continue;
10324       }
10325
10326       Standard_Boolean toEnable = Standard_True;
10327       if (++anArgIter < theArgNb
10328       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10329       {
10330         --anArgIter;
10331       }
10332       aParams.IsAntialiasingEnabled = toEnable;
10333     }
10334     else if (aFlag == "-gleam")
10335     {
10336       if (toPrint)
10337       {
10338         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
10339         continue;
10340       }
10341
10342       Standard_Boolean toEnable = Standard_True;
10343       if (++anArgIter < theArgNb
10344       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10345       {
10346         --anArgIter;
10347       }
10348       aParams.IsTransparentShadowEnabled = toEnable;
10349     }
10350     else if (aFlag == "-gi")
10351     {
10352       if (toPrint)
10353       {
10354         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
10355         continue;
10356       }
10357
10358       Standard_Boolean toEnable = Standard_True;
10359       if (++anArgIter < theArgNb
10360       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10361       {
10362         --anArgIter;
10363       }
10364       aParams.IsGlobalIlluminationEnabled = toEnable;
10365       if (!toEnable)
10366       {
10367         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
10368       }
10369     }
10370     else if (aFlag == "-blockedrng"
10371           || aFlag == "-brng")
10372     {
10373       if (toPrint)
10374       {
10375         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
10376         continue;
10377       }
10378
10379       Standard_Boolean toEnable = Standard_True;
10380       if (++anArgIter < theArgNb
10381         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10382       {
10383         --anArgIter;
10384       }
10385       aParams.CoherentPathTracingMode = toEnable;
10386     }
10387     else if (aFlag == "-maxrad")
10388     {
10389       if (toPrint)
10390       {
10391         theDI << aParams.RadianceClampingValue << " ";
10392         continue;
10393       }
10394       else if (++anArgIter >= theArgNb)
10395       {
10396         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10397         return 1;
10398       }
10399
10400       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
10401       if (!aMaxRadStr.IsRealValue())
10402       {
10403         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10404         return 1;
10405       }
10406
10407       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
10408       if (aMaxRadiance <= 0.0)
10409       {
10410         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
10411         return 1;
10412       }
10413       else
10414       {
10415         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
10416       }
10417     }
10418     else if (aFlag == "-iss")
10419     {
10420       if (toPrint)
10421       {
10422         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
10423         continue;
10424       }
10425
10426       Standard_Boolean toEnable = Standard_True;
10427       if (++anArgIter < theArgNb
10428         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10429       {
10430         --anArgIter;
10431       }
10432       aParams.AdaptiveScreenSampling = toEnable;
10433     }
10434     else if (aFlag == "-issd")
10435     {
10436       if (toPrint)
10437       {
10438         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
10439         continue;
10440       }
10441
10442       Standard_Boolean toEnable = Standard_True;
10443       if (++anArgIter < theArgNb
10444         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10445       {
10446         --anArgIter;
10447       }
10448       aParams.ShowSamplingTiles = toEnable;
10449     }
10450     else if (aFlag == "-nbtiles")
10451     {
10452       if (toPrint)
10453       {
10454         theDI << aParams.NbRayTracingTiles << " ";
10455         continue;
10456       }
10457       else if (++anArgIter >= theArgNb)
10458       {
10459         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10460         return 1;
10461       }
10462
10463       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
10464
10465       if (aNbTiles < 64)
10466       {
10467         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
10468         std::cerr << "Specify value in range [64, 1024].\n";
10469         return 1;
10470       }
10471       else
10472       {
10473         aParams.NbRayTracingTiles = aNbTiles;
10474       }
10475     }
10476     else if (aFlag == "-env")
10477     {
10478       if (toPrint)
10479       {
10480         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
10481         continue;
10482       }
10483
10484       Standard_Boolean toEnable = Standard_True;
10485       if (++anArgIter < theArgNb
10486         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10487       {
10488         --anArgIter;
10489       }
10490       aParams.UseEnvironmentMapBackground = toEnable;
10491     }
10492     else if (aFlag == "-twoside")
10493     {
10494       if (toPrint)
10495       {
10496         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
10497         continue;
10498       }
10499
10500       Standard_Boolean toEnable = Standard_True;
10501       if (++anArgIter < theArgNb
10502         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10503       {
10504         --anArgIter;
10505       }
10506       aParams.TwoSidedBsdfModels = toEnable;
10507     }
10508     else if (aFlag == "-shademodel"
10509           || aFlag == "-shadingmodel"
10510           || aFlag == "-shading")
10511     {
10512       if (toPrint)
10513       {
10514         switch (aView->ShadingModel())
10515         {
10516           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
10517           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
10518           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
10519           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
10520           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
10521         }
10522         continue;
10523       }
10524
10525       if (++anArgIter >= theArgNb)
10526       {
10527         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10528       }
10529
10530       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
10531       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
10532        && aModel != Graphic3d_TOSM_DEFAULT)
10533       {
10534         aView->SetShadingModel (aModel);
10535       }
10536       else
10537       {
10538         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
10539         return 1;
10540       }
10541     }
10542     else if (aFlag == "-resolution")
10543     {
10544       if (++anArgIter >= theArgNb)
10545       {
10546         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
10547         return 1;
10548       }
10549
10550       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
10551       if (aResolution.IsIntegerValue())
10552       {
10553         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
10554       }
10555       else
10556       {
10557         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10558         return 1;
10559       }
10560     }
10561     else if (aFlag == "-rebuildglsl"
10562           || aFlag == "-rebuild")
10563     {
10564       if (toPrint)
10565       {
10566         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
10567         continue;
10568       }
10569
10570       Standard_Boolean toEnable = Standard_True;
10571       if (++anArgIter < theArgNb
10572           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10573       {
10574         --anArgIter;
10575       }
10576       aParams.RebuildRayTracingShaders = toEnable;
10577     }
10578     else if (aFlag == "-focal")
10579     {
10580       if (++anArgIter >= theArgNb)
10581       {
10582         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10583         return 1;
10584       }
10585
10586       TCollection_AsciiString aParam (theArgVec[anArgIter]);
10587       if (aParam.IsRealValue())
10588       {
10589         float aFocalDist = static_cast<float> (aParam.RealValue());
10590         if (aFocalDist < 0)
10591         {
10592           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10593           return 1;
10594         }
10595         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
10596       }
10597       else
10598       {
10599         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10600         return 1;
10601       }
10602     }
10603     else if (aFlag == "-aperture")
10604     {
10605       if (++anArgIter >= theArgNb)
10606       {
10607         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10608         return 1;
10609       }
10610
10611       TCollection_AsciiString aParam(theArgVec[anArgIter]);
10612       if (aParam.IsRealValue())
10613       {
10614         float aApertureSize = static_cast<float> (aParam.RealValue());
10615         if (aApertureSize < 0)
10616         {
10617           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
10618           return 1;
10619         }
10620         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
10621       }
10622       else
10623       {
10624         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10625         return 1;
10626       }
10627     }
10628     else if (aFlag == "-exposure")
10629     {
10630       if (++anArgIter >= theArgNb)
10631       {
10632         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10633         return 1;
10634       }
10635
10636       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
10637       if (anExposure.IsRealValue())
10638       {
10639         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
10640       }
10641       else
10642       {
10643         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10644         return 1;
10645       }
10646     }
10647     else if (aFlag == "-whitepoint")
10648     {
10649       if (++anArgIter >= theArgNb)
10650       {
10651         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10652         return 1;
10653       }
10654
10655       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
10656       if (aWhitePoint.IsRealValue())
10657       {
10658         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
10659       }
10660       else
10661       {
10662         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10663         return 1;
10664       }
10665     }
10666     else if (aFlag == "-tonemapping")
10667     {
10668       if (++anArgIter >= theArgNb)
10669       {
10670         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10671         return 1;
10672       }
10673
10674       TCollection_AsciiString aMode (theArgVec[anArgIter]);
10675       aMode.LowerCase();
10676
10677       if (aMode == "disabled")
10678       {
10679         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
10680       }
10681       else if (aMode == "filmic")
10682       {
10683         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
10684       }
10685       else
10686       {
10687         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
10688         return 1;
10689       }
10690     }
10691     else if (aFlag == "-performancestats"
10692           || aFlag == "-performancecounters"
10693           || aFlag == "-perfstats"
10694           || aFlag == "-perfcounters"
10695           || aFlag == "-stats")
10696     {
10697       if (++anArgIter >= theArgNb)
10698       {
10699         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10700         return 1;
10701       }
10702
10703       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
10704       aFlagsStr.LowerCase();
10705       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
10706       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
10707       {
10708         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10709         return 1;
10710       }
10711       aView->ChangeRenderingParams().CollectedStats = aFlags;
10712       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
10713     }
10714     else if (aFlag == "-perfupdateinterval"
10715           || aFlag == "-statsupdateinterval")
10716     {
10717       if (++anArgIter >= theArgNb)
10718       {
10719         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
10720         return 1;
10721       }
10722       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
10723     }
10724     else
10725     {
10726       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
10727       return 1;
10728     }
10729   }
10730
10731   return 0;
10732 }
10733
10734 //=======================================================================
10735 //function : VProgressiveMode
10736 //purpose  :
10737 //=======================================================================
10738 #if defined(_WIN32)
10739 static Standard_Integer VProgressiveMode (Draw_Interpretor& /*theDI*/,
10740                                           Standard_Integer  /*theNbArgs*/,
10741                                           const char**      /*theArgs*/)
10742 {
10743   Handle(V3d_View) aView = ViewerTest::CurrentView();
10744   if (aView.IsNull())
10745   {
10746     std::cerr << "Error: no active viewer!\n";
10747     return 1;
10748   }
10749
10750   std::cout << "Press Enter or Escape key to exit progressive rendering mode" << std::endl;
10751
10752   for (;;)
10753   {
10754     aView->Redraw();
10755
10756     Standard_Boolean toExit = Standard_False;
10757
10758     MSG aMsg;
10759     while (PeekMessageW (&aMsg, NULL, 0, 0, PM_REMOVE))
10760     {
10761       if (aMsg.message == WM_KEYDOWN && (aMsg.wParam == 0x0d || aMsg.wParam == 0x1b))
10762       {
10763         toExit = Standard_True;
10764       }
10765
10766       TranslateMessage (&aMsg);
10767       DispatchMessageW (&aMsg);
10768     }
10769
10770     if (toExit)
10771     {
10772       break;
10773     }
10774   }
10775
10776   return 0;
10777 }
10778 #endif
10779
10780 //=======================================================================
10781 //function : VFrustumCulling
10782 //purpose  : enables/disables view volume's culling.
10783 //=======================================================================
10784 static int VFrustumCulling (Draw_Interpretor& theDI,
10785                             Standard_Integer  theArgNb,
10786                             const char**      theArgVec)
10787 {
10788   Handle(V3d_View) aView = ViewerTest::CurrentView();
10789   if (aView.IsNull())
10790   {
10791     std::cout << theArgVec[0] << " Error: Use 'vinit' command before\n";
10792     return 1;
10793   }
10794
10795   if (theArgNb < 2)
10796   {
10797     theDI << (aView->IsCullingEnabled() ? "on" : "off");
10798     return 0;
10799   }
10800   else if (theArgNb != 2)
10801   {
10802     std::cout << theArgVec[0] << " Syntax error: Specify the mode\n";
10803     return 1;
10804   }
10805
10806   TCollection_AsciiString aModeStr (theArgVec[1]);
10807   aModeStr.LowerCase();
10808   Standard_Boolean toEnable = 0;
10809   if (aModeStr == "on")
10810   {
10811     toEnable = 1;
10812   }
10813   else if (aModeStr == "off")
10814   {
10815     toEnable = 0;
10816   }
10817   else
10818   {
10819     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10820   }
10821
10822   aView->SetFrustumCulling (toEnable);
10823   aView->Redraw();
10824   return 0;
10825 }
10826
10827 //=======================================================================
10828 //function : VHighlightSelected
10829 //purpose  : 
10830 //=======================================================================
10831 static int VHighlightSelected (Draw_Interpretor& theDI,
10832                                Standard_Integer  theArgNb,
10833                                const char**      theArgVec)
10834 {
10835   if (ViewerTest::GetAISContext().IsNull())
10836   {
10837     std::cout << theArgVec[0] << " error : Context is not created. Please call vinit before.\n";
10838     return 1;
10839   }
10840
10841   const Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10842
10843   if (theArgNb < 2)
10844   {
10845     theDI << (aContext->ToHilightSelected() ? "on" : "off");
10846     return 0;
10847   }
10848
10849   if (theArgNb != 2)
10850   {
10851     std::cout  << theArgVec[0] << " error : wrong number of parameters."
10852           << "Type 'help" << theArgVec[0] << "' for more information.";
10853     return 1;
10854   }
10855
10856   // Parse parameter
10857   TCollection_AsciiString aMode (theArgVec[1]);
10858   aMode.LowerCase();
10859   Standard_Boolean toEnable = Standard_False;
10860   if (aMode.IsEqual ("on"))
10861   {
10862     toEnable = Standard_True;
10863   }
10864   else if (aMode.IsEqual ("off"))
10865   {
10866     toEnable = Standard_False;
10867   }
10868   else
10869   {
10870     toEnable = Draw::Atoi (theArgVec[1]) != 0;
10871   }
10872
10873   if (toEnable != aContext->ToHilightSelected())
10874   {
10875     aContext->SetToHilightSelected (toEnable);
10876
10877     // Move cursor to null position and  back to process updating of detection
10878     // and highlighting of selected object immediatly.
10879     Standard_Integer aPixX = 0;
10880     Standard_Integer aPixY = 0;
10881     const Handle(ViewerTest_EventManager)& anEventManager =  ViewerTest::CurrentEventManager();
10882
10883     anEventManager->GetCurrentPosition (aPixX, aPixY);
10884     anEventManager->MoveTo (0, 0);
10885     anEventManager->MoveTo (aPixX, aPixY);
10886   }
10887
10888   return 0;
10889 }
10890
10891 //=======================================================================
10892 //function : VXRotate
10893 //purpose  :
10894 //=======================================================================
10895 static Standard_Integer VXRotate (Draw_Interpretor& di,
10896                                    Standard_Integer argc,
10897                                    const char ** argv)
10898 {
10899   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
10900   if (aContext.IsNull())
10901   {
10902     di << argv[0] << "ERROR : use 'vinit' command before \n";
10903     return 1;
10904   }
10905   
10906   if (argc != 3)
10907   {
10908     di << "ERROR : Usage : " << argv[0] << " name angle\n";
10909     return 1;
10910   }
10911
10912   TCollection_AsciiString aName (argv[1]);
10913   Standard_Real anAngle = Draw::Atof (argv[2]);
10914
10915   // find object
10916   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
10917   Handle(AIS_InteractiveObject) anIObj;
10918   if (!aMap.IsBound2 (aName) )
10919   {
10920     di << "Use 'vdisplay' before\n";
10921     return 1;
10922   }
10923   else
10924   {
10925     anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
10926
10927     gp_Trsf aTransform;
10928     aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
10929     aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
10930
10931     aContext->SetLocation (anIObj, aTransform);
10932     aContext->UpdateCurrentViewer();
10933   }
10934
10935   return 0;
10936 }
10937
10938 //===============================================================================================
10939 //class   : ViewerTest_AISManipulator
10940 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
10941 //===============================================================================================
10942 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10943
10944 class ViewerTest_AISManipulator : public AIS_Manipulator
10945 {
10946 public:
10947
10948   ViewerTest_AISManipulator() : AIS_Manipulator()
10949   {
10950     GetMapOfAISManipulators().Add (this);
10951   }
10952
10953   virtual ~ViewerTest_AISManipulator()
10954   {
10955     GetMapOfAISManipulators().Remove (this);
10956   }
10957
10958   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10959 };
10960
10961 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
10962 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
10963
10964 //===============================================================================================
10965 //function : VManipulator
10966 //purpose  :
10967 //===============================================================================================
10968 static int VManipulator (Draw_Interpretor& theDi,
10969                          Standard_Integer  theArgsNb,
10970                          const char**      theArgVec)
10971 {
10972   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10973   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10974   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
10975   if (aView.IsNull()
10976    || aViewer.IsNull())
10977   {
10978     std::cerr << "No active viewer!\n";
10979     return 1;
10980   }
10981
10982   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
10983   Standard_Integer anArgIter = 1;
10984   for (; anArgIter < theArgsNb; ++anArgIter)
10985   {
10986     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
10987   }
10988
10989   ViewerTest_CmdParser aCmd;
10990   aCmd.AddDescription ("Manages manipulator for interactive objects:");
10991   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
10992   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
10993   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
10994   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
10995   aCmd.AddOption ("detach",         "...       - detach manipulator");
10996
10997   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
10998   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
10999   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
11000
11001   aCmd.AddOption ("move",   "... x y z - move object");
11002   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
11003   aCmd.AddOption ("scale",  "... factor - scale object");
11004
11005   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
11006   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
11007   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
11008   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
11009   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
11010   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
11011   aCmd.AddOption ("size",              "... size - set size of manipulator");
11012   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
11013
11014   aCmd.Parse (theArgsNb, theArgVec);
11015
11016   if (aCmd.HasOption ("help"))
11017   {
11018     theDi.PrintHelp (theArgVec[0]);
11019     return 0;
11020   }
11021
11022   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
11023
11024   TCollection_AsciiString aName (aCmd.Arg ("", 0).c_str());
11025
11026   if (aName.IsEmpty())
11027   {
11028     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
11029     return 1;
11030   }
11031
11032   // ----------------------------------
11033   // detach existing manipulator object
11034   // ----------------------------------
11035
11036   if (aCmd.HasOption ("detach"))
11037   {
11038     if (!aMapAIS.IsBound2 (aName))
11039     {
11040       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
11041       return 1;
11042     }
11043
11044     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11045     if (aManipulator.IsNull())
11046     {
11047       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11048       return 1;
11049     }
11050
11051     aManipulator->Detach();
11052     aMapAIS.UnBind2 (aName);
11053     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
11054
11055     return 0;
11056   }
11057
11058   // -----------------------------------------------
11059   // find or create manipulator if it does not exist
11060   // -----------------------------------------------
11061
11062   Handle(AIS_Manipulator) aManipulator;
11063   if (!aMapAIS.IsBound2 (aName))
11064   {
11065     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
11066
11067     aManipulator = new ViewerTest_AISManipulator();
11068     aMapAIS.Bind (aManipulator, aName);
11069   }
11070   else
11071   {
11072     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
11073     if (aManipulator.IsNull())
11074     {
11075       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
11076       return 1;
11077     }
11078   }
11079
11080   // -----------------------------------------
11081   // change properties of manipulator instance
11082   // -----------------------------------------
11083
11084   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
11085   {
11086     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
11087   }
11088   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
11089   {
11090     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
11091   }
11092   if (aCmd.HasOption ("followRotation", 1, Standard_True))
11093   {
11094     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
11095   }
11096   if (aCmd.HasOption ("gap", 1, Standard_True))
11097   {
11098     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
11099   }
11100   if (aCmd.HasOption ("part", 3, Standard_True))
11101   {
11102     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
11103     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
11104     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
11105     if (aMode < 1 || aMode > 3)
11106     {
11107       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 3].\n";
11108       return 1;
11109     }
11110
11111     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
11112   }
11113   if (aCmd.HasOption ("pos", 3, Standard_True))
11114   {
11115     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
11116     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
11117     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
11118
11119     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
11120   }
11121   if (aCmd.HasOption ("size", 1, Standard_True))
11122   {
11123     aManipulator->SetSize (aCmd.ArgFloat ("size"));
11124   }
11125   if (aCmd.HasOption ("zoomable", 1, Standard_True))
11126   {
11127     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
11128
11129     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
11130     {
11131       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
11132       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
11133     }
11134   }
11135
11136   // ---------------------------------------------------
11137   // attach, detach or access manipulator from an object
11138   // ---------------------------------------------------
11139
11140   if (aCmd.HasOption ("attach"))
11141   {
11142     // Find an object and attach manipulator to it
11143     if (!aCmd.HasOption ("attach", 1, Standard_True))
11144     {
11145       return 1;
11146     }
11147
11148     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
11149     if (!aMapAIS.IsBound2 (anObjName))
11150     {
11151       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
11152       return 1;
11153     }
11154
11155     Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapAIS.Find2 (anObjName));
11156     ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
11157     for (; anIt.More(); anIt.Next())
11158     {
11159       if (anIt.Value()->IsAttached()
11160        && anIt.Value()->Object() == anObject)
11161       {
11162         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
11163         return 1;
11164       }
11165     }
11166
11167     AIS_Manipulator::OptionsForAttach anOptions;
11168     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
11169     {
11170       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
11171     }
11172     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
11173     {
11174       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
11175     }
11176     if (aCmd.HasOption ("enableModes", 1, Standard_True))
11177     {
11178       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
11179     }
11180
11181     aManipulator->Attach (anObject, anOptions);
11182   }
11183
11184   // --------------------------------------
11185   // apply transformation using manipulator
11186   // --------------------------------------
11187
11188   if (aCmd.HasOption ("startTransform", 2, Standard_True))
11189   {
11190     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
11191   }
11192   if (aCmd.HasOption ("transform", 2, Standard_True))
11193   {
11194     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
11195   }
11196   if (aCmd.HasOption ("stopTransform"))
11197   {
11198     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
11199
11200     aManipulator->StopTransform (toApply);
11201   }
11202
11203   gp_Trsf aT;
11204   if (aCmd.HasOption ("move", 3, Standard_True))
11205   {
11206     aT.SetTranslationPart (aCmd.ArgVec ("move"));
11207   }
11208   if (aCmd.HasOption ("rotate", 7, Standard_True))
11209   {
11210     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
11211   }
11212   if (aCmd.HasOption ("scale", 1))
11213   {
11214     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
11215   }
11216
11217   if (aT.Form() != gp_Identity)
11218   {
11219     aManipulator->Transform (aT);
11220   }
11221
11222   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
11223
11224   return 0;
11225 }
11226
11227 //===============================================================================================
11228 //function : VSelectionProperties
11229 //purpose  :
11230 //===============================================================================================
11231 static int VSelectionProperties (Draw_Interpretor& theDi,
11232                                  Standard_Integer  theArgsNb,
11233                                  const char**      theArgVec)
11234 {
11235   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
11236   if (aCtx.IsNull())
11237   {
11238     std::cerr << "No active viewer!\n";
11239     return 1;
11240   }
11241
11242   Standard_Boolean toPrint  = theArgsNb == 1;
11243   Standard_Boolean toRedraw = Standard_False;
11244   Standard_Integer anArgIter = 1;
11245   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
11246   if (anArgIter < theArgsNb)
11247   {
11248     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
11249     anArgFirst.LowerCase();
11250     ++anArgIter;
11251     if (anArgFirst == "dynhighlight"
11252      || anArgFirst == "dynhilight"
11253      || anArgFirst == "dynamichighlight"
11254      || anArgFirst == "dynamichilight")
11255     {
11256       aType = Prs3d_TypeOfHighlight_Dynamic;
11257     }
11258     else if (anArgFirst == "localdynhighlight"
11259           || anArgFirst == "localdynhilight"
11260           || anArgFirst == "localdynamichighlight"
11261           || anArgFirst == "localdynamichilight")
11262     {
11263       aType = Prs3d_TypeOfHighlight_LocalDynamic;
11264     }
11265     else if (anArgFirst == "selhighlight"
11266           || anArgFirst == "selhilight"
11267           || anArgFirst == "selectedhighlight"
11268           || anArgFirst == "selectedhilight")
11269     {
11270       aType = Prs3d_TypeOfHighlight_Selected;
11271     }
11272     else if (anArgFirst == "localselhighlight"
11273           || anArgFirst == "localselhilight"
11274           || anArgFirst == "localselectedhighlight"
11275           || anArgFirst == "localselectedhilight")
11276     {
11277       aType = Prs3d_TypeOfHighlight_LocalSelected;
11278     }
11279     else
11280     {
11281       --anArgIter;
11282     }
11283   }
11284   for (; anArgIter < theArgsNb; ++anArgIter)
11285   {
11286     TCollection_AsciiString anArg (theArgVec[anArgIter]);
11287     anArg.LowerCase();
11288     if (anArg == "-help")
11289     {
11290       theDi.PrintHelp (theArgVec[0]);
11291       return 0;
11292     }
11293     else if (anArg == "-print")
11294     {
11295       toPrint = Standard_True;
11296     }
11297     else if (anArg == "-autoactivate")
11298     {
11299       Standard_Boolean toEnable = Standard_True;
11300       if (anArgIter + 1 < theArgsNb
11301        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
11302       {
11303         ++anArgIter;
11304       }
11305       aCtx->SetAutoActivateSelection (toEnable);
11306     }
11307     else if (anArg == "-pickstrategy"
11308           || anArg == "-pickingstrategy")
11309     {
11310       if (++anArgIter >= theArgsNb)
11311       {
11312         std::cout << "Syntax error: type of highlighting is undefined\n";
11313         return 1;
11314       }
11315
11316       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11317       TCollection_AsciiString aVal (theArgVec[anArgIter]);
11318       aVal.LowerCase();
11319       if (aVal == "first"
11320        || aVal == "firstaccepted"
11321        || aVal == "firstacceptable")
11322       {
11323         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
11324       }
11325       else if (aVal == "topmost"
11326             || aVal == "onlyTopmost")
11327       {
11328         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
11329       }
11330       else
11331       {
11332         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
11333         return 1;
11334       }
11335
11336       aCtx->SetPickingStrategy (aStrategy);
11337     }
11338     else if (anArg == "-pixtol"
11339           && anArgIter + 1 < theArgsNb)
11340     {
11341       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
11342     }
11343     else if ((anArg == "-mode"
11344            || anArg == "-dispmode")
11345           && anArgIter + 1 < theArgsNb)
11346     {
11347       if (aType == Prs3d_TypeOfHighlight_None)
11348       {
11349         std::cout << "Syntax error: type of highlighting is undefined\n";
11350         return 1;
11351       }
11352
11353       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
11354       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11355       aStyle->SetDisplayMode (aDispMode);
11356       toRedraw = Standard_True;
11357     }
11358     else if (anArg == "-layer"
11359           && anArgIter + 1 < theArgsNb)
11360     {
11361       if (aType == Prs3d_TypeOfHighlight_None)
11362       {
11363         std::cout << "Syntax error: type of highlighting is undefined\n";
11364         return 1;
11365       }
11366
11367       const Standard_Integer aNewLayer = Draw::Atoi (theArgVec[++anArgIter]);
11368       if (aNewLayer != Graphic3d_ZLayerId_UNKNOWN)
11369       {
11370         TColStd_SequenceOfInteger aLayers;
11371         aCtx->CurrentViewer()->GetAllZLayers (aLayers);
11372         if (std::find (aLayers.begin(), aLayers.end(), aNewLayer) == aLayers.end())
11373         {
11374           std::cout << "Syntax error: Layer " << aNewLayer << " is undefined\n";
11375           return 1;
11376         }
11377       }
11378
11379       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11380       aStyle->SetZLayer (aNewLayer);
11381       toRedraw = Standard_True;
11382     }
11383     else if (anArg == "-hicolor"
11384           || anArg == "-selcolor"
11385           || anArg == "-color")
11386     {
11387       if (anArg.StartsWith ("-hi"))
11388       {
11389         aType = Prs3d_TypeOfHighlight_Dynamic;
11390       }
11391       else if (anArg.StartsWith ("-sel"))
11392       {
11393         aType = Prs3d_TypeOfHighlight_Selected;
11394       }
11395       else if (aType == Prs3d_TypeOfHighlight_None)
11396       {
11397         std::cout << "Syntax error: type of highlighting is undefined\n";
11398         return 1;
11399       }
11400
11401       Quantity_Color aColor;
11402       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
11403                                                            theArgVec + anArgIter + 1,
11404                                                            aColor);
11405       if (aNbParsed == 0)
11406       {
11407         std::cout << "Syntax error: need more arguments.\n";
11408         return 1;
11409       }
11410       anArgIter += aNbParsed;
11411
11412       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11413       aStyle->SetColor (aColor);
11414       toRedraw = Standard_True;
11415     }
11416     else if ((anArg == "-transp"
11417            || anArg == "-transparency"
11418            || anArg == "-hitransp"
11419            || anArg == "-seltransp"
11420            || anArg == "-hitransplocal"
11421            || anArg == "-seltransplocal")
11422           && anArgIter + 1 < theArgsNb)
11423     {
11424       if (anArg.StartsWith ("-hi"))
11425       {
11426         aType = Prs3d_TypeOfHighlight_Dynamic;
11427       }
11428       else if (anArg.StartsWith ("-sel"))
11429       {
11430         aType = Prs3d_TypeOfHighlight_Selected;
11431       }
11432       else if (aType == Prs3d_TypeOfHighlight_None)
11433       {
11434         std::cout << "Syntax error: type of highlighting is undefined\n";
11435         return 1;
11436       }
11437
11438       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
11439       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11440       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
11441       toRedraw = Standard_True;
11442     }
11443     else if ((anArg == "-mat"
11444            || anArg == "-material")
11445           && anArgIter + 1 < theArgsNb)
11446     {
11447       if (aType == Prs3d_TypeOfHighlight_None)
11448       {
11449         std::cout << "Syntax error: type of highlighting is undefined\n";
11450         return 1;
11451       }
11452
11453       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
11454       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
11455       if (aMatName != Graphic3d_NOM_DEFAULT)
11456       {
11457         ++anArgIter;
11458         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
11459         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
11460         Graphic3d_MaterialAspect aMat (aMatName);
11461         aMat.SetColor (aStyle->Color());
11462         aMat.SetTransparency (aStyle->Transparency());
11463         anAspect->SetFrontMaterial (aMat);
11464         anAspect->SetInteriorColor (aStyle->Color());
11465         aStyle->SetBasicFillAreaAspect (anAspect);
11466       }
11467       else
11468       {
11469         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
11470       }
11471       toRedraw = Standard_True;
11472     }
11473     else
11474     {
11475       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
11476     }
11477   }
11478
11479   if (toPrint)
11480   {
11481     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
11482     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
11483     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
11484     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
11485     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
11486     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
11487     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
11488     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
11489     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
11490     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
11491     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
11492     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
11493   }
11494
11495   if (aCtx->NbSelected() != 0 && toRedraw)
11496   {
11497     aCtx->HilightSelected (Standard_True);
11498   }
11499
11500   return 0;
11501 }
11502
11503 //===============================================================================================
11504 //function : VDumpSelectionImage
11505 //purpose  :
11506 //===============================================================================================
11507 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
11508                                 Standard_Integer  theArgsNb,
11509                                 const char**      theArgVec)
11510 {
11511   if (theArgsNb < 2)
11512   {
11513     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
11514     return 1;
11515   }
11516
11517   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
11518   if (aContext.IsNull())
11519   {
11520     std::cout << "Error: no active view.\n";
11521     return 1;
11522   }
11523
11524   TCollection_AsciiString aFile;
11525   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11526   Image_Format anImgFormat = Image_Format_BGR;
11527   Standard_Integer aPickedIndex = 1;
11528   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
11529   {
11530     TCollection_AsciiString aParam (theArgVec[anArgIter]);
11531     aParam.LowerCase();
11532     if (aParam == "-type")
11533     {
11534       if (++anArgIter >= theArgsNb)
11535       {
11536         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
11537         return 1;
11538       }
11539
11540       TCollection_AsciiString aValue (theArgVec[anArgIter]);
11541       aValue.LowerCase();
11542       if (aValue == "depth"
11543        || aValue == "normdepth"
11544        || aValue == "normalizeddepth")
11545       {
11546         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
11547         anImgFormat = Image_Format_GrayF;
11548       }
11549       if (aValue == "depthinverted"
11550        || aValue == "normdepthinverted"
11551        || aValue == "normalizeddepthinverted"
11552        || aValue == "inverted")
11553       {
11554         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
11555         anImgFormat = Image_Format_GrayF;
11556       }
11557       else if (aValue == "unnormdepth"
11558             || aValue == "unnormalizeddepth")
11559       {
11560         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
11561         anImgFormat = Image_Format_GrayF;
11562       }
11563       else if (aValue == "objectcolor"
11564             || aValue == "object"
11565             || aValue == "color")
11566       {
11567         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
11568       }
11569       else if (aValue == "entitycolor"
11570             || aValue == "entity")
11571       {
11572         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
11573       }
11574       else if (aValue == "ownercolor"
11575             || aValue == "owner")
11576       {
11577         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
11578       }
11579       else if (aValue == "selectionmodecolor"
11580             || aValue == "selectionmode"
11581             || aValue == "selmodecolor"
11582             || aValue == "selmode")
11583       {
11584         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
11585       }
11586     }
11587     else if (aParam == "-picked"
11588           || aParam == "-pickeddepth"
11589           || aParam == "-pickedindex")
11590     {
11591       if (++anArgIter >= theArgsNb)
11592       {
11593         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
11594         return 1;
11595       }
11596
11597       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
11598     }
11599     else if (aFile.IsEmpty())
11600     {
11601       aFile = theArgVec[anArgIter];
11602     }
11603     else
11604     {
11605       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
11606       return 1;
11607     }
11608   }
11609   if (aFile.IsEmpty())
11610   {
11611     std::cout << "Syntax error: image file name is missing.\n";
11612     return 1;
11613   }
11614
11615   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
11616   Standard_Integer aWidth = 0, aHeight = 0;
11617   aView->Window()->Size (aWidth, aHeight);
11618
11619   Image_AlienPixMap aPixMap;
11620   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
11621   {
11622     std::cout << "Error: can't allocate image.\n";
11623     return 1;
11624   }
11625   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
11626   {
11627     std::cout << "Error: can't generate selection image.\n";
11628     return 1;
11629   }
11630   if (!aPixMap.Save (aFile))
11631   {
11632     std::cout << "Error: can't save selection image.\n";
11633     return 0;
11634   }
11635   return 0;
11636 }
11637
11638 //=======================================================================
11639 //function : ViewerCommands
11640 //purpose  :
11641 //=======================================================================
11642
11643 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
11644 {
11645
11646   const char *group = "ZeViewer";
11647   theCommands.Add("vinit",
11648           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
11649     "\n\t\t:     [-exitOnClose] [-closeOnEscape]"
11650   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11651     "\n\t\t:     [-display displayName]"
11652   #endif
11653     "\n\t\t: Creates new View window with specified name viewName."
11654     "\n\t\t: By default the new view is created in the viewer and in"
11655     "\n\t\t: graphic driver shared with active view."
11656     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
11657     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
11658     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
11659 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
11660     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
11661     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
11662 #endif
11663     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
11664     "\n\t\t:  -width, -height width and heigth of window respectively."
11665     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
11666     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
11667     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
11668     __FILE__,VInit,group);
11669   theCommands.Add("vclose" ,
11670     "[view_id [keep_context=0|1]]\n"
11671     "or vclose ALL - to remove all created views\n"
11672     " - removes view(viewer window) defined by its view_id.\n"
11673     " - keep_context: by default 0; if 1 and the last view is deleted"
11674     " the current context is not removed.",
11675     __FILE__,VClose,group);
11676   theCommands.Add("vactivate" ,
11677     "view_id"
11678     " - activates view(viewer window) defined by its view_id",
11679     __FILE__,VActivate,group);
11680   theCommands.Add("vviewlist",
11681     "vviewlist [format={tree, long}]"
11682     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
11683     " - format: format of result output, if tree the output is a tree view;"
11684     "otherwise it's a list of full view names. By default format = tree",
11685     __FILE__,VViewList,group);
11686   theCommands.Add("vhelp" ,
11687     "vhelp            : display help on the viewer commands",
11688     __FILE__,VHelp,group);
11689   theCommands.Add("vtop" ,
11690     "vtop or <T>      : Top view. Orientation +X+Y" ,
11691     __FILE__,VTop,group);
11692   theCommands.Add("vbottom" ,
11693     "vbottom          : Bottom view. Orientation +X-Y" ,
11694     __FILE__,VBottom,group);
11695   theCommands.Add("vleft" ,
11696     "vleft            : Left view. Orientation -Y+Z" ,
11697     __FILE__,VLeft,group);
11698   theCommands.Add("vright" ,
11699     "vright           : Right view. Orientation +Y+Z" ,
11700     __FILE__,VRight,group);
11701   theCommands.Add("vaxo" ,
11702     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
11703     __FILE__,VAxo,group);
11704   theCommands.Add("vfront" ,
11705     "vfront           : Front view. Orientation +X+Z" ,
11706     __FILE__,VFront,group);
11707   theCommands.Add("vback" ,
11708     "vback            : Back view. Orientation -X+Z" ,
11709     __FILE__,VBack,group);
11710   theCommands.Add("vpick" ,
11711     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
11712     VPick,group);
11713   theCommands.Add("vfit",
11714     "vfit or <F> [-selected] [-noupdate]"
11715     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
11716     __FILE__,VFit,group);
11717   theCommands.Add ("vfitarea",
11718     "vfitarea x1 y1 x2 y2"
11719     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
11720     "\n\t\t: Fit view to show area located between two points"
11721     "\n\t\t: given in world 2D or 3D corrdinates.",
11722     __FILE__, VFitArea, group);
11723   theCommands.Add ("vzfit", "vzfit [scale]\n"
11724     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
11725     "   \"scale\" - specifies factor to scale computed z range.\n",
11726     __FILE__, VZFit, group);
11727   theCommands.Add("vrepaint",
11728             "vrepaint [-immediate]"
11729     "\n\t\t: force redraw",
11730     __FILE__,VRepaint,group);
11731   theCommands.Add("vclear",
11732     "vclear          : vclear"
11733     "\n\t\t: remove all the object from the viewer",
11734     __FILE__,VClear,group);
11735   theCommands.Add("vsetbg",
11736     "vsetbg          : vsetbg imagefile [filltype] : Load image as background",
11737     __FILE__,VSetBg,group);
11738   theCommands.Add("vsetbgmode",
11739     "vsetbgmode      : vsetbgmode filltype : Change background image fill type",
11740     __FILE__,VSetBgMode,group);
11741   theCommands.Add("vsetgradientbg",
11742     "vsetgradientbg  : vsetgradientbg r1 g1 b1 r2 g2 b2 filltype : Mount gradient background",
11743     __FILE__,VSetGradientBg,group);
11744   theCommands.Add("vsetgrbgmode",
11745     "vsetgrbgmode    : vsetgrbgmode filltype : Change gradient background fill type",
11746     __FILE__,VSetGradientBgMode,group);
11747   theCommands.Add("vsetcolorbg",
11748     "vsetcolorbg     : vsetcolorbg r g b : Set background color",
11749     __FILE__,VSetColorBg,group);
11750   theCommands.Add("vsetdefaultbg",
11751     "vsetdefaultbg r g b\n"
11752     "\n\t\t: vsetdefaultbg r1 g1 b1 r2 g2 b2 fillmode"
11753     "\n\t\t: Set default viewer background fill color (flat/gradient).",
11754     __FILE__,VSetDefaultBg,group);
11755   theCommands.Add("vscale",
11756     "vscale          : vscale X Y Z",
11757     __FILE__,VScale,group);
11758   theCommands.Add("vzbufftrihedron",
11759             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
11760     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
11761     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
11762     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
11763     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
11764     "\n\t\t: Displays a trihedron",
11765     __FILE__,VZBuffTrihedron,group);
11766   theCommands.Add("vrotate",
11767     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
11768     "\n                : Option -mouseStart starts rotation according to the mouse position"
11769     "\n                : Option -mouseMove continues rotation with angle computed"
11770     "\n                : from last and new mouse position."
11771     "\n                : vrotate AX AY AZ [X Y Z]",
11772     __FILE__,VRotate,group);
11773   theCommands.Add("vzoom",
11774     "vzoom           : vzoom coef",
11775     __FILE__,VZoom,group);
11776   theCommands.Add("vpan",
11777     "vpan            : vpan dx dy",
11778     __FILE__,VPan,group);
11779   theCommands.Add("vexport",
11780     "vexport         : vexport full_file_path {PS | EPS | TEX | PDF | SVG | PGF | EMF }"
11781     " : exports the view to a vector file of a given format"
11782     " : notice that EMF format requires patched gl2ps",
11783     __FILE__,VExport,group);
11784   theCommands.Add("vcolorscale",
11785     "vcolorscale name [-noupdate|-update] [-demo]"
11786     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
11787     "\n\t\t:       [-font HeightFont=20]"
11788     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
11789     "\n\t\t:       [-smoothTransition {on|off}=off]"
11790     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
11791     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
11792     "\n\t\t:       [-textpos {left|right|center|none}=right]"
11793     "\n\t\t:       [-labelAtBorder {on|off}=on]"
11794     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
11795     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
11796     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
11797     "\n\t\t:       [-xy Left=0 Bottom=0]"
11798     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
11799     "\n\t\t:  -colors   - set colors for all intervals"
11800     "\n\t\t:  -color    - set color for specific interval"
11801     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
11802     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
11803     "\n\t\t:              at border means the value inbetween neighbor intervals,"
11804     "\n\t\t:              at center means the center value within current interval"
11805     "\n\t\t:  -labels   - set labels for all intervals"
11806     "\n\t\t:  -freeLabels - same as -labels but does not require"
11807     "\n\t\t:              matching the number of intervals"
11808     "\n\t\t:  -label    - set label for specific interval"
11809     "\n\t\t:  -title    - set title"
11810     "\n\t\t:  -reversed - setup smooth color transition between intervals"
11811     "\n\t\t:  -smoothTransition - swap colorscale direction"
11812     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
11813     __FILE__, VColorScale, group);
11814   theCommands.Add("vgraduatedtrihedron",
11815     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
11816     "\t[-namefont Name] [-valuesfont Name]\n"
11817     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
11818     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
11819     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
11820     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
11821     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
11822     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
11823     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
11824     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
11825     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
11826     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
11827     " - Displays or erases graduated trihedron"
11828     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
11829     " - namefont - font of axes names. Default: Arial\n"
11830     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
11831     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
11832     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
11833     " - valuesfont - font of axes values. Default: Arial\n"
11834     " - xcolor, ycolor, zcolor - color of axis and values\n"
11835     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
11836     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
11837     __FILE__,VGraduatedTrihedron,group);
11838   theCommands.Add("vtile" ,
11839             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
11840     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
11841     "\n\t\t:  -totalSize the size of virtual bigger viewport"
11842     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
11843     "\n\t\t:  -lowerLeft tile offset as lower left corner"
11844     "\n\t\t:  -upperLeft tile offset as upper left corner",
11845     __FILE__, VTile, group);
11846   theCommands.Add("vzlayer",
11847               "vzlayer [layerId]"
11848       "\n\t\t:         [-add|-delete|-get|-settings]"
11849       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
11850       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
11851       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
11852       "\n\t\t: ZLayer list management:"
11853       "\n\t\t:   -add      add new z layer to viewer and print its id"
11854       "\n\t\t:   -delete   delete z layer"
11855       "\n\t\t:   -get      print sequence of z layers"
11856       "\n\t\t:   -settings print status of z layer settings"
11857       "\n\t\t:   -disable  disables given setting"
11858       "\n\t\t:   -enable   enables  given setting",
11859     __FILE__,VZLayer,group);
11860   theCommands.Add("vlayerline",
11861     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
11862     __FILE__,VLayerLine,group);
11863   theCommands.Add ("vgrid",
11864     "vgrid [off] [Mode={r|c}] [Type={l|p}] [OriginX OriginY [StepX/StepRadius StepY/DivNb RotAngle]]"
11865     " : Mode - rectangular or circular"
11866     " : Type - lines or points",
11867     __FILE__, VGrid, group);
11868   theCommands.Add ("vpriviledgedplane",
11869     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
11870     "\n\t\t:   Ox, Oy, Oz - plane origin"
11871     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
11872     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
11873     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
11874     __FILE__, VPriviledgedPlane, group);
11875   theCommands.Add ("vconvert",
11876     "vconvert v [Mode={window|view}]"
11877     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
11878     "\n\t\t: vconvert x y z [Mode={window|grid}]"
11879     "\n\t\t:   window - convert to window coordinates, pixels"
11880     "\n\t\t:   view   - convert to view projection plane"
11881     "\n\t\t:   grid   - convert to model coordinates, given on grid"
11882     "\n\t\t:   ray    - convert projection ray to model coordiantes"
11883     "\n\t\t: - vconvert v window : convert view to window;"
11884     "\n\t\t: - vconvert v view   : convert window to view;"
11885     "\n\t\t: - vconvert x y window : convert view to window;"
11886     "\n\t\t: - vconvert x y view : convert window to view;"
11887     "\n\t\t: - vconvert x y : convert window to model;"
11888     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
11889     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
11890     "\n\t\t: - vconvert x y z window : convert model to window;"
11891     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
11892     "\n\t\t: Converts the given coordinates to window/view/model space.",
11893     __FILE__, VConvert, group);
11894   theCommands.Add ("vfps",
11895     "vfps [framesNb=100] : estimate average frame rate for active view",
11896     __FILE__, VFps, group);
11897   theCommands.Add ("vgldebug",
11898             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
11899     "\n\t\t:          [-extraMsg {0|1}] [{0|1}]"
11900     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
11901     "\n\t\t: Debug context can be requested only on Windows"
11902     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
11903     "\n\t\t:  -sync     - request synchronized debug GL context"
11904     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
11905     "\n\t\t:              which are suppressed by default,"
11906     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
11907     "\n\t\t:              which are suppressed by default",
11908     __FILE__, VGlDebug, group);
11909   theCommands.Add ("vvbo",
11910     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
11911     __FILE__, VVbo, group);
11912   theCommands.Add ("vstereo",
11913             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
11914     "\n\t\t:         [-anaglyph Filter]"
11915     "\n\t\t: Control stereo output mode. Available modes for -mode:"
11916     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
11917     "\n\t\t:                     requires driver support."
11918     "\n\t\t:                     Should be called BEFORE vinit!"
11919     "\n\t\t:  anaglyph         - Anaglyph glasses"
11920     "\n\t\t:  rowInterlaced    - row-interlaced display"
11921     "\n\t\t:  columnInterlaced - column-interlaced display"
11922     "\n\t\t:  chessBoard       - chess-board output"
11923     "\n\t\t:  sideBySide       - horizontal pair"
11924     "\n\t\t:  overUnder        - vertical   pair"
11925     "\n\t\t: Available Anaglyph filters for -anaglyph:"
11926     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
11927     "\n\t\t:  greenMagentaSimple",
11928     __FILE__, VStereo, group);
11929   theCommands.Add ("vcaps",
11930             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}]"
11931     "\n\t\t:       [-compatibleProfile {0|1}]"
11932     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
11933     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
11934     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
11935     "\n\t\t: Modify particular graphic driver options:"
11936     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
11937     "\n\t\t:             built-in GLSL programs"
11938     "\n\t\t:            (requires compatible profile)"
11939     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
11940     "\n\t\t:             arrays to GPU memory)"
11941     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
11942     "\n\t\t:  vsync    - switch VSync on or off"
11943     "\n\t\t:  winBuffer - allow using window buffer for rendering"
11944     "\n\t\t: Context creation options:"
11945     "\n\t\t:  softMode          - software OpenGL implementation"
11946     "\n\t\t:  compatibleProfile - backward-compatible profile"
11947     "\n\t\t:  quadbuffer        - QuadBuffer"
11948     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
11949     "\n\t\t: rendering paths producing the same visual result when"
11950     "\n\t\t: possible."
11951     "\n\t\t: Command is intended for testing old hardware compatibility.",
11952     __FILE__, VCaps, group);
11953   theCommands.Add ("vmemgpu",
11954     "vmemgpu [f]: print system-dependent GPU memory information if available;"
11955     " with f option returns free memory in bytes",
11956     __FILE__, VMemGpu, group);
11957   theCommands.Add ("vreadpixel",
11958     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]"
11959     " : Read pixel value for active view",
11960     __FILE__, VReadPixel, group);
11961   theCommands.Add("diffimage",
11962             "diffimage imageFile1 imageFile2 [diffImageFile]"
11963     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
11964     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
11965     "\n\t\t: Compare two images by content and generate difference image."
11966     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
11967     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
11968     __FILE__, VDiffImage, group);
11969   theCommands.Add ("vselect",
11970     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
11971     "- emulates different types of selection:\n"
11972     "- 1) single click selection\n"
11973     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
11974     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
11975     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
11976     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
11977     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
11978     " (partial inclusion - overlap - is not allowed by default)\n"
11979     "- 5) any of these selections with shift button pressed",
11980     __FILE__, VSelect, group);
11981   theCommands.Add ("vmoveto",
11982     "vmoveto x y"
11983     "- emulates cursor movement to pixel postion (x,y)",
11984     __FILE__, VMoveTo, group);
11985   theCommands.Add ("vviewparams",
11986               "vviewparams [-args] [-scale [s]]"
11987       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
11988       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
11989       "\n\t\t: Manage current view parameters or prints all"
11990       "\n\t\t: current values when called without argument."
11991       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
11992       "\n\t\t:   -eye  [x y z] prints or sets eye location"
11993       "\n\t\t:   -at   [x y z] prints or sets center of look"
11994       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
11995       "\n\t\t:   -proj [x y z] prints or sets direction of look"
11996       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
11997       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
11998       "\n\t\t:                 or changes the size of its maximum dimension"
11999       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
12000     __FILE__, VViewParams, group);
12001
12002   theCommands.Add("vanimation", "Alias for vanim",
12003     __FILE__, VAnimation, group);
12004
12005   theCommands.Add("vanim",
12006             "List existing animations:"
12007     "\n\t\t:  vanim"
12008     "\n\t\t: Animation playback:"
12009     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
12010     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
12011     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
12012     "\n\t\t:   -freeLook skip camera animations"
12013     "\n\t\t:   -lockLoop disable any interactions"
12014     "\n\t\t:"
12015     "\n\t\t: Animation definition:"
12016     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
12017     "\n\t\t:        [start TimeSec] [duration TimeSec]"
12018     "\n\t\t:"
12019     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
12020     "\n\t\t: specifies nested animations."
12021     "\n\t\t: There is no syntax to explicitly add new animation,"
12022     "\n\t\t: and all non-existing animations within the name will be"
12023     "\n\t\t: implicitly created on first use (including parents)."
12024     "\n\t\t:"
12025     "\n\t\t: Each animation might define the SINGLE action (see below),"
12026     "\n\t\t: like camera transition, object transformation or custom callback."
12027     "\n\t\t: Child animations can be used for defining concurrent actions."
12028     "\n\t\t:"
12029     "\n\t\t: Camera animation:"
12030     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
12031     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
12032     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
12033     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
12034     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
12035     "\n\t\t:   -atX    camera Center positions pair"
12036     "\n\t\t:   -upX    camera Up directions pair"
12037     "\n\t\t:   -scaleX camera Scale factors pair"
12038     "\n\t\t: Object animation:"
12039     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
12040     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
12041     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
12042     "\n\t\t:   -locX   object Location points pair (translation)"
12043     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
12044     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
12045     "\n\t\t: Custom callback:"
12046     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
12047     "\n\t\t:   %Pts        overall animation presentation timestamp"
12048     "\n\t\t:   %LocalPts   local animation timestamp"
12049     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
12050     "\n\t\t:"
12051     "\n\t\t: Video recording:"
12052     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
12053     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
12054     "\n\t\t:             [-crf Value] [-preset Preset]"
12055     "\n\t\t:   -fps     video framerate"
12056     "\n\t\t:   -format  file format, container (matroska, etc.)"
12057     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
12058     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
12059     "\n\t\t:   -crf     constant rate factor (specific to codec)"
12060     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
12061     __FILE__, VAnimation, group);
12062
12063   theCommands.Add("vchangeselected",
12064     "vchangeselected shape"
12065     "- adds to shape to selection or remove one from it",
12066                 __FILE__, VChangeSelected, group);
12067   theCommands.Add ("vnbselected",
12068     "vnbselected"
12069     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
12070   theCommands.Add ("vcamera",
12071               "vcamera [-ortho] [-projtype]"
12072       "\n\t\t:         [-persp]"
12073       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
12074       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
12075       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
12076       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
12077       "\n\t\t: Manage camera parameters."
12078       "\n\t\t: Prints current value when option called without argument."
12079       "\n\t\t: Orthographic camera:"
12080       "\n\t\t:   -ortho      activate orthographic projection"
12081       "\n\t\t: Perspective camera:"
12082       "\n\t\t:   -persp      activate perspective  projection (mono)"
12083       "\n\t\t:   -fovy       field of view in y axis, in degrees"
12084       "\n\t\t:   -distance   distance of eye from camera center"
12085       "\n\t\t: Stereoscopic camera:"
12086       "\n\t\t:   -stereo     perspective  projection (stereo)"
12087       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
12088       "\n\t\t:   -rightEye   perspective  projection (right eye)"
12089       "\n\t\t:   -iod        intraocular distance value"
12090       "\n\t\t:   -iodType    distance type, absolute or relative"
12091       "\n\t\t:   -zfocus     stereographic focus value"
12092       "\n\t\t:   -zfocusType focus type, absolute or relative",
12093     __FILE__, VCamera, group);
12094   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
12095     "- vautozfit [on={1|0}] [scale]\n"
12096     "    Prints or changes parameters of automatic z-fit mode:\n"
12097     "   \"on\" - turns automatic z-fit on or off\n"
12098     "   \"scale\" - specifies factor to scale computed z range.\n",
12099     __FILE__, VAutoZFit, group);
12100   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
12101     "   vzrange                - without parameters shows current values\n"
12102     "   vzrange [znear] [zfar] - applies provided values to view",
12103     __FILE__,VZRange, group);
12104   theCommands.Add ("vpurgedisplay",
12105     "vpurgedisplay"
12106     "- removes structures which don't belong to objects displayed in neutral point",
12107     __FILE__, VPurgeDisplay, group);
12108   theCommands.Add("vsetviewsize",
12109     "vsetviewsize size",
12110     __FILE__,VSetViewSize,group);
12111   theCommands.Add("vmoveview",
12112     "vmoveview Dx Dy Dz [Start = 1|0]",
12113     __FILE__,VMoveView,group);
12114   theCommands.Add("vtranslateview",
12115     "vtranslateview Dx Dy Dz [Start = 1|0)]",
12116     __FILE__,VTranslateView,group);
12117   theCommands.Add("vturnview",
12118     "vturnview Ax Ay Az [Start = 1|0]",
12119     __FILE__,VTurnView,group);
12120   theCommands.Add("vtextureenv",
12121     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
12122     "or user-defined file and optionally applying texture mapping parameters\n"
12123     "                  Usage:\n"
12124     "                  vtextureenv off - disables environment mapping\n"
12125     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
12126     "                              std_texture = (0..7)\n"
12127     "                              rep         = {clamp|repeat}\n"
12128     "                              mod         = {decal|modulate}\n"
12129     "                              flt         = {nearest|bilinear|trilinear}\n"
12130     "                              ss, st      - scale factors for s and t texture coordinates\n"
12131     "                              ts, tt      - translation for s and t texture coordinates\n"
12132     "                              rot         - texture rotation angle in degrees",
12133     __FILE__, VTextureEnv, group);
12134   theCommands.Add("vhlr",
12135             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
12136       "\n\t\t: Hidden Line Removal algorithm."
12137       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
12138       "\n\t\t:   -algoType   type of HLR algorithm.\n",
12139     __FILE__,VHLR,group);
12140   theCommands.Add("vhlrtype",
12141               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
12142       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
12143       "\n\t\t:   'algo' - exact HLR algorithm is applied"
12144       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
12145       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
12146     __FILE__,VHLRType,group);
12147   theCommands.Add("vclipplane",
12148               "vclipplane planeName [{0|1}]"
12149       "\n\t\t:   [-equation A B C D]"
12150       "\n\t\t:   [-set|-unset [objects|views]]"
12151       "\n\t\t:   [-maxPlanes]"
12152       "\n\t\t:   [-capping {0|1}]"
12153       "\n\t\t:     [-color R G B] [-hatch {on|off|ID}]"
12154       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
12155       "\n\t\t:       [-texRotate Angle]"
12156       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
12157       "\n\t\t:       [-useObjShader {0|1}]"
12158       "\n\t\t: Clipping planes management:"
12159       "\n\t\t:   -maxPlanes   print plane limit for view"
12160       "\n\t\t:   -delete      delete plane with given name"
12161       "\n\t\t:   {off|on|0|1} turn clipping on/off"
12162       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
12163       "\n\t\t:                applied to active View when list is omitted"
12164       "\n\t\t:   -equation A B C D change plane equation"
12165       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
12166       "\n\t\t: Capping options:"
12167       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
12168       "\n\t\t:   -color R G B          set capping color"
12169       "\n\t\t:   -texName Texture      set capping texture"
12170       "\n\t\t:   -texScale SX SY       set capping tex scale"
12171       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
12172       "\n\t\t:   -texRotate Angle      set capping tex rotation"
12173       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
12174       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
12175       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
12176       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
12177       __FILE__, VClipPlane, group);
12178   theCommands.Add("vdefaults",
12179                "vdefaults [-absDefl value]"
12180        "\n\t\t:           [-devCoeff value]"
12181        "\n\t\t:           [-angDefl value]"
12182        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
12183     , __FILE__, VDefaults, group);
12184   theCommands.Add("vlight",
12185     "tool to manage light sources, without arguments shows list of lights."
12186     "\n    Main commands: "
12187     "\n      '-clear' to clear lights"
12188     "\n      '-{def}aults' to load deafault lights"
12189     "\n      '-add' <type> to add any light source"
12190     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
12191     "\n      'change' <lightId> to edit light source with specified lightId"
12192     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
12193     "\n        -layer Id"
12194     "\n        -{pos}ition X Y Z"
12195     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
12196     "\n        -color colorName"
12197     "\n        -{head}light 0|1"
12198     "\n        -{sm}oothness value"
12199     "\n        -{int}ensity value"
12200     "\n        -{constAtten}uation value"
12201     "\n        -{linearAtten}uation value"
12202     "\n        -angle angleDeg"
12203     "\n        -{spotexp}onent value"
12204     "\n        -local|-global"
12205     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
12206     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
12207     __FILE__, VLight, group);
12208   theCommands.Add("vraytrace",
12209             "vraytrace [0|1]"
12210     "\n\t\t: Turns on/off ray-tracing renderer."
12211     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
12212     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
12213     __FILE__, VRenderParams, group);
12214   theCommands.Add("vrenderparams",
12215     "\n    Manages rendering parameters: "
12216     "\n      '-raster'                   Disables GPU ray-tracing"
12217     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
12218     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
12219     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
12220     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
12221     "\n      '-rendScale    value        Rendering resolution scale factor"
12222     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
12223     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
12224     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
12225     "\n      '-reflections  on|off'      Enables/disables specular reflections"
12226     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
12227     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
12228     "\n      '-gi           on|off'      Enables/disables global illumination effects"
12229     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
12230     "\n      '-env          on|off'      Enables/disables environment map background"
12231     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
12232     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
12233     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
12234     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
12235     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles in ISS mode"
12236     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
12237     "\n      '-shadingModel model'       Controls shading model from enumeration"
12238     "\n                                  color, flat, gouraud, phong"
12239     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
12240     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
12241     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
12242     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
12243     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
12244     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
12245     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points|gpuMem|basic|extended|nofps'"
12246     "\n                                  Show/hide performance counters (flags can be combined)"
12247     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
12248     "\n    Unlike vcaps, these parameters dramatically change visual properties."
12249     "\n    Command is intended to control presentation quality depending on"
12250     "\n    hardware capabilities and performance.",
12251     __FILE__, VRenderParams, group);
12252   theCommands.Add("vfrustumculling",
12253     "vfrustumculling [toEnable]: enables/disables objects clipping",
12254     __FILE__,VFrustumCulling,group);
12255   theCommands.Add("vhighlightselected",
12256     "vhighlightselected [0|1] or vhighlightselected [on|off]: enables/disables highlighting of selected objects.\n"
12257     "Without arguments it shows if highlighting of selected objects is enabled now.",
12258     __FILE__,VHighlightSelected,group);
12259   theCommands.Add ("vplace",
12260             "vplace dx dy"
12261     "\n\t\t: Places the point (in pixels) at the center of the window",
12262     __FILE__, VPlace, group);
12263   theCommands.Add("vxrotate",
12264     "vxrotate",
12265     __FILE__,VXRotate,group);
12266
12267     theCommands.Add("vmanipulator",
12268       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
12269       "\n    tool to create and manage AIS manipulators."
12270       "\n    Options: "
12271       "\n      '-attach AISObject'                 attach manipulator to AISObject"
12272       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
12273       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
12274       "\n      '-enableModes    {0|1}'             enable modes when attaching"
12275       "\n      '-detach'                           detach manipulator"
12276       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
12277       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
12278       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
12279       "\n      '-move x y z'                     - move attached object"
12280       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
12281       "\n      '-scale factor'                   - scale attached object"
12282       "\n      '-autoActivate      {0|1}'        - set activation on detection"
12283       "\n      '-followTranslation {0|1}'        - set following translation transform"
12284       "\n      '-followRotation    {0|1}'        - set following rotation transform"
12285       "\n      '-gap value'                      - set gap between sub-parts"
12286       "\n      '-part axis mode    {0|1}'        - set visual part"
12287       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
12288       "\n      '-size value'                     - set size of manipulator"
12289       "\n      '-zoomable {0|1}'                 - set zoom persistence",
12290     __FILE__, VManipulator, group);
12291
12292   theCommands.Add("vselprops",
12293     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
12294     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
12295     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
12296     "\n    -pickStrategy {first|topmost} : defines picking strategy"
12297     "\n                            'first'   to pick first acceptable (default)"
12298     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
12299     "\n    -pixTol    value        : sets up pixel tolerance"
12300     "\n    -dispMode  dispMode     : sets display mode for highlighting"
12301     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
12302     "\n    -color     {name|r g b} : sets highlight color"
12303     "\n    -transp    value        : sets transparency coefficient for highlight"
12304     "\n    -material  material     : sets highlight material"
12305     "\n    -print                  : prints current state of all mentioned parameters",
12306     __FILE__, VSelectionProperties, group);
12307
12308   theCommands.Add ("vseldump",
12309                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
12310                    "\n\t\t: Generate an image based on detection results:"
12311                    "\n\t\t:   depth       normalized depth values"
12312                    "\n\t\t:   unnormDepth unnormalized depth values"
12313                    "\n\t\t:   object      color of detected object"
12314                    "\n\t\t:   owner       color of detected owner"
12315                    "\n\t\t:   selMode     color of selection mode"
12316                    "\n\t\t:   entity      color of etected entity",
12317                    __FILE__, VDumpSelectionImage, group);
12318
12319 #if defined(_WIN32)
12320   theCommands.Add("vprogressive",
12321     "vprogressive",
12322     __FILE__, VProgressiveMode, group);
12323 #endif
12324 }